GRASS Programmer's Manual  6.4.4(2014)-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 
72 int G_close_cell(int fd)
73 {
74  struct fileinfo *fcb = &G__.fileinfo[fd];
75 
76  if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0)
77  return -1;
78  if (fcb->open_mode == OPEN_OLD)
79  return close_old(fd);
80 
81  return close_new(fd, 1);
82 }
83 
84 
105 int G_unopen_cell(int fd)
106 {
107  struct fileinfo *fcb = &G__.fileinfo[fd];
108 
109  if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0)
110  return -1;
111  if (fcb->open_mode == OPEN_OLD)
112  return close_old(fd);
113  else
114  return close_new(fd, 0);
115 }
116 
117 static int close_old(int fd)
118 {
119  struct fileinfo *fcb = &G__.fileinfo[fd];
120  int i;
121 
122  /* if G__.auto_mask was only allocated for reading map rows to create
123  non-existant null rows, and not for actuall mask, free G__.mask_row
124  if(G__.auto_mask <=0)
125  G_free (G__.mask_buf);
126  This is obsolete since now the mask_bus is always allocated
127  */
128 
129  if (fcb->gdal)
130  G_close_gdal_link(fcb->gdal);
131 
132  for (i = 0; i < NULL_ROWS_INMEM; i++)
133  G_free(fcb->NULL_ROWS[i]);
134  G_free(fcb->null_work_buf);
135 
136  if (fcb->cellhd.compressed)
137  G_free(fcb->row_ptr);
138  G_free(fcb->col_map);
139  G_free(fcb->mapset);
140  G_free(fcb->data);
141  G_free(fcb->name);
142  if (fcb->reclass_flag)
143  G_free_reclass(&fcb->reclass);
144  fcb->open_mode = -1;
145 
146  if (fcb->map_type != CELL_TYPE) {
147  G_quant_free(&fcb->quant);
148  xdr_destroy(&fcb->xdrstream);
149  }
150  close(fd);
151 
152  return 1;
153 }
154 
155 static int close_new(int fd, int ok)
156 {
157  struct fileinfo *fcb = &G__.fileinfo[fd];
158  int stat;
159  struct Categories cats;
160  struct History hist;
161  char path[GPATH_MAX];
162  CELL cell_min, cell_max;
163  int row, i, open_mode;
164 
165  if (ok) {
166  switch (fcb->open_mode) {
167  case OPEN_NEW_COMPRESSED:
168  G_debug(1, "close %s compressed", fcb->name);
169  break;
171  G_debug(1, "close %s uncompressed", fcb->name);
172  break;
173  case OPEN_NEW_RANDOM:
174  G_debug(1, "close %s random", fcb->name);
175  break;
176  }
177 
178  if (fcb->open_mode != OPEN_NEW_RANDOM &&
179  fcb->cur_row < fcb->cellhd.rows) {
180  G_zero_raster_buf(fcb->data, fcb->map_type);
181  for (row = fcb->cur_row; row < fcb->cellhd.rows; row++)
182  G_put_raster_row(fd, fcb->data, fcb->map_type);
183  G_free(fcb->data);
184  fcb->data = NULL;
185  }
186 
187  /* create path : full null file name */
188  G__make_mapset_element_misc("cell_misc", fcb->name);
189  G__file_name_misc(path, "cell_misc", NULL_FILE, fcb->name,
190  G_mapset());
191  remove(path);
192 
193  if (fcb->null_cur_row > 0) {
194  /* if temporary NULL file exists, write it into cell_misc/name/null */
195  int null_fd;
196 
197  null_fd = G__open_null_write(fd);
198  if (null_fd <= 0)
199  return -1;
200  if (null_fd < 1)
201  return -1;
202 
203  /* first finish writing null file */
204  /* write out the rows stored in memory */
205  for (row = fcb->min_null_row; row < fcb->null_cur_row; row++)
206  G__write_null_bits(null_fd,
207  fcb->NULL_ROWS[row - fcb->min_null_row],
208  row, fcb->cellhd.cols, fd);
209 
210  /* write missing rows */
211  if (fcb->open_mode != OPEN_NEW_RANDOM
212  && fcb->null_cur_row < fcb->cellhd.rows) {
213  G__init_null_bits(fcb->null_work_buf, fcb->cellhd.cols);
214  for (row = fcb->null_cur_row; row < fcb->cellhd.rows; row++)
215  G__write_null_bits(null_fd, fcb->null_work_buf, row,
216  fcb->cellhd.cols, fd);
217  }
218  close(null_fd);
219 
220  if (rename(fcb->null_temp_name, path)) {
221  G_warning(_("closecell: can't move %s\nto null file %s"),
222  fcb->null_temp_name, path);
223  stat = -1;
224  }
225  else {
226  remove(fcb->null_temp_name);
227  }
228  }
229  else {
230  remove(fcb->null_temp_name);
231  remove(path);
232  } /* null_cur_row > 0 */
233 
234  if (fcb->open_mode == OPEN_NEW_COMPRESSED) { /* auto compression */
235  fcb->row_ptr[fcb->cellhd.rows] = lseek(fd, 0L, SEEK_CUR);
236  G__write_row_ptrs(fd);
237  }
238 
239  if (fcb->map_type != CELL_TYPE) { /* floating point map */
240  int cell_fd;
241 
242  if (G__write_fp_format(fd) != 0) {
243  G_warning(_("Error writing floating point format file for map %s"),
244  fcb->name);
245  stat = -1;
246  }
247 
248  /* now write 0-length cell file */
249  G__make_mapset_element("cell");
250  cell_fd =
251  creat(G__file_name(path, "cell", fcb->name, fcb->mapset),
252  0666);
253  close(cell_fd);
254  strcpy(CELL_DIR, "fcell");
255  }
256  else {
257  /* remove fcell/name file */
258  G__file_name(path, "fcell", fcb->name, fcb->mapset);
259  remove(path);
260  /* remove cell_misc/name/f_format */
261  G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name,
262  fcb->mapset);
263  remove(path);
264  strcpy(CELL_DIR, "cell");
265  }
266  } /* ok */
267  /* NOW CLOSE THE FILE DESCRIPTOR */
268 
269  close(fd);
270  /* remember open_mode */
271  open_mode = fcb->open_mode;
272  fcb->open_mode = -1;
273 
274  if (fcb->data != NULL)
275  G_free(fcb->data);
276 
277  if (fcb->null_temp_name != NULL) {
278  G_free(fcb->null_temp_name);
279  fcb->null_temp_name = NULL;
280  }
281 
282  /* if the cell file was written to a temporary file
283  * move this temporary file into the cell file
284  * if the move fails, tell the user, but go ahead and create
285  * the support files
286  */
287  stat = 1;
288  if (ok && (fcb->temp_name != NULL)) {
289  G__file_name(path, CELL_DIR, fcb->name, fcb->mapset);
290  remove(path);
291  if (rename(fcb->temp_name, path)) {
292  G_warning(_("closecell: can't move %s\nto cell file %s"),
293  fcb->temp_name, path);
294  stat = -1;
295  }
296  else {
297  remove(fcb->temp_name);
298  }
299  }
300 
301  if (fcb->temp_name != NULL) {
302  G_free(fcb->temp_name);
303  }
304 
305  if (ok) {
306  /* remove color table */
307  G_remove_colors(fcb->name, "");
308 
309  /* create a history file */
310  G_short_history(fcb->name, "raster", &hist);
311  G_write_history(fcb->name, &hist);
312 
313  /* write the range */
314  if (fcb->map_type == CELL_TYPE) {
315  G_write_range(fcb->name, &fcb->range);
316  G__remove_fp_range(fcb->name);
317  }
318  /*NOTE: int range for floating point maps is not written out */
319  else { /* if(fcb->map_type != CELL_TYPE) */
320 
321  G_write_fp_range(fcb->name, &fcb->fp_range);
323  /* this range will be used to add default rule to quant structure */
324  }
325 
326  if (fcb->map_type != CELL_TYPE)
327  fcb->cellhd.format = -1;
328  else /* CELL map */
329  fcb->cellhd.format = fcb->nbytes - 1;
330 
331  /* write header file */
332  G_put_cellhd(fcb->name, &fcb->cellhd);
333 
334  /* if map is floating point write the quant rules, otherwise remove f_quant */
335  if (fcb->map_type != CELL_TYPE) {
336  /* DEFAULT RANGE QUANT
337  G_get_fp_range_min_max(&fcb->fp_range, &dcell_min, &dcell_max);
338  if(!G_is_d_null_value(&dcell_min) && !G_is_d_null_value(&dcell_max))
339  {
340  G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
341  G_quant_add_rule(&fcb->quant, dcell_min, dcell_max,
342  cell_min, cell_max);
343  }
344  */
345  G_quant_round(&fcb->quant);
346  if (G_write_quant(fcb->name, fcb->mapset, &fcb->quant) < 0)
347  G_warning(_("unable to write quant file!"));
348  }
349  else {
350  /* remove cell_misc/name/f_quant */
351  G__file_name_misc(path, "cell_misc", QUANT_FILE, fcb->name,
352  fcb->mapset);
353  remove(path);
354  }
355 
356  /* create empty cats file */
357  G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
358  if (G_is_c_null_value(&cell_max))
359  cell_max = 0;
360  G_init_cats(cell_max, (char *)NULL, &cats);
361  G_write_cats(fcb->name, &cats);
362  G_free_cats(&cats);
363 
364  /* write the histogram */
365  /* only works for integer maps */
366  if ((fcb->map_type == CELL_TYPE)
367  && (fcb->want_histogram)) {
368  G_write_histogram_cs(fcb->name, &fcb->statf);
369  G_free_cell_stats(&fcb->statf);
370  }
371  else {
372  G_remove_histogram(fcb->name);
373  }
374  } /* OK */
375 
376  G_free(fcb->name);
377  G_free(fcb->mapset);
378 
379  for (i = 0; i < NULL_ROWS_INMEM; i++)
380  G_free(fcb->NULL_ROWS[i]);
381  G_free(fcb->null_work_buf);
382 
383  if (fcb->map_type != CELL_TYPE)
384  G_quant_free(&fcb->quant);
385 
386  return stat;
387 }
388 
389 /* returns 0 on success, 1 on failure */
391 {
392  struct fileinfo *fcb = &G__.fileinfo[fd];
393  struct Key_Value *format_kv;
394  char path[GPATH_MAX];
395  int stat;
396 
397  if (fcb->map_type == CELL_TYPE) {
398  G_warning(_("unable to write f_format file for CELL maps"));
399  return 0;
400  }
401  format_kv = G_create_key_value();
402  if (fcb->map_type == FCELL_TYPE)
403  G_set_key_value("type", "float", format_kv);
404  else
405  G_set_key_value("type", "double", format_kv);
406 
407  G_set_key_value("byte_order", "xdr", format_kv);
408 
409  if (fcb->open_mode == OPEN_NEW_COMPRESSED)
410  G_set_key_value("lzw_compression_bits", "-1", format_kv);
411 
412  G__make_mapset_element_misc("cell_misc", fcb->name);
413  G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, fcb->mapset);
414  G_write_key_value_file(path, format_kv, &stat);
415 
416  G_free_key_value(format_kv);
417 
418  return stat;
419 }
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
#define NULL
Definition: strings.c:26
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:72
int G__open_null_write(int fd)
Definition: gis/put_row.c:748
off_t * row_ptr
Definition: G.h:51
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:390
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_warning(const char *msg,...)
Print a warning message to stderr.
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
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:105
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:266
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
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
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