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