GRASS Programmer's Manual  6.4.1(2011)
closecell.c
Go to the documentation of this file.
00001 
00002 /***********************************************************************
00003  *
00004  *   G_close_cell(fd)
00005  *      Closes and does housekeeping on an opened cell file
00006  *
00007  *   G_unopen_cell(fd)
00008  *      Closes and does housekeeping on an opened cell file
00009  *      without creating the cell file
00010  *
00011  *   parms:
00012  *      int fd     open cell file
00013  *
00014  *   returns:
00015  *      -1   on fail
00016  *       0   on success
00017  *
00018  *   note:
00019  *      On closing of a cell file that was open for writing, dummy cats
00020  *      and history files are created. Histogram and range info are written.
00021  *
00022  **********************************************************************/
00023 
00024 #ifdef __MINGW32__
00025 #  include <windows.h>
00026 #endif
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <unistd.h>
00032 #include <fcntl.h>
00033 #include <signal.h>
00034 #include <grass/gis.h>
00035 #include <grass/glocale.h>
00036 #include "G.h"
00037 
00038 #define FORMAT_FILE "f_format"
00039 #define QUANT_FILE  "f_quant"
00040 #define NULL_FILE   "null"
00041 
00042 static int close_old(int);
00043 static int close_new(int, int);
00044 static char CELL_DIR[100];
00045 
00046 
00079 int G_close_cell(int fd)
00080 {
00081     struct fileinfo *fcb = &G__.fileinfo[fd];
00082 
00083     if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0)
00084         return -1;
00085     if (fcb->open_mode == OPEN_OLD)
00086         return close_old(fd);
00087 
00088     return close_new(fd, 1);
00089 }
00090 
00091 
00112 int G_unopen_cell(int fd)
00113 {
00114     struct fileinfo *fcb = &G__.fileinfo[fd];
00115 
00116     if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0)
00117         return -1;
00118     if (fcb->open_mode == OPEN_OLD)
00119         return close_old(fd);
00120     else
00121         return close_new(fd, 0);
00122 }
00123 
00124 static int close_old(int fd)
00125 {
00126     struct fileinfo *fcb = &G__.fileinfo[fd];
00127     int i;
00128 
00129     /* if G__.auto_mask was only allocated for reading map rows to create
00130        non-existant null rows, and not for actuall mask, free G__.mask_row 
00131        if(G__.auto_mask <=0)
00132        G_free (G__.mask_buf);
00133        This is obsolete since now the mask_bus is always allocated
00134      */
00135 
00136     if (fcb->gdal)
00137         G_close_gdal_link(fcb->gdal);
00138 
00139     for (i = 0; i < NULL_ROWS_INMEM; i++)
00140         G_free(fcb->NULL_ROWS[i]);
00141     G_free(fcb->null_work_buf);
00142 
00143     if (fcb->cellhd.compressed)
00144         G_free(fcb->row_ptr);
00145     G_free(fcb->col_map);
00146     G_free(fcb->mapset);
00147     G_free(fcb->data);
00148     G_free(fcb->name);
00149     if (fcb->reclass_flag)
00150         G_free_reclass(&fcb->reclass);
00151     fcb->open_mode = -1;
00152 
00153     if (fcb->map_type != CELL_TYPE) {
00154         G_quant_free(&fcb->quant);
00155         xdr_destroy(&fcb->xdrstream);
00156     }
00157     close(fd);
00158 
00159     return 1;
00160 }
00161 
00162 static int close_new(int fd, int ok)
00163 {
00164     struct fileinfo *fcb = &G__.fileinfo[fd];
00165     int stat;
00166     struct Categories cats;
00167     struct History hist;
00168     char path[GPATH_MAX];
00169     CELL cell_min, cell_max;
00170     int row, i, open_mode;
00171 
00172     if (ok) {
00173         switch (fcb->open_mode) {
00174         case OPEN_NEW_COMPRESSED:
00175             G_debug(1, "close %s compressed", fcb->name);
00176             break;
00177         case OPEN_NEW_UNCOMPRESSED:
00178             G_debug(1, "close %s uncompressed", fcb->name);
00179             break;
00180         case OPEN_NEW_RANDOM:
00181             G_debug(1, "close %s random", fcb->name);
00182             break;
00183         }
00184 
00185         if (fcb->open_mode != OPEN_NEW_RANDOM &&
00186             fcb->cur_row < fcb->cellhd.rows) {
00187             G_zero_raster_buf(fcb->data, fcb->map_type);
00188             for (row = fcb->cur_row; row < fcb->cellhd.rows; row++)
00189                 G_put_raster_row(fd, fcb->data, fcb->map_type);
00190             G_free(fcb->data);
00191             fcb->data = NULL;
00192         }
00193 
00194         /* create path : full null file name */
00195         G__make_mapset_element_misc("cell_misc", fcb->name);
00196         G__file_name_misc(path, "cell_misc", NULL_FILE, fcb->name,
00197                           G_mapset());
00198         remove(path);
00199 
00200         if (fcb->null_cur_row > 0) {
00201             /* if temporary NULL file exists, write it into cell_misc/name/null */
00202             int null_fd;
00203 
00204             null_fd = G__open_null_write(fd);
00205             if (null_fd <= 0)
00206                 return -1;
00207             if (null_fd < 1)
00208                 return -1;
00209 
00210             /* first finish writing null file */
00211             /* write out the rows stored in memory */
00212             for (row = fcb->min_null_row; row < fcb->null_cur_row; row++)
00213                 G__write_null_bits(null_fd,
00214                                    fcb->NULL_ROWS[row - fcb->min_null_row],
00215                                    row, fcb->cellhd.cols, fd);
00216 
00217             /* write missing rows */
00218             if (fcb->open_mode != OPEN_NEW_RANDOM
00219                 && fcb->null_cur_row < fcb->cellhd.rows) {
00220                 G__init_null_bits(fcb->null_work_buf, fcb->cellhd.cols);
00221                 for (row = fcb->null_cur_row; row < fcb->cellhd.rows; row++)
00222                     G__write_null_bits(null_fd, fcb->null_work_buf, row,
00223                                        fcb->cellhd.cols, fd);
00224             }
00225             close(null_fd);
00226 
00227             if (rename(fcb->null_temp_name, path)) {
00228                 G_warning(_("closecell: can't move %s\nto null file %s"),
00229                           fcb->null_temp_name, path);
00230                 stat = -1;
00231             }
00232             else {
00233                 remove(fcb->null_temp_name);
00234             }
00235         }
00236         else {
00237             remove(fcb->null_temp_name);
00238             remove(path);
00239         }                       /* null_cur_row > 0 */
00240 
00241         if (fcb->open_mode == OPEN_NEW_COMPRESSED) {    /* auto compression */
00242             fcb->row_ptr[fcb->cellhd.rows] = lseek(fd, 0L, SEEK_CUR);
00243             G__write_row_ptrs(fd);
00244         }
00245 
00246         if (fcb->map_type != CELL_TYPE) {       /* floating point map */
00247             int cell_fd;
00248 
00249             if (G__write_fp_format(fd) != 0) {
00250                 G_warning(_("Error writing floating point format file for map %s"),
00251                           fcb->name);
00252                 stat = -1;
00253             }
00254 
00255             /* now write 0-length cell file */
00256             G__make_mapset_element("cell");
00257             cell_fd =
00258                 creat(G__file_name(path, "cell", fcb->name, fcb->mapset),
00259                       0666);
00260             close(cell_fd);
00261             strcpy(CELL_DIR, "fcell");
00262         }
00263         else {
00264             /* remove fcell/name file */
00265             G__file_name(path, "fcell", fcb->name, fcb->mapset);
00266             remove(path);
00267             /* remove cell_misc/name/f_format */
00268             G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name,
00269                               fcb->mapset);
00270             remove(path);
00271             strcpy(CELL_DIR, "cell");
00272             close(fd);
00273         }
00274     }                           /* ok */
00275     /* NOW CLOSE THE FILE DESCRIPTOR */
00276 
00277     close(fd);
00278     /* remember open_mode */
00279     open_mode = fcb->open_mode;
00280     fcb->open_mode = -1;
00281 
00282     if (fcb->data != NULL)
00283         G_free(fcb->data);
00284 
00285     if (fcb->null_temp_name != NULL) {
00286         G_free(fcb->null_temp_name);
00287         fcb->null_temp_name = NULL;
00288     }
00289 
00290     /* if the cell file was written to a temporary file
00291      * move this temporary file into the cell file
00292      * if the move fails, tell the user, but go ahead and create
00293      * the support files
00294      */
00295     stat = 1;
00296     if (ok && (fcb->temp_name != NULL)) {
00297         G__file_name(path, CELL_DIR, fcb->name, fcb->mapset);
00298         remove(path);
00299         if (rename(fcb->temp_name, path)) {
00300             G_warning(_("closecell: can't move %s\nto cell file %s"),
00301                       fcb->temp_name, path);
00302             stat = -1;
00303         }
00304         else {
00305             remove(fcb->temp_name);
00306         }
00307     }
00308 
00309     if (fcb->temp_name != NULL) {
00310         G_free(fcb->temp_name);
00311     }
00312 
00313     if (ok) {
00314         /* remove color table */
00315         G_remove_colors(fcb->name, "");
00316 
00317         /* create a history file */
00318         G_short_history(fcb->name, "raster", &hist);
00319         G_write_history(fcb->name, &hist);
00320 
00321         /* write the range */
00322         if (fcb->map_type == CELL_TYPE) {
00323             G_write_range(fcb->name, &fcb->range);
00324             G__remove_fp_range(fcb->name);
00325         }
00326         /*NOTE: int range for floating point maps is not written out */
00327         else {                  /* if(fcb->map_type != CELL_TYPE) */
00328 
00329             G_write_fp_range(fcb->name, &fcb->fp_range);
00330             G_construct_default_range(&fcb->range);
00331             /* this range will be used to add default rule to quant structure */
00332         }
00333 
00334         if (fcb->map_type != CELL_TYPE)
00335             fcb->cellhd.format = -1;
00336         else                    /* CELL map */
00337             fcb->cellhd.format = fcb->nbytes - 1;
00338 
00339         /* write header file */
00340         G_put_cellhd(fcb->name, &fcb->cellhd);
00341 
00342         /* if map is floating point write the quant rules, otherwise remove f_quant */
00343         if (fcb->map_type != CELL_TYPE) {
00344             /* DEFAULT RANGE QUANT
00345                G_get_fp_range_min_max(&fcb->fp_range, &dcell_min, &dcell_max);
00346                if(!G_is_d_null_value(&dcell_min) && !G_is_d_null_value(&dcell_max))
00347                {
00348                G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
00349                G_quant_add_rule(&fcb->quant, dcell_min, dcell_max, 
00350                cell_min, cell_max);
00351                }
00352              */
00353             G_quant_round(&fcb->quant);
00354             if (G_write_quant(fcb->name, fcb->mapset, &fcb->quant) < 0)
00355                 G_warning(_("unable to write quant file!"));
00356         }
00357         else {
00358             /* remove cell_misc/name/f_quant */
00359             G__file_name_misc(path, "cell_misc", QUANT_FILE, fcb->name,
00360                               fcb->mapset);
00361             remove(path);
00362         }
00363 
00364         /* create empty cats file */
00365         G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
00366         if (G_is_c_null_value(&cell_max))
00367             cell_max = 0;
00368         G_init_cats(cell_max, (char *)NULL, &cats);
00369         G_write_cats(fcb->name, &cats);
00370         G_free_cats(&cats);
00371 
00372         /* write the histogram */
00373         /* only works for integer maps */
00374         if ((fcb->map_type == CELL_TYPE)
00375             && (fcb->want_histogram)) {
00376             G_write_histogram_cs(fcb->name, &fcb->statf);
00377             G_free_cell_stats(&fcb->statf);
00378         }
00379         else {
00380             G_remove_histogram(fcb->name);
00381         }
00382     }                           /* OK */
00383 
00384     G_free(fcb->name);
00385     G_free(fcb->mapset);
00386 
00387     for (i = 0; i < NULL_ROWS_INMEM; i++)
00388         G_free(fcb->NULL_ROWS[i]);
00389     G_free(fcb->null_work_buf);
00390 
00391     if (fcb->map_type != CELL_TYPE)
00392         G_quant_free(&fcb->quant);
00393 
00394     return stat;
00395 }
00396 
00397 /* returns 0 on success, 1 on failure */
00398 int G__write_fp_format(int fd)
00399 {
00400     struct fileinfo *fcb = &G__.fileinfo[fd];
00401     struct Key_Value *format_kv;
00402     char path[GPATH_MAX];
00403     int stat;
00404 
00405     if (fcb->map_type == CELL_TYPE) {
00406         G_warning(_("unable to write f_format file for CELL maps"));
00407         return 0;
00408     }
00409     format_kv = G_create_key_value();
00410     if (fcb->map_type == FCELL_TYPE)
00411         G_set_key_value("type", "float", format_kv);
00412     else
00413         G_set_key_value("type", "double", format_kv);
00414 
00415     G_set_key_value("byte_order", "xdr", format_kv);
00416 
00417     if (fcb->open_mode == OPEN_NEW_COMPRESSED)
00418         G_set_key_value("lzw_compression_bits", "-1", format_kv);
00419 
00420     G__make_mapset_element_misc("cell_misc", fcb->name);
00421     G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, fcb->mapset);
00422     G_write_key_value_file(path, format_kv, &stat);
00423 
00424     G_free_key_value(format_kv);
00425 
00426     return stat;
00427 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines