/* $Id: TimesUpdate.c,v 1.3 2008/02/19 16:24:58 elena Exp $*/ /*===================================================================== * DD SYSTEM base package * DD_Server library * TimesUpdate.c * V.4.6 * * usage TimesUpdate -r/-i[-u]/-d nc_times_file nc_data_file[*.gz] nc_data_file[*.gz] .... * Note that in most of cases at the end of activity you have to run ClearTimes nc_times_file * * Versions: * Apr 23 1997, Usung *.gz files V.2.0 * Jan 4, 2006, V.3.0 - insert file and check overlaping * Jan 13,2006, V.3.1 - error is corrected * Feb 02,2006, V.3.2 - Corrected removing database in case of error * Sep 20, 2007, V.4.0, Fedorov, from rehash.nc. New NetCDF V.3, syncronization * Sep 25, 2007 V.4.1 The very first file and first file insert * Nov 29, 2007 V.4.2 If several first records - bug correction * Feb 17, 2008 V.4.5 Fedorov: New options , remake, insert, delete * Feb 19, 2008 V.4.6 delete bugs corrected *=====================================================================*/ /*===================================================================== * Description: * Program reads list of nc_data_files, probabbly gzipped, reads StartTime and Stop time * and create or update nc_times_file. The sequence of data files are not important * -r remove nc_times_file and create new one * -i insert new file(s) * -d remove file(s) from nc_times * * Dimensions: * TimeLingth TIMELENGTH * NameLength NAME_DIM * Record Unlimited * Variables: * * char StartTime[TIMELENGTH] * char EndTime[TIMELENGTH] * * Attributes: * none *======================================================================*/ #include #include #include #include #include #include #include #include /* Global Constant definitions */ #define TIME_LENGTH_NAME "TimeLength" #define TIME_LENGTH 17L #define REC_DIM_NAME "record" #define REC_DIM NC_UNLIMITED #define NAME_DIM_NAME "NameLength" #define NAME_DIM 32L #define NAME_LENGTH 100 #define STARTTIME "StartTime" #define STOPTIME "StopTime" #define FILENAME "FileName" #define TIME_TYPE NC_CHAR #define TEMPUNZIP "TimesUpdateTemp.nc\0" #define NODATA "NODATA\0" /*----------- Conditions --------------------------*/ enum Conditions {ALLLEFT,LEFTOVER,WELLIN,RIGHTOVER,ALLRIGHT,LEFTRIGHTOVER,LEFTIN}; /*----------- Modes -------------------------------*/ enum Modes {REMAKE, INSERT, DELETE}; /*----------- Type definition ------------------------------*/ typedef struct { char Name[NAME_LENGTH]; // current data file char StartS[TIME_LENGTH]; // Start Time String char StopS[TIME_LENGTH]; // Stop Time String double StartD; // Start double double StopD; // Stop double } t_StartStop; /*---------- Global variables (IDs) of open times file -------------*/ int tmID; /* nc file descriptor */ int StartID, StopID, NameID; size_t RecordsNumber = 0; // Records Number of the existing times file static char ZeroTime[TIME_LENGTH] = "0000000000000000\0"; static int ToZipFlag = 0; static char UnzipName[NAME_LENGTH]; /*======================================================================== * FUNCTIONS *=======================================================================*/ /*======================================================================== * GetFileInfo *=======================================================================*/ t_StartStop *GetFileInfo(char *FileName) { static t_StartStop StartStop; int dataID; int DataStartID, DataStopID; static size_t DataStart[1] = {0}; static size_t DataCount[1] = {TIME_LENGTH}; char command[200]; int Status; /*---- Check if this file exist ------------*/ if(strcmp(FileName+strlen(FileName)-3,".gz") == 0) // Zipped file { strcpy(UnzipName, TEMPUNZIP); sprintf(command,"gunzip -c %s > %s",FileName,UnzipName); system(command); ToZipFlag = 0; strncpy(StartStop.Name,FileName,strlen(FileName)-3); } else { ToZipFlag = 1; strcpy(UnzipName,FileName); strcpy(StartStop.Name,FileName); } if((Status = nc_open(UnzipName,NC_NOWRITE,&dataID)) == NC_NOERR) { Status = nc_inq_varid(dataID,STARTTIME,&DataStartID); Status = nc_inq_varid(dataID,STOPTIME, &DataStopID); Status = nc_get_vara_text(dataID,DataStartID,DataStart,DataCount,(char *)StartStop.StartS); Status = nc_get_vara_text(dataID,DataStopID,DataStart,DataCount,(char *)StartStop.StopS); Status = nc_close(dataID); } else if(Status == 2) { fprintf(stderr,"File %s does not exist\n",UnzipName); return NULL; } else { fprintf(stderr,"File %s is corrupted, Error = %d\n",UnzipName,Status); sprintf(command,"rm %s*",StartStop.Name); system(command); return NULL; } if((isdigit(StartStop.StartS[0]) == 0) || (isdigit(StartStop.StopS[0]) == 0)) { fprintf(stderr,"File %s is corrupted\n",UnzipName); sprintf(command,"rm %s*",StartStop.Name); system(command); return NULL; } StartStop.StartD = DD_Time2Double(StartStop.StartS); StartStop.StopD = DD_Time2Double(StartStop.StopS); return &StartStop; } /*-----------------------------------------------------------*/ /*------------------------------------------------------------ * RemoveRecord() *-----------------------------------------------------------*/ int RemoveRecord(size_t RecordPos, t_StartStop *StartStop) { static size_t TimeStart[2] = {0,0}; static size_t TimeCount[2] = {1,TIME_LENGTH}; static size_t NameCount[2] = {1, NAME_DIM}; char CStart[TIME_LENGTH],CStop[TIME_LENGTH], CName[NAME_DIM]; size_t Crec; char command[200]; int status; char NewName[NAME_LENGTH]; /*------- Remove corresponding file -------------------*/ TimeStart[0] = RecordPos; nc_get_vara_text(tmID,NameID,TimeStart,NameCount,(char *)CName); if(StartStop == NULL) NewName[0] = '\0'; else strcpy(NewName,StartStop->Name); if((strcmp(CName,NODATA) != 0)&&(strcmp(CName,NewName) != 0)) { // Remove old file which overlap with new one */ sprintf(command,"rm %s*",CName); system(command); } /*--- replacing Variable -----------------------*/ for(Crec = RecordPos + 1; Crec < RecordsNumber; Crec++) { TimeStart[0] = Crec; status = nc_get_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)CStart); status = nc_get_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)CStop); status = nc_get_vara_text(tmID,NameID,TimeStart,NameCount,(char *)CName); TimeStart[0]--; status = nc_put_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)CStart); status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)CStop); status = nc_put_vara_text(tmID,NameID,TimeStart,NameCount,(char *)CName); } /*----- Set Zero at the end -------------------------*/ TimeStart[0] = RecordsNumber - 1; status = nc_put_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)ZeroTime); status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)ZeroTime); RecordsNumber--; nc_sync(tmID); return 1; } /*-----------------------------------------------------------*/ /*------------------------------------------------------------ * InsertRecord() *-----------------------------------------------------------*/ int InsertRecord(size_t RecordPos, t_StartStop *StartStop) { static size_t TimeStart[2] = {0,0}; static size_t TimeCount[2] = {1,TIME_LENGTH}; static size_t NameCount[2] = {1, NAME_DIM}; char CStart[TIME_LENGTH],CStop[TIME_LENGTH], CName[NAME_DIM]; int Crec; int status; /*--- Scrall all wariables down-----------------------*/ for(Crec = RecordsNumber - 1; Crec >= (int)RecordPos; Crec--) { TimeStart[0] = (size_t)Crec; status = nc_get_vara_text (tmID,StartID,TimeStart,TimeCount,(char *)CStart); status = nc_get_vara_text (tmID,StopID,TimeStart,TimeCount,(char *)CStop); status = nc_get_vara_text (tmID,NameID,TimeStart,NameCount,(char *)CName); TimeStart[0]++; status = nc_put_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)CStart); status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)CStop); status = nc_put_vara_text(tmID,NameID,TimeStart,NameCount,(char *)CName); } /*------ Put the new record to empty space -----------------*/ TimeStart[0] = RecordPos; status = nc_put_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)StartStop->StartS); status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)StartStop->StopS); status = nc_put_vara_text(tmID,NameID,TimeStart,NameCount,(char *)StartStop->Name); RecordsNumber++; nc_sync(tmID); return 1; } /*==================================================================================*/ /*================================================================================== * MAIN *==================================================================================*/ main(int argc, char **argv) { static char usage[] = "usage: TimesUpdate -r/-i[-u]/-d nc_times_file nc_data_file[*.gz] nc_data_file[*.gz]"; char Start[TIME_LENGTH], Stop[TIME_LENGTH], Name[NAME_DIM]; /* NC definitions */ int TlDimID,RecDimID, NlDimID; /* ID of dimensions */ static size_t TimeStart[2] = {0,0}; static size_t TimeCount[2] = {1,TIME_LENGTH}; static size_t NameCount[2] = {1, NAME_DIM}; int DimVector[2]; char tmName[NAME_DIM]; int i, InsertFlag, FindFlag, ihole; char command[100]; char name[100]; int compress = 0; int status; double LastTime = 0.0, FirstTime = 0.0; // Times of the hall between files t_StartStop *CurrentRecord; // pointer to the internal static structure enum Modes CurrMode; enum Conditions condition; /*================================================================= * Check arguments and options *=================================================================*/ if(argc < 4) {fprintf(stderr,"%s\n",usage); exit(1); } if((strcmp(argv[1], "-r")) == 0) CurrMode = REMAKE; else if((strcmp(argv[1], "-i")) == 0) CurrMode = INSERT; else if((strcmp(argv[1], "-u")) == 0) CurrMode = INSERT; else if((strcmp(argv[1], "-d")) == 0) CurrMode = DELETE; else {fprintf(stderr,"Unknown option %s\n",argv[1]); exit(1);} /*-----------------------------------------------------------------*/ /*================================================================= * Creating Times ncdf file if we have to make a new file *=================================================================*/ switch(CurrMode) { case REMAKE: /* Create New File */ if((status = nc_create(argv[2],NC_SHARE,&tmID)) != NC_NOERR) { fprintf(stderr,"Can not create file %s\n",argv[2]); exit(0); } status = nc_def_dim(tmID,TIME_LENGTH_NAME,TIME_LENGTH,&TlDimID); status = nc_def_dim(tmID,NAME_DIM_NAME,NAME_DIM,&NlDimID); status = nc_def_dim(tmID,REC_DIM_NAME,REC_DIM,&RecDimID); DimVector[0] = RecDimID; DimVector[1] = TlDimID; status = nc_def_var(tmID, STARTTIME,TIME_TYPE,2,DimVector,&StartID); status = nc_def_var(tmID, STOPTIME,TIME_TYPE,2,DimVector,&StopID); DimVector[1] = NlDimID; status = nc_def_var(tmID, FILENAME,TIME_TYPE,2,DimVector,&NameID); RecordsNumber = 0; TimeStart[0] = (size_t)RecordsNumber; status = nc_enddef(tmID); break; /*====== Or just open existing file ===================*/ case INSERT: case DELETE: /* Open existing file */ if((status = nc_open(argv[2],NC_WRITE|NC_SHARE,&tmID)) != NC_NOERR) { fprintf(stderr,"Can not open file %s to write\n",argv[2]); exit(0); } status = nc_inq_dimid(tmID,REC_DIM_NAME,&RecDimID); status = nc_inq_varid(tmID, STARTTIME,&StartID); status = nc_inq_varid(tmID, STOPTIME,&StopID); status = nc_inq_varid(tmID, FILENAME,&NameID); status = nc_inq_dimlen(tmID,RecDimID, &RecordsNumber); break; } /*==========================================================================*/ /*========================================================================== * For Each file in the argument list *=========================================================================*/ for(i = 3; i < argc; i++) { switch(CurrMode) { case DELETE: TimeStart[0] = 0; FindFlag = 0; while((FindFlag == 0) && (TimeStart[0] < RecordsNumber)) { status = nc_get_vara_text(tmID,NameID,TimeStart,NameCount,(char *)tmName); if(strncmp(tmName, argv[i], strlen(tmName)) == 0) { /* Record is found */ FindFlag = 1; RemoveRecord((size_t)TimeStart[0],(t_StartStop *)NULL); } else TimeStart[0]++; } break; case REMAKE: case INSERT: if((CurrentRecord = GetFileInfo(argv[i])) != NULL) /* Read current file information */ { /*----------------- The very first file in VI DIR -------------------*/ if (RecordsNumber == 0) { TimeStart[0] = (size_t)0; status = nc_put_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)CurrentRecord->StartS); status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)CurrentRecord->StopS); status = nc_put_vara_text(tmID,NameID,TimeStart,NameCount,(char *)CurrentRecord->Name); RecordsNumber++; } else { /*--------------------------------------------------------- * Searchig the same file or a hole to insert *-------------------------------------------------------*/ InsertFlag = 0; ihole = 0; while((InsertFlag == 0) && (ihole <= RecordsNumber)) { if(ihole > 0) /* Get the Left Time of the hole */ { TimeStart[0] = (size_t)(ihole-1); status = nc_get_vara_text (tmID,StopID,TimeStart,TimeCount,(char *)Stop); FirstTime = DD_Time2Double(Stop); } else FirstTime = 0.0; if(ihole < RecordsNumber) /* Get the Right Time of the hole */ { TimeStart[0] = (size_t)ihole; status = nc_get_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)Start); LastTime = DD_Time2Double(Start); } else LastTime = 1.0e16; /*--------- Look the conditions ---------------*/ condition = ALLRIGHT; if((CurrentRecord->StartD < FirstTime - 60.0) && (CurrentRecord->StopD > LastTime + 60.0)) condition = LEFTRIGHTOVER; else if((CurrentRecord->StartD < FirstTime - 60.0) && (CurrentRecord->StopD < FirstTime + 60.0)) condition = ALLLEFT; else if((CurrentRecord->StartD < FirstTime - 60.0) && (CurrentRecord->StopD > FirstTime) && (CurrentRecord->StopD < LastTime + 60.0)) condition = LEFTOVER; else if((CurrentRecord->StartD >= FirstTime - 60.0) && (CurrentRecord->StopD <= LastTime + 60.0)) condition = WELLIN; else if((CurrentRecord->StartD >= FirstTime - 60.0) && (CurrentRecord->StartD < LastTime) && (CurrentRecord->StopD > LastTime + 60.0))condition = RIGHTOVER; else if((CurrentRecord->StartD > LastTime - 60.0) && (CurrentRecord->StopD > LastTime + 60.0)) condition = ALLRIGHT; /* What to do with these conditions ----------------*/ switch(condition) { case WELLIN : InsertRecord((size_t)ihole, CurrentRecord); InsertFlag = 1; break; case ALLLEFT : RemoveRecord((size_t)(ihole-1),CurrentRecord); ihole--; break; case ALLRIGHT : ihole++; break; case LEFTOVER : RemoveRecord((size_t)(ihole-1),CurrentRecord); ihole--; break; case RIGHTOVER : RemoveRecord((size_t)ihole,CurrentRecord); break; case LEFTRIGHTOVER : RemoveRecord((size_t)(ihole-1),CurrentRecord); RemoveRecord((size_t)(ihole-1),CurrentRecord); ihole--; break; } } // While InsertFlag } // if RecordsNumber > 0 /*---------- Zip or remove new nc file -----------------*/ if(ToZipFlag) sprintf(command,"gzip -f %s",CurrentRecord->Name); else sprintf(command,"rm %s",UnzipName); system(command); } // If current argument file is OK } // CASE } // For several arguments status = nc_close(tmID); return(0); } /*=========================================================================================================*/