GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
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()
31 {
32  return -1;
33 }
34 
35 #if !defined HAVE_OGR || !defined HAVE_POSTGRES
36 static int format()
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]) () = {
44  {
45  clo_dummy, V1_close_nat}
46 #ifdef HAVE_OGR
47  , {
48  clo_dummy, V1_close_ogr}
49  , {
50  clo_dummy, V1_close_ogr}
51 #else
52  , {
53  clo_dummy, format}
54  , {
55  clo_dummy, format}
56 #endif
57 #ifdef HAVE_POSTGRES
58  , {
59  clo_dummy, V1_close_pg}
60 #else
61  , {
62  clo_dummy, format}
63 #endif
64 };
65 
66 static void unlink_file(const struct Map_info *, const char *);
67 
68 /*!
69  \brief Close vector map
70 
71  \param Map pointer to Map_info
72 
73  \return 0 on success
74  \return non-zero on error
75  */
76 int Vect_close(struct Map_info *Map)
77 {
78  int create_link; /* used for external formats only */
79  struct Coor_info CInfo;
80 
81  G_debug(1, "Vect_close(): name = %s, mapset = %s, format = %d, level = %d, is_tmp = %d",
82  Map->name, Map->mapset, Map->format, Map->level, Map->temporary);
83 
84  if (Map->temporary &&
85  (Map->fInfo.ogr.dsn || Map->fInfo.pg.conninfo)) {
86  /* transfer features for external output format */
87  struct Map_info Out;
88 
89  putenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE=1");
90  if (-1 == Vect_open_new(&Out, Vect_get_name(Map), Vect_is_3d(Map))) {
91  G_warning(_("Unable to create vector map <%s>"),
92  Vect_get_name(Map));
93  return 1;
94  }
95 
96  /* copy metadata */
97  Vect_hist_copy(Map, &Out);
98  Vect_copy_head_data(Map, &Out);
99  /* copy dblinks (temporary map -> output map) to transfer
100  (input map -> output map) attributes */
101  Vect_copy_map_dblinks(Map, &Out, TRUE);
102  /* afterwords, dblinks must be removed from temporary map
103  otherwise when deleting temporary map also original
104  attribute tables would be deteled */
105  Vect_map_del_dblink(Map, -1); /* delete db links for all layers */
106 
107  if (0 != Vect_copy_map_lines_field(Map, 1, &Out)) { /* always layer = 1 for OGR/PG maps */
108  G_warning(_("Copying features failed"));
109  return -1;
110  }
111 
112  Vect_build(&Out);
113 
114  Vect_close(&Out);
115  putenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE="); /* unset variable */
116  }
117 
118  /* check for external formats whether to create a link */
119  create_link = TRUE;
120  if (Map->format == GV_FORMAT_OGR ||
121  Map->format == GV_FORMAT_POSTGIS) {
122  char *def_file;
123 
124  if (Map->format == GV_FORMAT_POSTGIS) {
125  if (getenv("GRASS_VECTOR_PGFILE"))
126  def_file = getenv("GRASS_VECTOR_PGFILE");
127  else
128  def_file = "PG";
129  }
130  else {
131  def_file = "OGR";
132  }
133  if (G_find_file2("", def_file, G_mapset())) {
134  FILE *fp;
135  const char *p;
136 
137  struct Key_Value *key_val;
138 
139  fp = G_fopen_old("", def_file, G_mapset());
140  if (!fp) {
141  G_warning(_("Unable to open %s file"), def_file);
142  }
143  else {
144  key_val = G_fread_key_value(fp);
145  fclose(fp);
146 
147  /* create a vector link in the current mapset ? */
148  p = G_find_key_value("link", key_val);
149  if (p && G_strcasecmp(p, "no") == 0) {
150  create_link = FALSE;
151  }
152  else {
153  p = G_find_key_value("link_name", key_val);
154  if (p) {
155  /* use different name for a link */
156  G_free(Map->name);
157  Map->name = G_store(p);
158  }
159  }
160  }
161  }
162  }
163 
164  /* store support files for vector maps in the current mapset if in
165  write mode on level 2 */
166  if (strcmp(Map->mapset, G_mapset()) == 0 &&
167  Map->support_updated &&
168  Map->plus.built == GV_BUILD_ALL &&
169  create_link) {
170 
171  unlink_file(Map, GV_TOPO_ELEMENT); /* topo */
172 
173  unlink_file(Map, GV_SIDX_ELEMENT); /* sidx */
174 
175  unlink_file(Map, GV_CIDX_ELEMENT); /* cidx */
176 
177  if (Map->format == GV_FORMAT_OGR || Map->format == GV_FORMAT_POSTGIS) {
178  unlink_file(Map, GV_FIDX_ELEMENT); /* fidx */
179  }
180 
181  Vect_coor_info(Map, &CInfo);
182  Map->plus.coor_size = CInfo.size;
183  Map->plus.coor_mtime = CInfo.mtime;
184 
185  /* write out topo file */
186  Vect_save_topo(Map);
187 
188  /* write out sidx file */
189  Map->plus.Spidx_new = TRUE; /* force writing */
190  Vect_save_sidx(Map);
191 
192  /* write out cidx file */
193  Vect_cidx_save(Map);
194 
195  /* write out fidx file */
196  if (Map->format == GV_FORMAT_OGR)
197  V2_close_ogr(Map);
198  else if (Map->format == GV_FORMAT_POSTGIS)
199  V2_close_pg(Map);
200  }
201 
202  /* spatial index must also be closed when opened with topo but not
203  * modified */
204  if (Map->plus.spidx_fp.file &&
205  Map->plus.Spidx_built == TRUE &&
206  !Map->support_updated &&
207  Map->plus.built == GV_BUILD_ALL) {
208 
209  G_debug(1, "spatial index file closed");
210  fclose(Map->plus.spidx_fp.file);
211  }
212 
213  /* release memory if required */
214  if (Map->level > 1 && Map->plus.release_support) {
215  G_debug(1, "free topology, spatial index, and category index");
216  dig_free_plus(&(Map->plus));
217  }
218 
219  G_debug(1, "close history file");
220  if (Map->hist_fp)
221  fclose(Map->hist_fp);
222 
223  /* close level 1 files / data sources if not head_only */
224  if (!Map->head_only) {
225  if (create_link && ((*Close_array[Map->format][1]) (Map)) != 0) {
226  G_warning(_("Unable to close vector <%s>"),
227  Vect_get_full_name(Map));
228  return 1;
229  }
230  }
231 
232  G_free(Map->name);
233  G_free(Map->mapset);
234  G_free(Map->location);
235  G_free(Map->gisdbase);
236 
237  Map->open = VECT_CLOSED_CODE;
238 
239  return 0;
240 }
241 
242 /*!
243  \brief Save format definition file for vector map
244 
245  \param Map pointer to Map_info structure
246 
247  \return 1 on success
248  \return 0 on error
249  */
250 int Vect_save_frmt(struct Map_info *Map)
251 {
252  FILE *fd;
253  char buf[GPATH_MAX];
254 
255  if (Map->format != GV_FORMAT_OGR &&
256  Map->format != GV_FORMAT_POSTGIS) {
257  G_warning(_("Invalid request for writing frmt file - map format is %d"), Map->format);
258  return 0;
259  }
260 
261  /* create frmt file */
262  sprintf(buf, "%s/%s", GV_DIRECTORY, Map->name);
263  fd = G_fopen_new(buf, GV_FRMT_ELEMENT);
264  if (fd == NULL) {
265  G_fatal_error("Unable to create file '%s'", buf);
266  }
267 
268  if (Map->format == GV_FORMAT_POSTGIS) {
269 #ifdef HAVE_POSTGRES
270  fprintf(fd, "format: postgis\n");
271  fprintf(fd, "conninfo: %s\n", Map->fInfo.pg.conninfo);
272  fprintf(fd, "schema: %s\n", Map->fInfo.pg.schema_name);
273  fprintf(fd, "table: %s\n", Map->fInfo.pg.table_name);
274 #else
275  G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
276  return 0;
277 #endif
278  } else if (Map->format == GV_FORMAT_OGR) {
279 #ifdef HAVE_OGR
280  fprintf(fd, "format: ogr\n");
281  fprintf(fd, "dsn: %s\n", Map->fInfo.ogr.dsn);
282  fprintf(fd, "layer: %s\n", Map->fInfo.ogr.layer_name);
283 #else
284  G_fatal_error(_("GRASS is not compiled with OGR support"));
285  return 0;
286 #endif
287  }
288 
289  G_verbose_message(_("Link to vector map <%s> created"), Map->name);
290 
291  /* close frmt file */
292  fclose(fd);
293 
294  return 1;
295 }
296 
297 /*! Free memory of line cache
298 
299  \param cache pointer to lines cache to be freed
300 */
301 void Vect__free_cache(struct Format_info_cache *cache) {
302  int i;
303  /* destroy lines in cache */
304  for (i = 0; i < cache->lines_alloc; i++) {
305  Vect_destroy_line_struct(cache->lines[i]);
306  }
307  G_free(cache->lines);
308  G_free(cache->lines_types);
309  G_free(cache->lines_cats);
310 
311  G_zero(cache, sizeof(struct Format_info_cache));
312 }
313 
314 /*! Free memory of offset array
315 
316  \param cache pointer to offset array to be freed
317 */
319 {
320  G_free(offset->array);
321  G_zero(offset, sizeof(struct Format_info_offset));
322 }
323 
324 void unlink_file(const struct Map_info *Map, const char *name)
325 {
326  char path[GPATH_MAX];
327 
328  /* delete old support files if available */
329  Vect__get_element_path(path, Map, name);
330  if (access(path, F_OK) == 0) { /* file exists? */
331  G_debug(2, "\t%s: unlink", path);
332  unlink(path);
333  }
334 }
int Vect_open_new(struct Map_info *, const char *, int)
Create new vector map for reading/writing.
int Vect_save_frmt(struct Map_info *Map)
Save format definition file for vector map.
int * array
Offset list.
Definition: dig_structs.h:446
int Spidx_new
Build new spatial index.
Definition: dig_structs.h:1059
#define TRUE
Definition: gis.h:59
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&#39;t touch) ...
Definition: find_file.c:249
char * name
Map name (for 4.0)
Definition: dig_structs.h:1332
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
off_t coor_size
Size of coor file.
Definition: dig_structs.h:1161
int built
Highest level of topology currently available.
Definition: dig_structs.h:873
int open
Open indicator.
Definition: dig_structs.h:1296
char * Vect__get_element_path(char *file_path, const struct Map_info *Map, const char *element)
Get map element full path (internal use only)
#define GV_DIRECTORY
Name of vector directory.
Definition: dig_defines.h:8
#define GV_FRMT_ELEMENT
Format description, data location (OGR)
Definition: dig_defines.h:10
off_t size
Total size (in bytes)
Definition: dig_structs.h:384
struct Key_Value * G_fread_key_value(FILE *)
Read key/values pairs from file.
Definition: key_value2.c:49
int release_support
Release memory occupied by support structures (topo, spatial, category)
Definition: dig_structs.h:838
void Vect__free_cache(struct Format_info_cache *cache)
int Vect_close(struct Map_info *Map)
Close vector map.
#define GV_FORMAT_OGR
OGR format.
Definition: dig_defines.h:85
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 Vect_copy_head_data(const struct Map_info *, struct Map_info *)
Copy header data from one to another map.
Definition: init_head.c:77
char * location
Location name.
Definition: dig_structs.h:1342
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
#define GV_TOPO_ELEMENT
Native format, topology file.
Definition: dig_defines.h:20
int * lines_cats
List of line cats (used only for PostGIS Topology access)
Definition: dig_structs.h:481
char * dsn
OGR datasource name.
Definition: dig_structs.h:525
struct Format_info fInfo
Format info for non-native formats.
Definition: dig_structs.h:1415
long mtime
Time of last modification.
Definition: dig_structs.h:388
int Vect_save_sidx(struct Map_info *)
Save spatial index file for vector map.
Definition: build.c:1247
int level
Topology level.
Definition: dig_structs.h:1313
char * table_name
Table name.
Definition: dig_structs.h:619
#define NULL
Definition: ccmath.h:32
void dig_free_plus(struct Plus_head *)
Free Plus structure.
Definition: plus.c:174
int Spidx_built
Spatial index built?
Definition: dig_structs.h:1053
#define VECT_CLOSED_CODE
Vector map close code.
Definition: dig_defines.h:113
int Vect_hist_copy(const struct Map_info *, struct Map_info *)
Copy history from one map to another.
Definition: hist.c:131
int V2_close_ogr(struct Map_info *)
Close vector map on topological level (write out fidx file)
Definition: close_ogr.c:90
struct gvfile spidx_fp
Spatial index file pointer.
Definition: dig_structs.h:1070
void Vect__free_offset(struct Format_info_offset *offset)
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition: strings.c:47
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition: gis/open.c:220
#define GV_CIDX_ELEMENT
Native format, category index.
Definition: dig_defines.h:24
Data structure used for building pseudo-topology.
Definition: dig_structs.h:397
int Vect_build(struct Map_info *)
Build topology for vector map.
Definition: build.c:576
#define FALSE
Definition: gis.h:63
int lines_alloc
Number of allocated lines in cache.
Definition: dig_structs.h:485
struct Format_info_pg pg
PostGIS info.
Definition: dig_structs.h:726
int V1_close_ogr(struct Map_info *)
Close vector map (OGR dsn & layer) on level 1.
Definition: close_ogr.c:35
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1286
int Vect_map_del_dblink(struct Map_info *, int)
Delete db connection from Map_info structure.
Definition: field.c:153
struct Format_info_ogr ogr
OGR info.
Definition: dig_structs.h:722
#define GPATH_MAX
Definition: gis.h:180
int V1_close_nat(struct Map_info *)
Close vector map.
Definition: close_nat.c:34
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:253
int Vect_cidx_save(struct Map_info *)
Save category index to binary file (cidx)
Definition: Vlib/cindex.c:475
Lines cache for reading feature (non-native formats)
Definition: dig_structs.h:461
char * mapset
Mapset name.
Definition: dig_structs.h:1336
int head_only
Open only header.
Definition: dig_structs.h:1320
Definition: gis.h:512
int * lines_types
List of line types (GV_POINT, GV_LINE, ...)
Definition: dig_structs.h:477
int support_updated
Support files were updated.
Definition: dig_structs.h:1327
Vector map info.
Definition: dig_structs.h:1259
long coor_mtime
Time of last coor modification.
Definition: dig_structs.h:1165
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition: dig_defines.h:89
char * layer_name
OGR layer name.
Definition: dig_structs.h:529
FILE * file
File descriptor.
Definition: dig_structs.h:101
int Vect_is_3d(const struct Map_info *)
Check if vector map is 3D.
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
int temporary
Temporary map flag.
Definition: dig_structs.h:1276
const char * Vect_get_full_name(const struct Map_info *)
Get fully qualified name of vector map.
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
char * conninfo
Connection string.
Definition: dig_structs.h:607
int Vect_save_topo(struct Map_info *)
Save topology file for vector map.
Definition: build.c:999
void G_warning(const char *,...) __attribute__((format(printf
Coor file info.
Definition: dig_structs.h:379
Definition: path.h:16
struct line_pnts ** lines
Lines array.
Definition: dig_structs.h:473
#define _(str)
Definition: glocale.h:10
int format
Map format (native, ogr, postgis)
Definition: dig_structs.h:1271
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
#define GV_BUILD_ALL
Topology levels - build everything (currently same as GV_BUILD_CENTROIDS)
Definition: dig_defines.h:133
#define GV_FIDX_ELEMENT
External format (OGR), feature index.
Definition: dig_defines.h:26
#define GV_SIDX_ELEMENT
Native format, spatial index.
Definition: dig_defines.h:22
int V2_close_pg(struct Map_info *)
Close vector map (PostGIS layer) on topological level (write out fidx file)
Definition: close_pg.c:112
const char * name
Definition: named_colr.c:7
void Vect_copy_map_dblinks(const struct Map_info *, struct Map_info *, int)
Copy DB links from input vector map to output vector map.
Definition: field.c:197
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
char * schema_name
Schema name.
Definition: dig_structs.h:615
char * getenv()
void void G_verbose_message(const char *,...) __attribute__((format(printf
int Vect_coor_info(const struct Map_info *, struct Coor_info *)
Update Coor_info structure.
const char * Vect_get_name(const struct Map_info *)
Get name of vector map.
int G_debug(int, const char *,...) __attribute__((format(printf
int V1_close_pg(struct Map_info *)
Close vector map (PostGIS layer) on level 1.
Definition: close_pg.c:36
char * gisdbase
GISDBASE path.
Definition: dig_structs.h:1346
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
Definition: key_value1.c:84
FILE * hist_fp
History file.
Definition: dig_structs.h:1393