GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-bb27c0570b
vector/Vlib/close.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/close.c
3 
4  \brief Vector library - Close vector map
5 
6  Higher level functions for reading/writing/manipulating vectors.
7 
8  (C) 2001-2015 by the GRASS Development Team
9 
10  This program is free software under the GNU General Public License
11  (>=v2). Read the file COPYING that comes with GRASS for details.
12 
13  \author Original author CERL, probably Dave Gerdes or Mike Higgins.
14  \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
15  \author Update to GRASS 7 Martin Landa <landa.martin gmail.com>
16  */
17 
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 
25 #include <grass/vector.h>
26 #include <grass/glocale.h>
27 
28 #include "local_proto.h"
29 
30 static int clo_dummy(struct Map_info *map UNUSED)
31 {
32  return -1;
33 }
34 
35 #if !defined HAVE_OGR || !defined HAVE_POSTGRES
36 static int format(struct Map_info *map UNUSED)
37 {
38  G_fatal_error(_("Requested format is not compiled in this version"));
39  return 0;
40 }
41 #endif
42 
43 static int (*Close_array[][2])(struct Map_info *) = {{clo_dummy, V1_close_nat}
44 #ifdef HAVE_OGR
45  ,
46  {clo_dummy, V1_close_ogr},
47  {clo_dummy, V1_close_ogr}
48 #else
49  ,
50  {clo_dummy, format},
51  {clo_dummy, format}
52 #endif
53 #ifdef HAVE_POSTGRES
54  ,
55  {clo_dummy, V1_close_pg}
56 #else
57  ,
58  {clo_dummy, format}
59 #endif
60 };
61 
62 static void unlink_file(struct Map_info *, const char *);
63 
64 /*!
65  \brief Close vector map
66 
67  \param Map pointer to Map_info
68 
69  \return 0 on success
70  \return non-zero on error
71  */
72 int Vect_close(struct Map_info *Map)
73 {
74  int create_link; /* used for external formats only */
75  struct Coor_info CInfo;
76 
77  G_debug(1,
78  "Vect_close(): name = %s, mapset = %s, format = %d, level = %d, "
79  "is_tmp = %d",
80  Map->name, Map->mapset, Map->format, Map->level, Map->temporary);
81 
82  if (Map->temporary && (Map->fInfo.ogr.dsn || Map->fInfo.pg.conninfo)) {
83  /* transfer features for external output format */
84  struct Map_info Out;
85 
86  putenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE=1");
87  if (-1 == Vect_open_new(&Out, Vect_get_name(Map), Vect_is_3d(Map))) {
88  G_warning(_("Unable to create vector map <%s>"),
89  Vect_get_name(Map));
90  return 1;
91  }
92 
93  /* copy metadata */
94  Vect_hist_copy(Map, &Out);
95  Vect_copy_head_data(Map, &Out);
96  /* copy dblinks (temporary map -> output map) to transfer
97  (input map -> output map) attributes */
98  Vect_copy_map_dblinks(Map, &Out, TRUE);
99  /* afterwords, dblinks must be removed from temporary map
100  otherwise when deleting temporary map also original
101  attribute tables would be deteled */
102  Vect_map_del_dblink(Map, -1); /* delete db links for all layers */
103 
104  if (0 != Vect_copy_map_lines_field(
105  Map, 1, &Out)) { /* always layer = 1 for OGR/PG maps */
106  G_warning(_("Copying features failed"));
107  return -1;
108  }
109 
110  Vect_build(&Out);
111 
112  Vect_close(&Out);
113  putenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE="); /* unset variable */
114  }
115 
116  /* check for external formats whether to create a link */
117  create_link = TRUE;
118  if (Map->format == GV_FORMAT_OGR || Map->format == GV_FORMAT_POSTGIS) {
119  char *def_file;
120 
121  if (Map->format == GV_FORMAT_POSTGIS) {
122  if (getenv("GRASS_VECTOR_PGFILE"))
123  def_file = getenv("GRASS_VECTOR_PGFILE");
124  else
125  def_file = "PG";
126  }
127  else {
128  def_file = "OGR";
129  }
130  if (G_find_file2("", def_file, G_mapset())) {
131  FILE *fp;
132  const char *p;
133 
134  struct Key_Value *key_val;
135 
136  fp = G_fopen_old("", def_file, G_mapset());
137  if (!fp) {
138  G_warning(_("Unable to open %s file"), def_file);
139  }
140  else {
141  key_val = G_fread_key_value(fp);
142  fclose(fp);
143 
144  /* create a vector link in the current mapset ? */
145  p = G_find_key_value("link", key_val);
146  if (p && G_strcasecmp(p, "no") == 0) {
147  create_link = FALSE;
148  }
149  else {
150  p = G_find_key_value("link_name", key_val);
151  if (p) {
152  /* use different name for a link */
153  G_free(Map->name);
154  Map->name = G_store(p);
155  }
156  }
157  }
158  }
159  }
160 
161  /* store support files for vector maps in the current mapset if in
162  write mode on level 2 */
163  if (strcmp(Map->mapset, G_mapset()) == 0 && Map->support_updated &&
164  Map->plus.built == GV_BUILD_ALL && create_link) {
165 
166  unlink_file(Map, GV_TOPO_ELEMENT); /* topo */
167 
168  unlink_file(Map, GV_SIDX_ELEMENT); /* sidx */
169 
170  unlink_file(Map, GV_CIDX_ELEMENT); /* cidx */
171 
172  if (Map->format == GV_FORMAT_OGR || Map->format == GV_FORMAT_POSTGIS) {
173  unlink_file(Map, GV_FIDX_ELEMENT); /* fidx */
174  }
175 
176  Vect_coor_info(Map, &CInfo);
177  Map->plus.coor_size = CInfo.size;
178  Map->plus.coor_mtime = CInfo.mtime;
179 
180  /* write out topo file */
181  Vect_save_topo(Map);
182 
183  /* write out sidx file */
184  Map->plus.Spidx_new = TRUE; /* force writing */
185  Vect_save_sidx(Map);
186 
187  /* write out cidx file */
188  Vect_cidx_save(Map);
189 
190  /* write out fidx file */
191  if (Map->format == GV_FORMAT_OGR)
192  V2_close_ogr(Map);
193  else if (Map->format == GV_FORMAT_POSTGIS)
194  V2_close_pg(Map);
195  }
196 
197  /* spatial index must also be closed when opened with topo but not
198  * modified */
199  if (Map->plus.spidx_fp.file && Map->plus.Spidx_built == TRUE &&
200  !Map->support_updated && Map->plus.built == GV_BUILD_ALL) {
201 
202  G_debug(1, "spatial index file closed");
203  fclose(Map->plus.spidx_fp.file);
204  }
205 
206  /* release memory if required */
207  if (Map->level > 1 && Map->plus.release_support) {
208  G_debug(1, "free topology, spatial index, and category index");
209  dig_free_plus(&(Map->plus));
210  }
211 
212  G_debug(1, "close history file");
213  if (Map->hist_fp)
214  fclose(Map->hist_fp);
215 
216  /* close level 1 files / data sources if not head_only */
217  if (!Map->head_only) {
218  if (create_link && ((*Close_array[Map->format][1])(Map)) != 0) {
219  G_warning(_("Unable to close vector <%s>"),
220  Vect_get_full_name(Map));
221  return 1;
222  }
223  }
224 
225  G_free(Map->name);
226  G_free(Map->mapset);
227  G_free(Map->location);
228  G_free(Map->gisdbase);
229 
230  Map->open = VECT_CLOSED_CODE;
231 
232  return 0;
233 }
234 
235 /*!
236  \brief Save format definition file for vector map
237 
238  \param Map pointer to Map_info structure
239 
240  \return 1 on success
241  \return 0 on error
242  */
243 int Vect_save_frmt(struct Map_info *Map)
244 {
245  FILE *fd;
246  char buf[GPATH_MAX];
247 
248  if (Map->format != GV_FORMAT_OGR && Map->format != GV_FORMAT_POSTGIS) {
249  G_warning(_("Invalid request for writing frmt file - map format is %d"),
250  Map->format);
251  return 0;
252  }
253 
254  /* create frmt file */
255  sprintf(buf, "%s/%s", GV_DIRECTORY, Map->name);
256  fd = G_fopen_new(buf, GV_FRMT_ELEMENT);
257  if (fd == NULL) {
258  G_fatal_error("Unable to create file '%s'", buf);
259  }
260 
261  if (Map->format == GV_FORMAT_POSTGIS) {
262 #ifdef HAVE_POSTGRES
263  fprintf(fd, "format: postgis\n");
264  fprintf(fd, "conninfo: %s\n", Map->fInfo.pg.conninfo);
265  fprintf(fd, "schema: %s\n", Map->fInfo.pg.schema_name);
266  fprintf(fd, "table: %s\n", Map->fInfo.pg.table_name);
267 #else
268  G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
269  return 0;
270 #endif
271  }
272  else if (Map->format == GV_FORMAT_OGR) {
273 #ifdef HAVE_OGR
274  fprintf(fd, "format: ogr\n");
275  fprintf(fd, "dsn: %s\n", Map->fInfo.ogr.dsn);
276  fprintf(fd, "layer: %s\n", Map->fInfo.ogr.layer_name);
277 #else
278  G_fatal_error(_("GRASS is not compiled with OGR support"));
279  return 0;
280 #endif
281  }
282 
283  G_verbose_message(_("Link to vector map <%s> created"), Map->name);
284 
285  /* close frmt file */
286  fclose(fd);
287 
288  return 1;
289 }
290 
291 /*! Free memory of line cache
292 
293  \param cache pointer to lines cache to be freed
294  */
296 {
297  int i;
298 
299  /* destroy lines in cache */
300  for (i = 0; i < cache->lines_alloc; i++) {
301  Vect_destroy_line_struct(cache->lines[i]);
302  }
303  G_free(cache->lines);
304  G_free(cache->lines_types);
305  G_free(cache->lines_cats);
306 
307  G_zero(cache, sizeof(struct Format_info_cache));
308 }
309 
310 /*! Free memory of offset array
311 
312  \param cache pointer to offset array to be freed
313  */
315 {
316  G_free(offset->array);
317  G_zero(offset, sizeof(struct Format_info_offset));
318 }
319 
320 void unlink_file(struct Map_info *Map, const char *name)
321 {
322  char path[GPATH_MAX];
323 
324  /* delete old support files if available */
326  if (access(path, F_OK) == 0) { /* file exists? */
327  G_debug(2, "\t%s: unlink", path);
328  unlink(path);
329  }
330 }
#define NULL
Definition: ccmath.h:32
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:251
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
const char * G_find_file2(const char *, const char *, const char *)
Searches for a file from the mapset search list or in a specified mapset. (look but don't touch)
Definition: find_file.c:234
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
Definition: key_value1.c:85
void void G_verbose_message(const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
struct Key_Value * G_fread_key_value(FILE *)
Read key/values pairs from file.
Definition: key_value2.c:49
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition: strings.c:47
int G_debug(int, const char *,...) __attribute__((format(printf
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition: gis/open.c:219
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition: line.c:77
int Vect_cidx_save(struct Map_info *)
Save category index to binary file (cidx)
Definition: Vlib/cindex.c:478
int Vect_coor_info(struct Map_info *, struct Coor_info *)
Update Coor_info structure.
int Vect_open_new(struct Map_info *, const char *, int)
Create new vector map for reading/writing.
int Vect_map_del_dblink(struct Map_info *, int)
Delete db connection from Map_info structure.
Definition: field.c:160
const char * Vect_get_full_name(struct Map_info *)
Get fully qualified name of vector map.
int Vect_copy_map_lines_field(struct Map_info *, int, struct Map_info *)
Copy all alive vector features from given layer from input vector map to output vector map.
int V2_close_pg(struct Map_info *)
int V1_close_nat(struct Map_info *)
Close vector map.
Definition: close_nat.c:34
int Vect_save_topo(struct Map_info *)
Save topology file for vector map.
Definition: build.c:1012
int Vect_save_sidx(struct Map_info *)
Save spatial index file for vector map.
Definition: build.c:1261
int Vect_copy_head_data(struct Map_info *, struct Map_info *)
Copy header data from one to another map.
Definition: init_head.c:77
int Vect_hist_copy(struct Map_info *, struct Map_info *)
Copy history from one map to another.
Definition: hist.c:131
void Vect_copy_map_dblinks(struct Map_info *, struct Map_info *, int)
Copy DB links from input vector map to output vector map.
Definition: field.c:205
int Vect_build(struct Map_info *)
Build topology for vector map.
Definition: build.c:586
int V1_close_ogr(struct Map_info *)
Close vector map (OGR dsn & layer) on level 1.
Definition: close_ogr.c:35
int V1_close_pg(struct Map_info *)
const char * Vect_get_name(struct Map_info *)
Get name of vector map.
int V2_close_ogr(struct Map_info *)
Close vector map on topological level (write out fidx file)
Definition: close_ogr.c:90
int Vect_is_3d(struct Map_info *)
Check if vector map is 3D.
#define VECT_CLOSED_CODE
Vector map close code.
Definition: dig_defines.h:113
#define GV_FRMT_ELEMENT
Format description, data location (OGR)
Definition: dig_defines.h:10
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition: dig_defines.h:89
#define GV_DIRECTORY
Name of vector directory.
Definition: dig_defines.h:8
#define GV_SIDX_ELEMENT
Native format, spatial index.
Definition: dig_defines.h:22
#define GV_BUILD_ALL
Topology levels - build everything (currently same as GV_BUILD_CENTROIDS)
Definition: dig_defines.h:134
#define GV_FIDX_ELEMENT
External format (OGR), feature index.
Definition: dig_defines.h:26
#define GV_CIDX_ELEMENT
Native format, category index.
Definition: dig_defines.h:24
#define GV_TOPO_ELEMENT
Native format, topology file.
Definition: dig_defines.h:20
#define GV_FORMAT_OGR
OGR format.
Definition: dig_defines.h:85
void dig_free_plus(struct Plus_head *)
Free Plus structure.
Definition: plus.c:173
#define GPATH_MAX
Definition: gis.h:194
#define TRUE
Definition: gis.h:79
#define FALSE
Definition: gis.h:83
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition: gis.h:47
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
Coor file info.
Definition: dig_structs.h:371
off_t size
Total size (in bytes)
Definition: dig_structs.h:375
long mtime
Time of last modification.
Definition: dig_structs.h:379
Lines cache for reading feature (non-native formats)
Definition: dig_structs.h:450
int * lines_types
List of line types (GV_POINT, GV_LINE, ...)
Definition: dig_structs.h:466
struct line_pnts ** lines
Lines array.
Definition: dig_structs.h:462
int lines_alloc
Number of allocated lines in cache.
Definition: dig_structs.h:474
int * lines_cats
List of line cats (used only for PostGIS Topology access)
Definition: dig_structs.h:470
Data structure used for building pseudo-topology.
Definition: dig_structs.h:388
int * array
Offset list.
Definition: dig_structs.h:436
char * dsn
OGR datasource name.
Definition: dig_structs.h:513
char * layer_name
OGR layer name.
Definition: dig_structs.h:517
char * schema_name
Schema name.
Definition: dig_structs.h:602
char * conninfo
Connection string.
Definition: dig_structs.h:594
char * table_name
Table name.
Definition: dig_structs.h:606
struct Format_info_pg pg
PostGIS info.
Definition: dig_structs.h:712
struct Format_info_ogr ogr
OGR info.
Definition: dig_structs.h:708
Definition: gis.h:525
Vector map info.
Definition: dig_structs.h:1243
char * mapset
Mapset name.
Definition: dig_structs.h:1320
int temporary
Temporary map flag.
Definition: dig_structs.h:1260
int support_updated
Support files were updated.
Definition: dig_structs.h:1311
char * gisdbase
GISDBASE path.
Definition: dig_structs.h:1331
int level
Topology level.
Definition: dig_structs.h:1297
char * name
Map name (for 4.0)
Definition: dig_structs.h:1316
FILE * hist_fp
History file.
Definition: dig_structs.h:1378
int open
Open indicator.
Definition: dig_structs.h:1280
char * location
Location name.
Definition: dig_structs.h:1327
int head_only
Open only header.
Definition: dig_structs.h:1304
int format
Map format (native, ogr, postgis)
Definition: dig_structs.h:1255
struct Format_info fInfo
Format info for non-native formats.
Definition: dig_structs.h:1400
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1270
struct gvfile spidx_fp
Spatial index file pointer.
Definition: dig_structs.h:1054
int Spidx_built
Spatial index built?
Definition: dig_structs.h:1037
off_t coor_size
Size of coor file.
Definition: dig_structs.h:1145
int Spidx_new
Build new spatial index.
Definition: dig_structs.h:1043
int release_support
Release memory occupied by support structures (topo, spatial, category)
Definition: dig_structs.h:822
long coor_mtime
Time of last coor modification.
Definition: dig_structs.h:1149
int built
Highest level of topology currently available.
Definition: dig_structs.h:857
FILE * file
File descriptor.
Definition: dig_structs.h:98
Definition: path.h:15
int Vect_close(struct Map_info *Map)
Close vector map.
void Vect__free_offset(struct Format_info_offset *offset)
int Vect_save_frmt(struct Map_info *Map)
Save format definition file for vector map.
void Vect__free_cache(struct Format_info_cache *cache)
char * Vect__get_element_path(char *file_path, struct Map_info *Map, const char *element)
Get map element full path (internal use only)