GRASS Programmer's Manual  6.4.3(2013)-r
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
closecell.c
Go to the documentation of this file.
1 
2 /***********************************************************************
3  *
4  * G_close_cell(fd)
5  * Closes and does housekeeping on an opened cell file
6  *
7  * G_unopen_cell(fd)
8  * Closes and does housekeeping on an opened cell file
9  * without creating the cell file
10  *
11  * parms:
12  * int fd open cell file
13  *
14  * returns:
15  * -1 on fail
16  * 0 on success
17  *
18  * note:
19  * On closing of a cell file that was open for writing, dummy cats
20  * and history files are created. Histogram and range info are written.
21  *
22  **********************************************************************/
23 
24 #ifdef __MINGW32__
25 # include <windows.h>
26 #endif
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <signal.h>
34 #include <grass/gis.h>
35 #include <grass/glocale.h>
36 #include "G.h"
37 
38 #define FORMAT_FILE "f_format"
39 #define QUANT_FILE "f_quant"
40 #define NULL_FILE "null"
41 
42 static int close_old(int);
43 static int close_new(int, int);
44 static char CELL_DIR[100];
45 
46 
79 int G_close_cell(int fd)
80 {
81  struct fileinfo *fcb = &G__.fileinfo[fd];
82 
83  if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0)
84  return -1;
85  if (fcb->open_mode == OPEN_OLD)
86  return close_old(fd);
87 
88  return close_new(fd, 1);
89 }
90 
91 
113 {
114  struct fileinfo *fcb = &G__.fileinfo[fd];
115 
116  if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0)
117  return -1;
118  if (fcb->open_mode == OPEN_OLD)
119  return close_old(fd);
120  else
121  return close_new(fd, 0);
122 }
123 
124 static int close_old(int fd)
125 {
126  struct fileinfo *fcb = &G__.fileinfo[fd];
127  int i;
128 
129  /* if G__.auto_mask was only allocated for reading map rows to create
130  non-existant null rows, and not for actuall mask, free G__.mask_row
131  if(G__.auto_mask <=0)
132  G_free (G__.mask_buf);
133  This is obsolete since now the mask_bus is always allocated
134  */
135 
136  if (fcb->gdal)
137  G_close_gdal_link(fcb->gdal);
138 
139  for (i = 0; i < NULL_ROWS_INMEM; i++)
140  G_free(fcb->NULL_ROWS[i]);
141  G_free(fcb->null_work_buf);
142 
143  if (fcb->cellhd.compressed)
144  G_free(fcb->row_ptr);
145  G_free(fcb->col_map);
146  G_free(fcb->mapset);
147  G_free(fcb->data);
148  G_free(fcb->name);
149  if (fcb->reclass_flag)
150  G_free_reclass(&fcb->reclass);
151  fcb->open_mode = -1;
152 
153  if (fcb->map_type != CELL_TYPE) {
154  G_quant_free(&fcb->quant);
155  xdr_destroy(&fcb->xdrstream);
156  }
157  close(fd);
158 
159  return 1;
160 }
161 
162 static int close_new(int fd, int ok)
163 {
164  struct fileinfo *fcb = &G__.fileinfo[fd];
165  int stat;
166  struct Categories cats;
167  struct History hist;
168  char path[GPATH_MAX];
169  CELL cell_min, cell_max;
170  int row, i, open_mode;
171 
172  if (ok) {
173  switch (fcb->open_mode) {
174  case OPEN_NEW_COMPRESSED:
175  G_debug(1, "close %s compressed", fcb->name);
176  break;
178  G_debug(1, "close %s uncompressed", fcb->name);
179  break;
180  case OPEN_NEW_RANDOM:
181  G_debug(1, "close %s random", fcb->name);
182  break;
183  }
184 
185  if (fcb->open_mode != OPEN_NEW_RANDOM &&
186  fcb->cur_row < fcb->cellhd.rows) {
187  G_zero_raster_buf(fcb->data, fcb->map_type);
188  for (row = fcb->cur_row; row < fcb->cellhd.rows; row++)
189  G_put_raster_row(fd, fcb->data, fcb->map_type);
190  G_free(fcb->data);
191  fcb->data = NULL;
192  }
193 
194  /* create path : full null file name */
195  G__make_mapset_element_misc("cell_misc", fcb->name);
196  G__file_name_misc(path, "cell_misc", NULL_FILE, fcb->name,
197  G_mapset());
198  remove(path);
199 
200  if (fcb->null_cur_row > 0) {
201  /* if temporary NULL file exists, write it into cell_misc/name/null */
202  int null_fd;
203 
204  null_fd = G__open_null_write(fd);
205  if (null_fd <= 0)
206  return -1;
207  if (null_fd < 1)
208  return -1;
209 
210  /* first finish writing null file */
211  /* write out the rows stored in memory */
212  for (row = fcb->min_null_row; row < fcb->null_cur_row; row++)
213  G__write_null_bits(null_fd,
214  fcb->NULL_ROWS[row - fcb->min_null_row],
215  row, fcb->cellhd.cols, fd);
216 
217  /* write missing rows */
218  if (fcb->open_mode != OPEN_NEW_RANDOM
219  && fcb->null_cur_row < fcb->cellhd.rows) {
220  G__init_null_bits(fcb->null_work_buf, fcb->cellhd.cols);
221  for (row = fcb->null_cur_row; row < fcb->cellhd.rows; row++)
222  G__write_null_bits(null_fd, fcb->null_work_buf, row,
223  fcb->cellhd.cols, fd);
224  }
225  close(null_fd);
226 
227  if (rename(fcb->null_temp_name, path)) {
228  G_warning(_("closecell: can't move %s\nto null file %s"),
229  fcb->null_temp_name, path);
230  stat = -1;
231  }
232  else {
233  remove(fcb->null_temp_name);
234  }
235  }
236  else {
237  remove(fcb->null_temp_name);
238  remove(path);
239  } /* null_cur_row > 0 */
240 
241  if (fcb->open_mode == OPEN_NEW_COMPRESSED) { /* auto compression */
242  fcb->row_ptr[fcb->cellhd.rows] = lseek(fd, 0L, SEEK_CUR);
243  G__write_row_ptrs(fd);
244  }
245 
246  if (fcb->map_type != CELL_TYPE) { /* floating point map */
247  int cell_fd;
248 
249  if (G__write_fp_format(fd) != 0) {
250  G_warning(_("Error writing floating point format file for map %s"),
251  fcb->name);
252  stat = -1;
253  }
254 
255  /* now write 0-length cell file */
256  G__make_mapset_element("cell");
257  cell_fd =
258  creat(G__file_name(path, "cell", fcb->name, fcb->mapset),
259  0666);
260  close(cell_fd);
261  strcpy(CELL_DIR, "fcell");
262  }
263  else {
264  /* remove fcell/name file */
265  G__file_name(path, "fcell", fcb->name, fcb->mapset);
266  remove(path);
267  /* remove cell_misc/name/f_format */
268  G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name,
269  fcb->mapset);
270  remove(path);
271  strcpy(CELL_DIR, "cell");
272  close(fd);
273  }
274  } /* ok */
275  /* NOW CLOSE THE FILE DESCRIPTOR */
276 
277  close(fd);
278  /* remember open_mode */
279  open_mode = fcb->open_mode;
280  fcb->open_mode = -1;
281 
282  if (fcb->data != NULL)
283  G_free(fcb->data);
284 
285  if (fcb->null_temp_name != NULL) {
286  G_free(fcb->null_temp_name);
287  fcb->null_temp_name = NULL;
288  }
289 
290  /* if the cell file was written to a temporary file
291  * move this temporary file into the cell file
292  * if the move fails, tell the user, but go ahead and create
293  * the support files
294  */
295  stat = 1;
296  if (ok && (fcb->temp_name != NULL)) {
297  G__file_name(path, CELL_DIR, fcb->name, fcb->mapset);
298  remove(path);
299  if (rename(fcb->temp_name, path)) {
300  G_warning(_("closecell: can't move %s\nto cell file %s"),
301  fcb->temp_name, path);
302  stat = -1;
303  }
304  else {
305  remove(fcb->temp_name);
306  }
307  }
308 
309  if (fcb->temp_name != NULL) {
310  G_free(fcb->temp_name);
311  }
312 
313  if (ok) {
314  /* remove color table */
315  G_remove_colors(fcb->name, "");
316 
317  /* create a history file */
318  G_short_history(fcb->name, "raster", &hist);
319  G_write_history(fcb->name, &hist);
320 
321  /* write the range */
322  if (fcb->map_type == CELL_TYPE) {
323  G_write_range(fcb->name, &fcb->range);
324  G__remove_fp_range(fcb->name);
325  }
326  /*NOTE: int range for floating point maps is not written out */
327  else { /* if(fcb->map_type != CELL_TYPE) */
328 
329  G_write_fp_range(fcb->name, &fcb->fp_range);
331  /* this range will be used to add default rule to quant structure */
332  }
333 
334  if (fcb->map_type != CELL_TYPE)
335  fcb->cellhd.format = -1;
336  else /* CELL map */
337  fcb->cellhd.format = fcb->nbytes - 1;
338 
339  /* write header file */
340  G_put_cellhd(fcb->name, &fcb->cellhd);
341 
342  /* if map is floating point write the quant rules, otherwise remove f_quant */
343  if (fcb->map_type != CELL_TYPE) {
344  /* DEFAULT RANGE QUANT
345  G_get_fp_range_min_max(&fcb->fp_range, &dcell_min, &dcell_max);
346  if(!G_is_d_null_value(&dcell_min) && !G_is_d_null_value(&dcell_max))
347  {
348  G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
349  G_quant_add_rule(&fcb->quant, dcell_min, dcell_max,
350  cell_min, cell_max);
351  }
352  */
353  G_quant_round(&fcb->quant);
354  if (G_write_quant(fcb->name, fcb->mapset, &fcb->quant) < 0)
355  G_warning(_("unable to write quant file!"));
356  }
357  else {
358  /* remove cell_misc/name/f_quant */
359  G__file_name_misc(path, "cell_misc", QUANT_FILE, fcb->name,
360  fcb->mapset);
361  remove(path);
362  }
363 
364  /* create empty cats file */
365  G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
366  if (G_is_c_null_value(&cell_max))
367  cell_max = 0;
368  G_init_cats(cell_max, (char *)NULL, &cats);
369  G_write_cats(fcb->name, &cats);
370  G_free_cats(&cats);
371 
372  /* write the histogram */
373  /* only works for integer maps */
374  if ((fcb->map_type == CELL_TYPE)
375  && (fcb->want_histogram)) {
376  G_write_histogram_cs(fcb->name, &fcb->statf);
377  G_free_cell_stats(&fcb->statf);
378  }
379  else {
380  G_remove_histogram(fcb->name);
381  }
382  } /* OK */
383 
384  G_free(fcb->name);
385  G_free(fcb->mapset);
386 
387  for (i = 0; i < NULL_ROWS_INMEM; i++)
388  G_free(fcb->NULL_ROWS[i]);
389  G_free(fcb->null_work_buf);
390 
391  if (fcb->map_type != CELL_TYPE)
392  G_quant_free(&fcb->quant);
393 
394  return stat;
395 }
396 
397 /* returns 0 on success, 1 on failure */
399 {
400  struct fileinfo *fcb = &G__.fileinfo[fd];
401  struct Key_Value *format_kv;
402  char path[GPATH_MAX];
403  int stat;
404 
405  if (fcb->map_type == CELL_TYPE) {
406  G_warning(_("unable to write f_format file for CELL maps"));
407  return 0;
408  }
409  format_kv = G_create_key_value();
410  if (fcb->map_type == FCELL_TYPE)
411  G_set_key_value("type", "float", format_kv);
412  else
413  G_set_key_value("type", "double", format_kv);
414 
415  G_set_key_value("byte_order", "xdr", format_kv);
416 
417  if (fcb->open_mode == OPEN_NEW_COMPRESSED)
418  G_set_key_value("lzw_compression_bits", "-1", format_kv);
419 
420  G__make_mapset_element_misc("cell_misc", fcb->name);
421  G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, fcb->mapset);
422  G_write_key_value_file(path, format_kv, &stat);
423 
424  G_free_key_value(format_kv);
425 
426  return stat;
427 }
char * G_mapset(void)
current mapset name
Definition: mapset.c:31
int G_is_c_null_value(const CELL *cellVal)
Returns 1 if cell is NULL, 0 otherwise. This will test if the value cell is the largest int...
Definition: null_val.c:374
int G_free_cell_stats(struct Cell_stats *s)
free cell stats
Definition: cell_stats.c:413
int G_put_raster_row(int fd, const void *buf, RASTER_MAP_TYPE data_type)
Definition: gis/put_row.c:223
int nbytes
Definition: G.h:58
int G_short_history(const char *name, const char *type, struct History *hist)
initialize history structure
Definition: history.c:202
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
int want_histogram
Definition: G.h:49
RASTER_MAP_TYPE map_type
Definition: G.h:59
void G_quant_free(struct Quant *q)
Definition: quant.c:316
#define OPEN_NEW_RANDOM
Definition: G.h:103
char * G__file_name_misc(char *path, const char *dir, const char *element, const char *name, const char *mapset)
Definition: file_name.c:70
char * name
Definition: G.h:63
int G_close_cell(int fd)
close a raster map
Definition: closecell.c:79
int G__open_null_write(int fd)
Definition: gis/put_row.c:748
off_t * row_ptr
Definition: G.h:51
FILE * fd
Definition: g3dcolor.c:368
int G__write_row_ptrs(int fd)
Definition: gis/format.c:162
int G_write_cats(char *name, struct Categories *cats)
write raster category file
Definition: gis/cats.c:1185
int G_init_cats(CELL num, const char *title, struct Categories *pcats)
initialize category structure
Definition: gis/cats.c:1417
int fileinfo_count
Definition: G.h:94
int G__write_fp_format(int fd)
Definition: closecell.c:398
int G_write_fp_range(const char *name, const struct FPRange *range)
Write the floating point range file f_range. This file is written in binary using XDR format...
Definition: range.c:380
unsigned char * null_work_buf
Definition: G.h:68
char * temp_name
Definition: G.h:60
int G_free_key_value(struct Key_Value *kv)
Free allocated Key_Value structure.
Definition: key_value1.c:145
int G_zero_raster_buf(void *rast, RASTER_MAP_TYPE data_type)
Zero a raster buffer.
Definition: zero_cell.c:54
unsigned char * data
Definition: G.h:57
COLUMN_MAPPING * col_map
Definition: G.h:52
int G_write_histogram_cs(const char *name, struct Cell_stats *statf)
Writes the histogram based on cell statistics to file.
Definition: histogram.c:135
struct GDAL_link * gdal
Definition: G.h:71
struct Range range
Definition: G.h:47
#define QUANT_FILE
Definition: closecell.c:39
int G_write_history(const char *name, struct History *hist)
write raster history file
Definition: history.c:153
struct Reclass reclass
Definition: G.h:45
#define OPEN_NEW_UNCOMPRESSED
Definition: G.h:102
int G_remove_histogram(const char *name)
Removes the histogram.
Definition: histogram.c:371
#define NULL_FILE
Definition: closecell.c:40
int G_free_cats(struct Categories *pcats)
free category structure memory
Definition: gis/cats.c:1540
Definition: G.h:74
int G_put_cellhd(const char *name, struct Cell_head *cellhd)
Definition: put_cellhd.c:19
int G_get_range_min_max(const struct Range *range, CELL *min, CELL *max)
get range min and max
Definition: range.c:608
int stat
Definition: g3dcolor.c:369
struct Cell_stats statf
Definition: G.h:46
char * G__file_name(char *path, const char *element, const char *name, const char *mapset)
Builds full path names to GIS data files.
Definition: file_name.c:33
int G__write_null_bits(int null_fd, const unsigned char *flags, int row, int cols, int fd)
Definition: gis/put_row.c:766
#define FORMAT_FILE
Definition: closecell.c:38
char * mapset
Definition: G.h:64
int G_unopen_cell(int fd)
unopen a raster map
Definition: closecell.c:112
int open_mode
Definition: G.h:43
int cur_row
Definition: G.h:54
int G__init_null_bits(unsigned char *flags, int cols)
Definition: null_val.c:742
void G_close_gdal_link(struct GDAL_link *gdal)
Definition: gdal.c:262
char * null_temp_name
Definition: G.h:61
int G__make_mapset_element_misc(const char *dir, const char *name)
Create misc element in the current mapset.
Definition: mapset_msc.c:82
return NULL
Definition: dbfopen.c:1394
struct fileinfo * fileinfo
Definition: G.h:95
XDR xdrstream
Definition: G.h:66
int G_free_reclass(struct Reclass *reclass)
Definition: reclass.c:155
int G_write_key_value_file(const char *file, const struct Key_Value *kv, int *stat)
Write key/value pairs to file.
Definition: key_value3.c:29
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
int G_construct_default_range(struct Range *range)
Sets the integer range r to [1,255].
Definition: range.c:112
#define OPEN_OLD
Definition: G.h:100
struct Cell_head cellhd
Definition: G.h:44
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
int min_null_row
Definition: G.h:69
Definition: G.h:41
#define NULL_ROWS_INMEM
Definition: G.h:11
int null_cur_row
Definition: G.h:55
int G__make_mapset_element(const char *p_element)
Create element in the current mapset.
Definition: mapset_msc.c:34
struct Quant quant
Definition: G.h:70
int G__remove_fp_range(const char *name)
Definition: range.c:95
int G_write_quant(const char *name, const char *mapset, const struct Quant *quant)
Writes the f_quant file for the raster map name from q. if mapset==G_mapset() i.e. the map is in current mapset, then the original quant file in cell_misc/map/f_quant is written. Otherwise q is written into quant2/mapset/name (much like colr2 element). This results in map being read using quant rules stored in q from G_mapset(). See G_read_quant() for detailes.
Definition: quant_rw.c:198
unsigned char * NULL_ROWS[NULL_ROWS_INMEM]
Definition: G.h:67
int G_remove_colors(const char *name, const char *mapset)
Definition: color_remove.c:24
struct FPRange fp_range
Definition: G.h:48
int G_write_range(const char *name, const struct Range *range)
write raster range file
Definition: range.c:334
int G_set_key_value(const char *key, const char *value, struct Key_Value *kv)
Set value for given key.
Definition: key_value1.c:55
int G_quant_round(struct Quant *quant)
Definition: quant.c:479
#define OPEN_NEW_COMPRESSED
Definition: G.h:101
struct Key_Value * G_create_key_value(void)
Allocate and initialize Key_Value structure.
Definition: key_value1.c:25
int reclass_flag
Definition: G.h:50