Commit 58faca3ff01761c84934a5c597366332754815b4

Authored by Benjamin Renard
1 parent e9c962b4

First implementation of new cache system

src/INCLUDE/DD_comm.h
... ... @@ -183,7 +183,9 @@
183 183 */
184 184  
185 185 /*-------------------- TYPEDEF ---------------------------*/
186   -typedef struct { char names[CASHLEN][MAXSETLENGTH];
  186 +typedef struct {
  187 + char CacheFilePath[PATHLENGTH];
  188 + char names[CASHLEN][MAXSETLENGTH];
187 189 long times[CASHLEN];
188 190 int FileOpen[CASHLEN]; /* 1 if file is open */
189 191 int ID; /* ID of open cach file */
... ... @@ -275,24 +277,29 @@ enum LockStatus {NOLOCK, LOCKED, LOCKREMOVED};
275 277 extern int OpenInstr(char *InstrName);
276 278  
277 279 /*
278   - * Init shared memory for VI cache lock system
  280 + * Init shared memory for cache system
279 281 */
280   -extern void CacheLock_Init();
  282 +extern void Cache_Init();
281 283  
282 284 /*
283   - * Free shared memory used for VI cache lock system
  285 + * Free shared memory used for cache system
284 286 */
285   -extern void CacheLock_Free();
  287 +extern void Cache_Free();
286 288  
287 289 /*
288   - * Lock cache for a specific VI
  290 + * Free shared memory used for cache system
289 291 */
290   -extern void CacheLock_Lock(char* VIID);
  292 +extern int Cache_RequestDataFileAccess(DD_Var_t *D, char* dataFileName);
291 293  
292 294 /*
293   - * Unlock cache for a specific VI
  295 + * Free shared memory used for cache system
294 296 */
295   -extern void CacheLock_Unlock(char* VIID);
  297 +extern int Cache_ReleaseDataFileAccess(DD_Var_t *D);
  298 +
  299 +/*
  300 + * Close cache file
  301 + */
  302 +extern int Cache_CloseFile(DD_Var_t *D);
296 303  
297 304 /*
298 305 * Open Virtual instrument by name and returns the ID
... ... @@ -357,6 +364,7 @@ size_t MaxRecord(int ncID);
357 364 * Inspect all variables and dimensions of the file (exept Time associated) and
358 365 * returm maximal record number to transmit
359 366 */
  367 +
360 368 /*------------------ Global constants ----------------------------------*/
361 369 static u_int xdrlen[] = {4,4,4,8,4};
362 370 static size_t unixlen[] = {sizeof(char),sizeof(int),sizeof(float),sizeof(double),sizeof(short)};
... ...
src/SERVER/DD_Cache.c 0 โ†’ 100644
... ... @@ -0,0 +1,651 @@
  1 +/*=====================================================================
  2 + * DD SYSTEM base package
  3 + * DD_Server library
  4 + * DD_CacheLock.c
  5 + * V.1.0
  6 + * Last revision:
  7 + * May 29 2015: Version 1.0. First implementation of a lock system for concurrent access to a virtual instrument
  8 + */
  9 +
  10 +#include <stdio.h>
  11 +#include <string.h>
  12 +#include <sys/mman.h>
  13 +#include <pthread.h>
  14 +#include <sys/stat.h>
  15 +#include <netcdf.h>
  16 +#include "DD.h"
  17 +#include "DD_comm.h"
  18 +
  19 +//Max number of VI that can be used at the same time
  20 +#define CACHE_MAXVI 30
  21 +//Max number of clients that can be used a data file of a VI at the same time
  22 +#define CACHE_MAXCLIENT 30
  23 +
  24 +//Use state of a cache element
  25 +#define CACHE_NOTUSED 0
  26 +#define CACHE_USED 1
  27 +
  28 +typedef struct
  29 +{
  30 + //Name of the related data file
  31 + char name[MAXFILENAME];
  32 + //List of client that's currently use this data file
  33 + pid_t clientPIDS[CACHE_MAXCLIENT];
  34 + //State flag (CACHE_NOTUSED or CACHE_USED)
  35 + int state;
  36 +} CacheDataFile;
  37 +
  38 +typedef struct
  39 +{
  40 + //Virtual instrument ID
  41 + char VIID[MAXSETLENGTH];
  42 + //List of data files
  43 + CacheDataFile dataFiles[CASHLEN];
  44 + //State flag (CACHE_NOTUSED or CACHE_USED)
  45 + int state;
  46 + //Mutex for concurrential access
  47 + pthread_mutex_t lock;
  48 + //PID of the process that's currently lock the mutex
  49 + pid_t lockPID;
  50 +} CacheVIFile;
  51 +
  52 +typedef struct
  53 +{
  54 + //List of currently used VI
  55 + CacheVIFile VIFiles[CACHE_MAXVI];
  56 + //Mutex for concurrential access
  57 + pthread_mutex_t lock;
  58 + //PID of the process that's currently lock the mutex
  59 + pid_t lockPID;
  60 +} CacheData;
  61 +
  62 +extern int Verbose;
  63 +
  64 +/*
  65 + * Pointer to structure of Cache Data
  66 + */
  67 +static CacheData* cache_data = NULL;
  68 +
  69 +/*
  70 + * Refresh "CACHE" table from Cache file
  71 + */
  72 +int Cache_RefreshTable(DD_Var_t *D)
  73 +{
  74 + int status; /* Error indicator */
  75 +
  76 + if (D->Cash.ID < 0)
  77 + {
  78 + if(Verbose) fprintf(stderr,"Cache_RefreshTable. Cache file %s not opened\n", D->Cash.CacheFilePath);
  79 + D->LastFileStatus = CACHERR;
  80 + return CACHERR;
  81 + }
  82 +
  83 + status = nc_sync(D->Cash.ID);
  84 + if(status != NC_NOERR)
  85 + {
  86 + if(Verbose) fprintf(stderr,"Cache_RefreshTable. Error to synchronize cache file %s, message:%s\n", D->Cash.CacheFilePath, nc_strerror(status));
  87 + D->LastFileStatus = CACHERR;
  88 + return CACHERR;
  89 + }
  90 +
  91 + size_t cashStart[2] = {0L,0L};
  92 + size_t cashCount[2] = {1L,MAXFILENAME};
  93 +
  94 + for(cashStart[0] = 0; cashStart[0] < CASHLEN; cashStart[0]++)
  95 + {
  96 + status = nc_get_vara_text(D->Cash.ID, D->Cash.nameID,cashStart,cashCount, D->Cash.names[cashStart[0]]);
  97 + if(status != NC_NOERR)
  98 + {
  99 + if(Verbose) fprintf(stderr,"Cache_RefreshTable. Error to synchronize cache file name, message: %s\n", nc_strerror(status));
  100 + D->LastFileStatus = CACHERR;
  101 + return CACHERR;
  102 + }
  103 + status = nc_get_vara_long(D->Cash.ID, D->Cash.timeID,cashStart,cashCount,&(D->Cash.times[cashStart[0]]));
  104 + if(status != NC_NOERR)
  105 + {
  106 + if(Verbose) fprintf(stderr,"Cache_RefreshTable. Error to synchronize cache time, message: %s\n", nc_strerror(status));
  107 + D->LastFileStatus = CACHERR;
  108 + return CACHERR;
  109 + }
  110 + }
  111 +
  112 + if(Verbose) fprintf(stderr,"Cache_RefreshTable. Cache table is synchronized\n");
  113 +
  114 + return OK;
  115 +}
  116 +
  117 +/*
  118 + * Close cache file
  119 + */
  120 +int Cache_CloseFile(DD_Var_t *D)
  121 +{
  122 + int status; /* Error indicator */
  123 +
  124 + if(D->Cash.ID >= 0)
  125 + {
  126 + status = nc_close(D->Cash.ID);
  127 + D->Cash.ID = -1;
  128 + if(Verbose)
  129 + fprintf(stderr,"CloseCacheFile()");
  130 + }
  131 +}
  132 +
  133 +/*
  134 + * Open cache file
  135 + */
  136 +int Cache_OpenFile(DD_Var_t *D)
  137 +{
  138 + int status; /* Error indicator */
  139 +
  140 + if (D->Cash.ID >= 0)
  141 + return (OK);
  142 +
  143 + status = nc_open(D->Cash.CacheFilePath,NC_WRITE|NC_SHARE,&(D->Cash.ID)); /* Cach file */
  144 + if(status != NC_NOERR)
  145 + {
  146 + if(Verbose) fprintf(stderr, "Cache_OpenFile. Error to open cache file %s, message:%s\n", D->Cash.CacheFilePath, nc_strerror(status));
  147 + D->LastFileStatus = CACHERR;
  148 + return(CACHERR);
  149 + }
  150 + status = nc_inq_varid(D->Cash.ID,"name",&(D->Cash.nameID));
  151 + status = nc_inq_varid(D->Cash.ID,"time",&(D->Cash.timeID));
  152 + status = nc_inq_varid(D->Cash.ID,"fopen",&(D->Cash.fopenID));
  153 + D->CurrCushN = -1;
  154 +
  155 + if(status != NC_NOERR)
  156 + {
  157 + if(Verbose) fprintf(stderr,"Cache_OpenFile. Error to open cache file %s, message:%s\n", D->Cash.CacheFilePath, nc_strerror(status));
  158 + D->LastFileStatus = CACHERR;
  159 + return(CACHERR);
  160 + }
  161 +
  162 + if(Verbose) fprintf(stderr,"Cache_OpenFile. Cache file %s is open\n", D->Cash.CacheFilePath);
  163 + return (OK);
  164 +}
  165 +
  166 +/*
  167 + * Decompress a data file
  168 + */
  169 +void Cache_DecompressDataFile(DD_Var_t *D, char* dataFileName)
  170 +{
  171 + char FullName[PATHLENGTH];
  172 + strcpy(FullName,D->path);
  173 + strcat(FullName, dataFileName);
  174 +
  175 + char command[300];
  176 + strcpy(command, "gunzip -c ");
  177 + strcat(command,FullName);
  178 + strcat(command, ".gz > ");
  179 + strcat(command, FullName);
  180 + system(command); /* File is unzipped */
  181 + sprintf(command, "chmod g+w %s\0",FullName);
  182 + system(command); /* File is unzipped */
  183 +}
  184 +
  185 +/*
  186 + * Compress a data file
  187 + */
  188 +void Cache_CompressDataFile(DD_Var_t *D, char* dataFileName)
  189 +{
  190 + //This is not really a compression, just a supression of the uncompressed data file
  191 + char command[300];
  192 + strcpy(command, "rm ");
  193 + strcat(command,D->path);
  194 + strcat(command,dataFileName);
  195 + strcat(command, " &");
  196 + system(command);
  197 +}
  198 +
  199 +/*
  200 + * Check if a process is running
  201 + */
  202 +int Cache_PIDIsRunning(pid_t pid)
  203 +{
  204 + return (kill(pid, 0) == 0 ? 1 : 0);
  205 +}
  206 +
  207 +/*
  208 + * Release lock for dead process
  209 + */
  210 +void Cache_ForceUnlockIfNotRunning(pthread_mutex_t *mutex, pid_t* lockPID)
  211 +{
  212 + if (pthread_mutex_trylock(mutex) != 0)
  213 + {
  214 + //Test if the child process is alive
  215 + if (Cache_PIDIsRunning((*lockPID)) == 0)
  216 + {
  217 + //Force unlock
  218 + (*lockPID) = 0;
  219 + pthread_mutex_unlock(mutex);
  220 + }
  221 + }
  222 + else
  223 + {
  224 + (*lockPID) = 0;
  225 + pthread_mutex_unlock(mutex);
  226 + }
  227 +}
  228 +
  229 +/*
  230 + * Unlock access
  231 + */
  232 +void Cache_Unlock(pthread_mutex_t *mutex, pid_t* lockPID)
  233 +{
  234 + int PID = getpid();
  235 + if ((*lockPID) == PID)
  236 + {
  237 + (*lockPID) = 0;
  238 + pthread_mutex_unlock(mutex);
  239 + }
  240 +}
  241 +
  242 +/*
  243 + * Lock access
  244 + */
  245 +void Cache_Lock(pthread_mutex_t* mutex, pid_t* lockPID)
  246 +{
  247 + int PID = getpid();
  248 + int attempt = 0;
  249 + while (1)
  250 + {
  251 + if (pthread_mutex_trylock(mutex) == 0)
  252 + {
  253 + //Mutex now lock for this PID
  254 + (*lockPID) = PID;
  255 + return;
  256 + }
  257 + //Not available
  258 + if ((attempt > 10) && ((*lockPID) != 0))
  259 + {
  260 + Cache_ForceUnlockIfNotRunning(mutex, lockPID);
  261 + attempt = 0;
  262 + }
  263 + ++attempt;
  264 + //sleep(2);
  265 + }
  266 +}
  267 +
  268 +/*
  269 + * Init the shared memory used to manage concurrent access to cache
  270 + */
  271 +void Cache_Init()
  272 +{
  273 + if (cache_data != NULL)
  274 + return;
  275 +
  276 + if(Verbose) fprintf(stderr,"Cache_Init\n");
  277 +
  278 + // place our shared data in shared memory
  279 + int prot = PROT_READ | PROT_WRITE;
  280 + int flags = MAP_SHARED | MAP_ANONYMOUS;
  281 + cache_data = mmap(NULL, sizeof(CacheData), prot, flags, -1, 0);
  282 +
  283 + memset(cache_data, 0, sizeof(CacheData));
  284 +
  285 + // initialise mutex so it works properly in shared memory
  286 + // global mutex for global cache data access
  287 + pthread_mutexattr_t attr;
  288 + pthread_mutexattr_init(&attr);
  289 + pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
  290 + pthread_mutex_init(&cache_data->lock, &attr);
  291 +
  292 + int i, j;
  293 + for (i = 0; i < CACHE_MAXVI; ++i)
  294 + {
  295 + // mutex for VI cache data access
  296 + pthread_mutexattr_t attr;
  297 + pthread_mutexattr_init(&attr);
  298 + pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
  299 + pthread_mutex_init(&cache_data->VIFiles[i].lock, &attr);
  300 + }
  301 +}
  302 +
  303 +/*
  304 + * Free the shared memory used by the cache manager
  305 + */
  306 +void Cache_Free()
  307 +{
  308 + if(Verbose) fprintf(stderr,"Cache_Free\n");
  309 + if (cache_data != NULL)
  310 + munmap(cache_data, sizeof(CacheData));
  311 + cache_data = NULL;
  312 +}
  313 +
  314 +/*
  315 + * Get and lock the access to a virtual instrument
  316 + */
  317 +int Cache_GetAndLockVI(char* VIID)
  318 +{
  319 + if (cache_data == NULL)
  320 + return;
  321 +
  322 + int i;
  323 + int PID = getpid();
  324 +
  325 + Cache_Lock(&(cache_data->lock), &(cache_data->lockPID));
  326 +
  327 + for (i = 0; i < CACHE_MAXVI; ++i)
  328 + {
  329 + if ((cache_data->VIFiles[i].state == CACHE_USED) && (strcmp(VIID, cache_data->VIFiles[i].VIID) == 0))
  330 + {
  331 + //VI already exist in the cache data
  332 + Cache_Lock(&(cache_data->VIFiles[i].lock), &(cache_data->VIFiles[i].lockPID));
  333 + Cache_Unlock(&(cache_data->lock), &(cache_data->lockPID));
  334 + if(Verbose) fprintf(stderr,"Cache_GetAndLockVI. %s is locked by PID %d\n", VIID, PID);
  335 + return i;
  336 + }
  337 + }
  338 +
  339 + //VI not exist in the cache data => Try to find an available slot to add it
  340 + for (i = 0; i < CACHE_MAXVI; ++i)
  341 + {
  342 + if (cache_data->VIFiles[i].state == CACHE_NOTUSED)
  343 + {
  344 + //Use this slot for the VI
  345 + Cache_Lock(&(cache_data->VIFiles[i].lock), &(cache_data->VIFiles[i].lockPID));
  346 + Cache_Unlock(&(cache_data->lock), &(cache_data->lockPID));
  347 + cache_data->VIFiles[i].state = CACHE_USED;
  348 + strcpy(cache_data->VIFiles[i].VIID, VIID);
  349 + if(Verbose) fprintf(stderr,"Cache_GetAndLockVI. %s is locked by PID %d\n", VIID, PID);
  350 + return i;
  351 + }
  352 + }
  353 +
  354 + //Not available slot for this VI. Wait and retry
  355 + if(Verbose)
  356 + fprintf(stderr,"Cache_GetAndLockVI. Cannot find an available slot for %s => Wait and retry\n", VIID);
  357 +
  358 + int j;
  359 + int k;
  360 + //Cleanup
  361 + for (i = 0; i < CACHE_MAXVI; ++i)
  362 + {
  363 + Cache_ForceUnlockIfNotRunning(&(cache_data->VIFiles[i].lock), &(cache_data->VIFiles[i].lockPID));
  364 + if (cache_data->VIFiles[i].lockPID == 0)
  365 + {
  366 + cache_data->VIFiles[i].state = CACHE_NOTUSED;
  367 + for (j = 0; j < CASHLEN; ++j)
  368 + {
  369 + if (cache_data->VIFiles[i].dataFiles[j].state != CACHE_USED)
  370 + continue;
  371 + cache_data->VIFiles[i].dataFiles[j].state = CACHE_NOTUSED;
  372 + for (k = 0; k < CACHE_MAXCLIENT; ++k)
  373 + {
  374 + if (cache_data->VIFiles[i].dataFiles[j].clientPIDS[k] != 0)
  375 + {
  376 + if (Cache_PIDIsRunning(cache_data->VIFiles[i].dataFiles[j].clientPIDS[k]) == 0)
  377 + cache_data->VIFiles[i].dataFiles[j].clientPIDS[k] = 0;
  378 + else
  379 + {
  380 + cache_data->VIFiles[i].dataFiles[j].state = CACHE_USED;
  381 + }
  382 + }
  383 + }
  384 + if (cache_data->VIFiles[i].dataFiles[j].state == CACHE_USED)
  385 + cache_data->VIFiles[i].state = CACHE_USED;
  386 + }
  387 + }
  388 + }
  389 +
  390 + Cache_Unlock(&(cache_data->lock), &(cache_data->lockPID));
  391 + //sleep(2);
  392 + return Cache_GetAndLockVI(VIID);
  393 +}
  394 +
  395 +/*
  396 + * Unlock the access to a virtual instrument
  397 + */
  398 +void Cache_UnlockVI(char* VIID)
  399 +{
  400 + if (cache_data == NULL)
  401 + return;
  402 +
  403 + int i;
  404 + for (i = 0; i < CACHE_MAXVI; ++i)
  405 + {
  406 + if (strcmp(VIID, cache_data->VIFiles[i].VIID) == 0)
  407 + {
  408 + Cache_Unlock(&(cache_data->VIFiles[i].lock), &(cache_data->VIFiles[i].lockPID));
  409 + if(Verbose) fprintf(stderr,"Cache_Unlock. %s is unlocked\n", VIID);
  410 + return;
  411 + }
  412 + }
  413 + if(Verbose) fprintf(stderr,"Cache_Unlock. Cannot unlock %s\n", VIID);
  414 +}
  415 +
  416 +/*
  417 + * Request the access to a specified data file for a client
  418 + */
  419 +int Cache_RequestDataFileAccess(DD_Var_t *D, char* dataFileName)
  420 +{
  421 + if (cache_data == NULL)
  422 + return(CACHERR);
  423 +
  424 + //Retrieve VI in cache data
  425 + int cacheVIIndex = Cache_GetAndLockVI(D->InstrName);
  426 +
  427 + //Open Cache file if needed
  428 +
  429 + if (D->Cash.ID < 0)
  430 + {
  431 + if (Cache_OpenFile(D) != OK)
  432 + {
  433 + Cache_UnlockVI(D->InstrName);
  434 + return(CACHERR);
  435 + }
  436 + }
  437 +
  438 + //Refresh Cache Table in relation with the cache file
  439 + if (Cache_RefreshTable(D) != OK)
  440 + {
  441 + Cache_UnlockVI(D->InstrName);
  442 + return(CACHERR);
  443 + }
  444 +
  445 + int i;
  446 + int j;
  447 + int PID = getpid();
  448 +
  449 + //Find existing data file in cache data and add current PID to client list
  450 + int dataFileIndex = -1;
  451 + for (i = 0; i < CASHLEN; ++i)
  452 + {
  453 + if (strcmp(cache_data->VIFiles[cacheVIIndex].dataFiles[i].name, dataFileName) == 0)
  454 + {
  455 + //Check if PID is already in the list of clients
  456 + for (j = 0; j < CACHE_MAXCLIENT; ++j)
  457 + {
  458 + if (cache_data->VIFiles[cacheVIIndex].dataFiles[i].clientPIDS[j] == PID)
  459 + {
  460 + dataFileIndex = i;
  461 + cache_data->VIFiles[cacheVIIndex].dataFiles[i].state = CACHE_USED;
  462 + break;
  463 + }
  464 + }
  465 + if (dataFileIndex >= 0)
  466 + break;
  467 + //Try to add PID in the list of clients
  468 + for (j = 0; j < CACHE_MAXCLIENT; ++j)
  469 + {
  470 + if (cache_data->VIFiles[cacheVIIndex].dataFiles[i].clientPIDS[j] == 0)
  471 + {
  472 + dataFileIndex = i;
  473 + cache_data->VIFiles[cacheVIIndex].dataFiles[i].clientPIDS[j] = PID;
  474 + cache_data->VIFiles[cacheVIIndex].dataFiles[i].state = CACHE_USED;
  475 + break;
  476 + }
  477 + }
  478 + if (dataFileIndex >= 0)
  479 + break;
  480 + //Try to find a not alive PID
  481 + for (j = 0; j < CACHE_MAXCLIENT; ++j)
  482 + {
  483 + if (Cache_PIDIsRunning(cache_data->VIFiles[cacheVIIndex].dataFiles[i].clientPIDS[j]) == 0)
  484 + {
  485 + //Replace by this PID
  486 + dataFileIndex = i;
  487 + cache_data->VIFiles[cacheVIIndex].dataFiles[i].clientPIDS[j] = PID;
  488 + cache_data->VIFiles[cacheVIIndex].dataFiles[i].state = CACHE_USED;
  489 + break;
  490 + }
  491 + }
  492 + if (dataFileIndex >= 0)
  493 + break;
  494 + //Too many client read this data file => wait and retry
  495 + Cache_UnlockVI(D->InstrName);
  496 + if(Verbose)
  497 + fprintf(stderr,"Cache_RequestDataFileAccess. Too many clients already access to %s.\n", dataFileName);
  498 + //Retry
  499 + //sleep(2);
  500 + return Cache_RequestDataFileAccess(D, dataFileName);
  501 + }
  502 + }
  503 +
  504 + if (dataFileIndex < 0)
  505 + {
  506 + //Data file not open by a client => try to find the older available slot
  507 + long minTime = -1;
  508 + for (i = 0; i < CASHLEN; ++i)
  509 + {
  510 + if (cache_data->VIFiles[cacheVIIndex].dataFiles[i].state == CACHE_NOTUSED)
  511 + {
  512 + if ((minTime > -1) && (minTime < D->Cash.times[i]))
  513 + continue;
  514 + dataFileIndex = i;
  515 + minTime = D->Cash.times[i];
  516 + }
  517 + }
  518 + if (dataFileIndex >= 0)
  519 + {
  520 + memset(cache_data->VIFiles[cacheVIIndex].dataFiles[dataFileIndex].clientPIDS, 0, CACHE_MAXCLIENT * sizeof(pid_t));
  521 + cache_data->VIFiles[cacheVIIndex].dataFiles[dataFileIndex].clientPIDS[0] = PID;
  522 + cache_data->VIFiles[cacheVIIndex].dataFiles[dataFileIndex].state = CACHE_USED;
  523 + strcpy(cache_data->VIFiles[cacheVIIndex].dataFiles[dataFileIndex].name, dataFileName);
  524 + }
  525 + }
  526 +
  527 + if (dataFileIndex < 0)
  528 + {
  529 + //Not available slot to open this data file => wait and retry
  530 + Cache_UnlockVI(D->InstrName);
  531 + if(Verbose)
  532 + fprintf(stderr,"Cache_RequestDataFileAccess. Not available slot to open data file %s.\n", dataFileName);
  533 + //Retry
  534 + //sleep(2);
  535 + return Cache_RequestDataFileAccess(D, dataFileName);
  536 + }
  537 +
  538 + if (strcmp(D->Cash.names[dataFileIndex], dataFileName) != 0)
  539 + {
  540 + if (D->Cash.names[dataFileIndex][0] != ' ')
  541 + {
  542 + //Compress old data file
  543 + Cache_CompressDataFile(D, D->Cash.names[dataFileIndex]);
  544 + }
  545 + //Decompress new data file
  546 + Cache_DecompressDataFile(D, dataFileName);
  547 +
  548 + size_t CashStart[2] = {0L,0L};
  549 + size_t CashCount[2] = {1L,MAXFILENAME};
  550 +
  551 + //Update cache table
  552 + strcpy(&(D->Cash.names[dataFileIndex][0]), dataFileName);
  553 + D->Cash.times[dataFileIndex] = time(NULL);
  554 + CashStart[0] = dataFileIndex;
  555 +
  556 + //Update cache file
  557 + int status; /* Error indicator */
  558 + status = nc_put_vara_text(D->Cash.ID, D->Cash.nameID,CashStart,CashCount,&(D->Cash.names[CashStart[0]][0]));
  559 + status = nc_put_vara_long(D->Cash.ID, D->Cash.timeID,CashStart,CashCount,&(D->Cash.times[CashStart[0]]));
  560 + if(status != NC_NOERR)
  561 + {
  562 + Cache_UnlockVI(D->InstrName);
  563 + D->LastFileStatus = CACHERR;
  564 + if(Verbose) fprintf(stderr,"Cache_RequestDataFileAccess. Error to write Name and Time to cash file, message: %s\n",nc_strerror(status));
  565 + return (CACHERR);
  566 + }
  567 + status = nc_sync(D->Cash.ID);
  568 + }
  569 + else
  570 + {
  571 + char FullName[PATHLENGTH];
  572 + strcpy(FullName,D->path);
  573 + strcat(FullName, dataFileName);
  574 + struct stat buffer;
  575 + if (stat (FullName, &buffer) != 0)
  576 + //Force decompression
  577 + Cache_DecompressDataFile(D, dataFileName);
  578 + }
  579 +
  580 + D->CurrCushN = dataFileIndex;
  581 +
  582 + if(Verbose) fprintf(stderr,"Cache_RequestDataFileAccess. Client get access to %s\n", dataFileName);
  583 +
  584 + Cache_UnlockVI(D->InstrName);
  585 + return (OK);
  586 +}
  587 +
  588 +/*
  589 + * Release the access to a specified data file for a client
  590 + */
  591 +int Cache_ReleaseDataFileAccess(DD_Var_t *D)
  592 +{
  593 + if (cache_data == NULL)
  594 + return(CACHERR);
  595 +
  596 + if (D->CurrCushN < 0)
  597 + {
  598 + if(Verbose) fprintf(stderr,"Cache_ReleaseDataFileAccess. WARNING : Nothing to release!\n");
  599 + return(OK);
  600 + }
  601 +
  602 + //Retrieve VI in cache data
  603 + int cacheVIIndex = Cache_GetAndLockVI(D->InstrName);
  604 +
  605 + //Refresh Cache Table in relation with the cache file
  606 + if (Cache_RefreshTable(D) != OK)
  607 + {
  608 + Cache_UnlockVI(D->InstrName);
  609 + return(CACHERR);
  610 + }
  611 +
  612 + int i;
  613 + int j;
  614 + int PID = getpid();
  615 + for (i = 0; i < CASHLEN; ++i)
  616 + {
  617 + if (strcmp(cache_data->VIFiles[cacheVIIndex].dataFiles[i].name, D->Cash.names[D->CurrCushN]) == 0)
  618 + {
  619 + if (i != D->CurrCushN)
  620 + {
  621 + //Incoherence !!
  622 + if(Verbose) fprintf(stderr,"Cache_ReleaseDataFileAccess. WARNING : Incoherence between cache file and cache data!\n");
  623 + }
  624 + //Try to find PID in clients list and update state flag
  625 + cache_data->VIFiles[cacheVIIndex].dataFiles[i].state = CACHE_NOTUSED;
  626 + for (j = 0; j < CACHE_MAXCLIENT; ++j)
  627 + {
  628 + if (cache_data->VIFiles[cacheVIIndex].dataFiles[i].clientPIDS[j] == PID)
  629 + {
  630 + //Remove PID to the list
  631 + cache_data->VIFiles[cacheVIIndex].dataFiles[i].clientPIDS[j] = 0;
  632 + if(Verbose) fprintf(stderr,"Cache_ReleaseDataFileAccess. Client release access to %s\n", D->Cash.names[D->CurrCushN]);
  633 + }
  634 + else if (cache_data->VIFiles[cacheVIIndex].dataFiles[i].clientPIDS[j] != 0)
  635 + cache_data->VIFiles[cacheVIIndex].dataFiles[i].state = CACHE_USED;
  636 + }
  637 + }
  638 + }
  639 +
  640 + D->CurrCushN = -1;
  641 +
  642 + Cache_UnlockVI(D->InstrName);
  643 +
  644 + return(OK);
  645 +}
  646 +
  647 +
  648 +
  649 +
  650 +
  651 +
... ...
src/SERVER/DD_CacheLock.c deleted
... ... @@ -1,143 +0,0 @@
1   -/*=====================================================================
2   - * DD SYSTEM base package
3   - * DD_Server library
4   - * DD_CacheLock.c
5   - * V.1.0
6   - * Last revision:
7   - * May 29 2015: Version 1.0. First implementation of a lock system for concurrent access to a virtual instrument
8   - */
9   -
10   -#include <stdio.h>
11   -#include <string.h>
12   -#include <sys/mman.h>
13   -#include <pthread.h>
14   -
15   -typedef struct
16   -{
17   - char VIID[30];
18   - pthread_mutex_t mutex;
19   -} CacheLockVI;
20   -
21   -#define NB_CACHELOCK_VI 30
22   -typedef struct
23   -{
24   - CacheLockVI cacheLockVI[NB_CACHELOCK_VI];
25   - pthread_mutex_t mutex;
26   -} CacheLockData;
27   -
28   -extern int Verbose;
29   -
30   -static CacheLockData* cachelock_data = NULL;
31   -
32   -/*
33   - * Init the shared memory used by the lock system
34   - */
35   -void CacheLock_Init()
36   -{
37   - if (cachelock_data != NULL)
38   - return;
39   -
40   - if(Verbose) fprintf(stderr,"CacheLock_Init\n");
41   -
42   - // place our shared data in shared memory
43   - int prot = PROT_READ | PROT_WRITE;
44   - int flags = MAP_SHARED | MAP_ANONYMOUS;
45   - cachelock_data = mmap(NULL, sizeof(CacheLockData), prot, flags, -1, 0);
46   -
47   - // initialise mutex so it works properly in shared memory
48   -
49   - // global mutex
50   - pthread_mutexattr_t attr;
51   - pthread_mutexattr_init(&attr);
52   - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
53   - pthread_mutex_init(&cachelock_data->mutex, &attr);
54   -
55   - int i;
56   - for (i = 0; i < NB_CACHELOCK_VI; ++i)
57   - {
58   - // virtual instrument mutex
59   - pthread_mutexattr_t attr;
60   - pthread_mutexattr_init(&attr);
61   - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
62   - pthread_mutex_init(&cachelock_data->cacheLockVI[i].mutex, &attr);
63   - }
64   -}
65   -
66   -/*
67   - * Free the shared memory used by the lock system
68   - */
69   -void CacheLock_Free()
70   -{
71   - if(Verbose) fprintf(stderr,"CacheLock_Free\n");
72   - if (cachelock_data != NULL)
73   - munmap(cachelock_data, sizeof(CacheLockData));
74   - cachelock_data = NULL;
75   -}
76   -
77   -/*
78   - * Get and lock the access to a virtual instrument
79   - */
80   -void CacheLock_Lock(char* VIID)
81   -{
82   - if (cachelock_data == NULL)
83   - return;
84   -
85   - int i;
86   - pthread_mutex_lock(&cachelock_data->mutex);
87   - for (i = 0; i < NB_CACHELOCK_VI; ++i)
88   - {
89   - if (strcmp(VIID, cachelock_data->cacheLockVI[i].VIID) == 0)
90   - {
91   - //A cache lock already exist for this VI
92   - //Try to get access
93   - pthread_mutex_lock(&cachelock_data->cacheLockVI[i].mutex);
94   - if(Verbose) fprintf(stderr,"CacheLock_Lock. %s is locked\n", VIID);
95   - pthread_mutex_unlock(&cachelock_data->mutex);
96   - return;
97   - }
98   - }
99   - pthread_mutex_unlock(&cachelock_data->mutex);
100   -
101   - //No cache lock exist for this VI
102   - //Try to find an available cache lock
103   - while (1)
104   - {
105   - pthread_mutex_lock(&cachelock_data->mutex);
106   - for (i = 0; i < NB_CACHELOCK_VI; ++i)
107   - {
108   - if (pthread_mutex_trylock(&cachelock_data->cacheLockVI[i].mutex) == 0)
109   - {
110   - //This cache lock is now used for this VIID
111   - strcpy(cachelock_data->cacheLockVI[i].VIID, VIID);
112   - if(Verbose) fprintf(stderr,"CacheLock_Lock. %s is locked\n", VIID);
113   - pthread_mutex_unlock(&cachelock_data->mutex);
114   - return;
115   - }
116   - }
117   - //No available cache lock for the moment
118   - if(Verbose) fprintf(stderr,"CacheLock_Lock. Cannot find an available cache lock for %s => Wait and retry later\n", VIID);
119   - pthread_mutex_unlock(&cachelock_data->mutex);
120   - sleep(2);
121   - }
122   -}
123   -
124   -/*
125   - * Unlock the access to a virtual instrument
126   - */
127   -void CacheLock_Unlock(char* VIID)
128   -{
129   - if (cachelock_data == NULL)
130   - return;
131   -
132   - int i;
133   - for (i = 0; i < NB_CACHELOCK_VI; ++i)
134   - {
135   - if (strcmp(VIID, cachelock_data->cacheLockVI[i].VIID) == 0)
136   - {
137   - if(Verbose) fprintf(stderr,"CacheLock_Unlock. %s is unlocked\n", VIID);
138   - pthread_mutex_unlock(&cachelock_data->cacheLockVI[i].mutex);
139   - return;
140   - }
141   - }
142   - if(Verbose) fprintf(stderr,"CacheLock_Unlock. Cannot unlock %s\n", VIID);
143   -}
src/SERVER/DD_GetData.c
... ... @@ -155,6 +155,7 @@ int OpenInstr(char *VInstrName)
155 155 DD_Var[id]->AttrData.Variables = NULL;
156 156 DD_Var[id]->ncID = -1;
157 157 DD_Var[id]->Maxnc_rec = 0;
  158 + DD_Var[id]->Cash.ID = -1;
158 159 strcpy(DD_Var[id]->path, RefVar[0]);
159 160  
160 161 /*----- Init control Flags ---------------*/
... ... @@ -183,28 +184,12 @@ int OpenInstr(char *VInstrName)
183 184 /**
184 185 if(Verbose) fprintf(stderr,"OpentInstr(%s): ID = %d, Atributes are resetted\n",VInstrName,id);
185 186 **/
186   -/* ----------------------------------------------------------------
187   - * Open "CACHE" file
188   - * -----------------------------------------------------------------*/
189   - status = nc_open(RefVar[3],NC_WRITE|NC_SHARE,&(DD_Var[id]->Cash.ID)); /* Cach file */
190   - if(status != NC_NOERR)
191   - {
192   - if(Verbose) fprintf(stderr,"OpentInstr(): open cash %s, message:%s\n",RefVar[3], nc_strerror(status));
193   - return(CACHERR);
194   - }
195   - status = nc_inq_varid(DD_Var[id]->Cash.ID,"name",&(DD_Var[id]->Cash.nameID));
196   - status = nc_inq_varid(DD_Var[id]->Cash.ID,"time",&(DD_Var[id]->Cash.timeID));
197   - status = nc_inq_varid(DD_Var[id]->Cash.ID,"fopen",&(DD_Var[id]->Cash.fopenID));
198   - DD_Var[id]->CurrCushN = -1;
199 187  
200   - if(status != NC_NOERR)
201   - {
202   - if(Verbose) fprintf(stderr,"OpentInstr(): %s\n",nc_strerror(status));
203   - return(CACHERR);
204   - }
205   -/**
206   - if(Verbose) fprintf(stderr,"OpentInstr(%s): ID = %d, Cache is open\n",VInstrName,id);
207   -**/
  188 +/* -------------------------------------------------------------------
  189 + * Set cache file path
  190 + */
  191 + strcpy(DD_Var[id]->Cash.CacheFilePath,RefVar[3]);
  192 +
208 193 /* ----------------------------------------------------------------
209 194 * Read Global timing and minimal gap from INFO file
210 195 * -----------------------------------------------------------------*/
... ... @@ -272,8 +257,6 @@ int CloseID(int ID)
272 257 */
273 258  
274 259 {
275   - size_t CashStart[2] = {0L,0L};
276   - size_t CashCount[2] = {1L,MAXFILENAME};
277 260 int status;
278 261 int i,il, count = 0;
279 262 /* Is this ID */
... ... @@ -289,21 +272,15 @@ int CloseID(int ID)
289 272 {
290 273 status = nc_close(DD_Var[ID]->ncID);
291 274 DD_Var[ID]->ncID = -1;
  275 + Cache_ReleaseDataFileAccess(DD_Var[ID]);
292 276 /**
293 277 if(Verbose) fprintf(stderr,"CloseID(%d): Data File is closed\n",ID);
294 278 **/
295 279 }
296   - if(DD_Var[ID]->Cash.ID >= 0)
297   - {
298   - status = nc_close(DD_Var[ID]->Cash.ID);
299   - DD_Var[ID]->Cash.ID = -1;
300   - if(Verbose)
301   - {
302   - if(DD_Var[ID]->CurrCushN >= 0)
303   - fprintf(stderr,"CloseID(%d): File %s, N %d closed\n",ID, &(DD_Var[ID]->Cash.names[DD_Var[ID]->CurrCushN][0]),DD_Var[ID]->CurrCushN);
304   - else fprintf(stderr,"CloseID(%d): cash closed\n",ID);
305   - }
306   - }
  280 + //Close cache file
  281 +
  282 + Cache_CloseFile(DD_Var[ID]);
  283 +
307 284 if(DD_Var[ID]->attrID >= 0)
308 285 {
309 286 status = nc_close(DD_Var[ID]->attrID);
... ...
src/SERVER/DD_Server.c
... ... @@ -578,13 +578,11 @@ void Serv(int SocketID)
578 578 /*------ Call data until LastPacket Flag (OK) returns --------*/
579 579 else do
580 580 {
581   - CacheLock_Lock(DD_Var[id]->InstrName);
582 581 err = GetMultiData(id,VarSize,VarNames,ReqTime,BackFlag);
583   - CacheLock_Unlock(DD_Var[id]->InstrName);
584 582 if(err >= 0)
585 583 {
586   - serr = SendDataPacket(DD_Var[id],SocketID,DD_Var[id]->LastPacketFlag); /* OK, MOREDATA, MOREDELAY */
587   - if(Verbose) fprintf(stderr, "Server:DATAGETRQ (ID=%d):GetMultiData->SentPackets\n", id);
  584 + serr = SendDataPacket(DD_Var[id],SocketID,DD_Var[id]->LastPacketFlag); /* OK, MOREDATA, MOREDELAY */
  585 + if(Verbose) fprintf(stderr, "Server:DATAGETRQ (ID=%d):GetMultiData->SentPackets\n", id);
588 586 }
589 587 }
590 588 while((err >= 0) && (DD_Var[id]->LastPacketFlag == MOREDATA));
... ... @@ -663,7 +661,7 @@ int main(int argc, char **argv)
663 661 else if(((argv[1])[1] == 'v') || ((argv[1])[1] == 'V')) Verbose = 1;
664 662 else Verbose = 0;
665 663  
666   - CacheLock_Init();
  664 + Cache_Init();
667 665  
668 666 if((ListenerID = SetListener()) < 0)
669 667 {
... ... @@ -702,7 +700,7 @@ int main(int argc, char **argv)
702 700  
703 701 close(ListenerID);
704 702  
705   - CacheLock_Free();
  703 + Cache_Free();
706 704  
707 705 return 0;
708 706 }
... ...
src/SERVER/ncfileop.c
... ... @@ -32,21 +32,21 @@ extern int Verbose;
32 32 *===========================================================*/
33 33 int CloseOldFile(DD_Var_t *D)
34 34 {
35   - size_t CashStart[2] = {0L,0L};
36   - size_t CashCount[2] = {1L,MAXFILENAME};
37 35 int status;
38 36  
39 37 if(D->Maxnc_rec > 0)
40 38 {
41 39 status = nc_close(D->ncID);
  40 + char name[MAXFILENAME];
  41 + strcpy(name,D->Cash.names[D->CurrCushN]);
  42 + Cache_ReleaseDataFileAccess(D);
42 43 if(status < 0)
43 44 {
44 45 D->LastFileStatus = DATAFILEERR;
45   - if(Verbose) fprintf(stderr,"CloseOldFile: file %s, error while closed\n",&(D->Cash.names[D->CurrCushN][0]),D->CurrCushN);
  46 + if(Verbose) fprintf(stderr,"CloseOldFile: file %s, error while closed, message : \n", name, nc_strerror(status));
46 47 return DATAFILEERR;
47 48 }
48   - if(Verbose) fprintf(stderr,"CloseOldFile: file %s, %d closed\n",&(D->Cash.names[D->CurrCushN][0]),D->CurrCushN);
49   - D->CurrCushN = -1;
  49 + if(Verbose) fprintf(stderr,"CloseOldFile: file %s closed\n", name);
50 50 D->Maxnc_rec = 0;
51 51 }
52 52 else if(Verbose) fprintf(stderr,"CloseOldFile: Nothing To close\n");
... ... @@ -77,8 +77,6 @@ int SetNewFile(DD_Var_t *D, int N)
77 77 */
78 78 {
79 79 static char TimeDimName[] = "Time";
80   - static size_t CashStart[2] = {0L,0L};
81   - static size_t CashCount[2] = {1L,MAXFILENAME};
82 80 static size_t TimeCount[2] = {1,TIMELENGTH};
83 81  
84 82 char Name[MAXFILENAME]; /* Name of data nc file */
... ... @@ -204,31 +202,6 @@ int SetNewFile(DD_Var_t *D, int N)
204 202 } /* else just continue */
205 203 }
206 204 }
207   -
208   -/*-------------- refresh the Cache table ---------------------------*/
209   - status = nc_sync(D->Cash.ID);
210   - if(status != NC_NOERR)
211   - {
212   - if(Verbose) fprintf(stderr,"SetNewFile(): Cache Synchro: %s\n",nc_strerror(status));
213   - return CACHERR;
214   - }
215   - for(CashStart[0] = 0; CashStart[0] < CASHLEN; CashStart[0]++)
216   - {
217   - status = nc_get_vara_text(D->Cash.ID, D->Cash.nameID,CashStart,CashCount,D->Cash.names[CashStart[0]]);
218   - if(status != NC_NOERR)
219   - {
220   - if(Verbose) fprintf(stderr,"SetNewFile(): Cache Names: %s\n",nc_strerror(status));
221   - D->LastFileStatus = CACHERR;
222   - return CACHERR;
223   - }
224   - status = nc_get_vara_long(D->Cash.ID, D->Cash.timeID,CashStart,CashCount,&(D->Cash.times[CashStart[0]]));
225   - if(status != NC_NOERR)
226   - {
227   - if(Verbose) fprintf(stderr,"SetNewFile(): Cache Times %s\n",nc_strerror(status));
228   - D->LastFileStatus = CACHERR;
229   - return CACHERR;
230   - }
231   - }
232 205  
233 206 /*----------- Close the old file ----------------------*/
234 207 if((status = CloseOldFile(D)) < 0) return DATAFILEERR;
... ... @@ -237,141 +210,17 @@ int SetNewFile(DD_Var_t *D, int N)
237 210 strcpy(FullName+strlen(D->path), Name);
238 211 // if(Verbose) fprintf(stderr,"SetNewFile(): New file to open: %s\n",FullName);
239 212  
240   - NewAttempt = 0;
  213 + //Request data file access to the cache manager
  214 + if (Cache_RequestDataFileAccess(D, Name) != OK)
  215 + return (CACHERR);
241 216  
242   - while (NewAttempt < 3)
243   - {
244   - /*----- Search the new requested file in the cache and the oldest file ----------*/
245   - FileNumber = 0;
246   - CurrentTime = time(NULL); Find = 0; OldestNumber = -1;
247   -
248   - while((FileNumber < CASHLEN) && // Cache is finished
249   - ((Find = strcmp(&(D->Cash.names[FileNumber][0]),Name)) != 0) && // File is already in the Cache
250   - (D->Cash.names[FileNumber][0] != ' ')) // There is empty space
251   - {
252   - if((D->Cash.times[FileNumber] < (CurrentTime - FILEACCMARG) ) && (OldestNumber == -1)) OldestNumber = FileNumber;
253   - dltt = (int)(D->Cash.times[OldestNumber] - D->Cash.times[FileNumber]);
254   - if(dltt > 0) OldestNumber = FileNumber;
255   - FileNumber++;
256   - }
257   -
258   - /* ====================================================
259   - * Sometimes it is possible, that:
260   - * 1) No corresponding file in the cache (Find != 0)
261   - * 2) The oldest file is not found (OldestNumber == -1)
262   - * 3) cach is full (FileNumber == CASHLEN)
263   - * Then we need to repeat the search after one sec delay
264   - *==================================================== */
265   - if((Find != 0) && (FileNumber == CASHLEN) && (OldestNumber == -1))
266   - {
267   - NewAttempt++;
268   - sleep((unsigned )(FILEACCMARG));
269   -
270   - if (Verbose)
271   - fprintf(stderr,"Waiting %d secs to get the Oldest File\n", FILEACCMARG);
272   -
273   - } else NewAttempt = 3;
274   - }
275   -
276   -//---------- Parsing resultat of search -------------
277   -// if(Verbose)
278   -// {
279   -// if(OldestNumber > -1) fprintf(stderr,"SetNewFile(): Search: Is Oldest File %d %d %d\n", OldestNumber,D->Cash.times[OldestNumber],CurrentTime);
280   -// else fprintf(stderr,"SetNewFile(): Search: No Oldest File %d %d\n", OldestNumber,CurrentTime);
281   -// }
282   -
283   - if(Find != 0)
284   -/*---------------- No request file in the CACHE ----------------------*/
285   - {
286   - if(FileNumber < CASHLEN)
287   - {
288   - if(D->Cash.names[FileNumber][0] == ' ') /* There is empty space in the table */
289   - {
290   - strcpy(command, "gunzip -c ");
291   - strcat(command, FullName);
292   - strcat(command, ".gz > ");
293   - strcat(command, FullName);
294   - system(command); /* File is unzipped */
295   - sprintf(command, "chmod g+w %s\0",FullName);
296   - system(command); /* File is unzipped */
297   -
298   - strcpy(&(D->Cash.names[FileNumber][0]),Name);
299   - D->Cash.times[FileNumber] = CurrentTime;
300   - CashStart[0] = FileNumber;
301   - D->CurrCushN = FileNumber;
302   - }
303   - else
304   - {
305   - D->LastFileStatus = CACHERR;
306   - return CACHERR; /* Unrecoverable error */
307   - }
308   - }
309   - else /* No empty space. It is necessury to remove one file */
310   - {
311   - if (OldestNumber > -1) //------ Oldest file is found -------
312   - {
313   - strcpy(command, "gunzip -c ");
314   - strcat(command, FullName);
315   - strcat(command, ".gz > ");
316   - strcat(command, FullName);
317   - system(command); /* File is unzipped */
318   - sprintf(command, "chmod g+w %s\0",FullName);
319   - system(command); /* File is unzipped */
320   -
321   - strcpy(command, "rm ");
322   - strcat(command,D->path);
323   - strcat(command,&(D->Cash.names[OldestNumber][0]));
324   - strcat(command, " &");
325   - system(command); /* Old file removed */
326   - strcpy(&(D->Cash.names[OldestNumber][0]),Name);
327   - D->Cash.times[OldestNumber] = CurrentTime;
328   - CashStart[0] = OldestNumber;
329   - D->CurrCushN = OldestNumber;
330   - }
331   - else {
332   - if(Verbose) fprintf(stderr,"SetNewFile(): return CACHTOOREC\n");
333   - D->LastFileStatus = CACHTOOREC;
334   - D->TimeRecNumber -= N;
335   - return CACHTOOREC; //----- Say client that all files are too new
336   - }
337   - }
338   - /*------------ The place for new cache is found --------------*/
339   - status = nc_put_vara_text(D->Cash.ID, D->Cash.nameID,CashStart,CashCount,&(D->Cash.names[CashStart[0]][0]));
340   - status = nc_put_vara_long(D->Cash.ID, D->Cash.timeID,CashStart,CashCount,&(D->Cash.times[CashStart[0]]));
341   - if(status != NC_NOERR)
342   - {
343   - if(Verbose) fprintf(stderr,"SetNewFile(): Write Name and Time to cash: %s\n",nc_strerror(status));
344   - D->LastFileStatus = CACHERR;
345   - return CACHERR;
346   - }
347   - status = nc_sync(D->Cash.ID);
348   - }
349   -//------------------ There is FILE already in the CACHE --------------
350   - else /*------- The requested file is already in the cache just refresh the time */
351   - {
352   - CashStart[0] = FileNumber;
353   - D->Cash.times[FileNumber] = CurrentTime; /* refresh the time */
354   - D->CurrCushN = FileNumber;
355   - status = nc_put_vara_long(D->Cash.ID, D->Cash.timeID,CashStart,CashCount,&(D->Cash.times[CashStart[0]]));
356   - if(status != NC_NOERR)
357   - {
358   - if(Verbose) fprintf(stderr,"SetNewFile(): File In Cache: %s\n",nc_strerror(status));
359   - D->LastFileStatus = CACHERR;
360   - return CACHERR;
361   - }
362   - status = nc_sync(D->Cash.ID);
363   - }
364 217  
365   -// if(Verbose) fprintf(stderr,"SetNewFile(): file %s, %d to be open\n",FullName,D->CurrCushN);
366   -
367   -
368   -/*--------------- CACHE refreshed and requested file is unzipped ------------------------*/
369 218 /*----------------- Open requested file -----------------------------------------------*/
370 219  
371 220 status = nc_open(FullName,NC_NOWRITE,&(D->ncID));
372 221 if(status != NC_NOERR)
373 222 {
374   - if(Verbose) fprintf(stderr,"SetNewFile(): Error while File Open: %s\n",nc_strerror(status));
  223 + if(Verbose) fprintf(stderr,"SetNewFile(): Error while File Open: %s, message : %s\n", Name, nc_strerror(status));
375 224 D->LastFileStatus =DATAFILEERR ;
376 225 return DATAFILEERR;
377 226 }
... ... @@ -496,3 +345,4 @@ size_t MaxRecord(int ncID)
496 345 }
497 346 /*----------------------------------------------------------------------*/
498 347  
  348 +
... ...