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,7 +183,9 @@
183 */ 183 */
184 184
185 /*-------------------- TYPEDEF ---------------------------*/ 185 /*-------------------- TYPEDEF ---------------------------*/
186 -typedef struct { char names[CASHLEN][MAXSETLENGTH]; 186 +typedef struct {
  187 + char CacheFilePath[PATHLENGTH];
  188 + char names[CASHLEN][MAXSETLENGTH];
187 long times[CASHLEN]; 189 long times[CASHLEN];
188 int FileOpen[CASHLEN]; /* 1 if file is open */ 190 int FileOpen[CASHLEN]; /* 1 if file is open */
189 int ID; /* ID of open cach file */ 191 int ID; /* ID of open cach file */
@@ -275,24 +277,29 @@ enum LockStatus {NOLOCK, LOCKED, LOCKREMOVED}; @@ -275,24 +277,29 @@ enum LockStatus {NOLOCK, LOCKED, LOCKREMOVED};
275 extern int OpenInstr(char *InstrName); 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 * Open Virtual instrument by name and returns the ID 305 * Open Virtual instrument by name and returns the ID
@@ -357,6 +364,7 @@ size_t MaxRecord(int ncID); @@ -357,6 +364,7 @@ size_t MaxRecord(int ncID);
357 * Inspect all variables and dimensions of the file (exept Time associated) and 364 * Inspect all variables and dimensions of the file (exept Time associated) and
358 * returm maximal record number to transmit 365 * returm maximal record number to transmit
359 */ 366 */
  367 +
360 /*------------------ Global constants ----------------------------------*/ 368 /*------------------ Global constants ----------------------------------*/
361 static u_int xdrlen[] = {4,4,4,8,4}; 369 static u_int xdrlen[] = {4,4,4,8,4};
362 static size_t unixlen[] = {sizeof(char),sizeof(int),sizeof(float),sizeof(double),sizeof(short)}; 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 @@ @@ -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,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,6 +155,7 @@ int OpenInstr(char *VInstrName)
155 DD_Var[id]->AttrData.Variables = NULL; 155 DD_Var[id]->AttrData.Variables = NULL;
156 DD_Var[id]->ncID = -1; 156 DD_Var[id]->ncID = -1;
157 DD_Var[id]->Maxnc_rec = 0; 157 DD_Var[id]->Maxnc_rec = 0;
  158 + DD_Var[id]->Cash.ID = -1;
158 strcpy(DD_Var[id]->path, RefVar[0]); 159 strcpy(DD_Var[id]->path, RefVar[0]);
159 160
160 /*----- Init control Flags ---------------*/ 161 /*----- Init control Flags ---------------*/
@@ -183,28 +184,12 @@ int OpenInstr(char *VInstrName) @@ -183,28 +184,12 @@ int OpenInstr(char *VInstrName)
183 /** 184 /**
184 if(Verbose) fprintf(stderr,"OpentInstr(%s): ID = %d, Atributes are resetted\n",VInstrName,id); 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 * Read Global timing and minimal gap from INFO file 194 * Read Global timing and minimal gap from INFO file
210 * -----------------------------------------------------------------*/ 195 * -----------------------------------------------------------------*/
@@ -272,8 +257,6 @@ int CloseID(int ID) @@ -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 int status; 260 int status;
278 int i,il, count = 0; 261 int i,il, count = 0;
279 /* Is this ID */ 262 /* Is this ID */
@@ -289,21 +272,15 @@ int CloseID(int ID) @@ -289,21 +272,15 @@ int CloseID(int ID)
289 { 272 {
290 status = nc_close(DD_Var[ID]->ncID); 273 status = nc_close(DD_Var[ID]->ncID);
291 DD_Var[ID]->ncID = -1; 274 DD_Var[ID]->ncID = -1;
  275 + Cache_ReleaseDataFileAccess(DD_Var[ID]);
292 /** 276 /**
293 if(Verbose) fprintf(stderr,"CloseID(%d): Data File is closed\n",ID); 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 if(DD_Var[ID]->attrID >= 0) 284 if(DD_Var[ID]->attrID >= 0)
308 { 285 {
309 status = nc_close(DD_Var[ID]->attrID); 286 status = nc_close(DD_Var[ID]->attrID);
src/SERVER/DD_Server.c
@@ -578,13 +578,11 @@ void Serv(int SocketID) @@ -578,13 +578,11 @@ void Serv(int SocketID)
578 /*------ Call data until LastPacket Flag (OK) returns --------*/ 578 /*------ Call data until LastPacket Flag (OK) returns --------*/
579 else do 579 else do
580 { 580 {
581 - CacheLock_Lock(DD_Var[id]->InstrName);  
582 err = GetMultiData(id,VarSize,VarNames,ReqTime,BackFlag); 581 err = GetMultiData(id,VarSize,VarNames,ReqTime,BackFlag);
583 - CacheLock_Unlock(DD_Var[id]->InstrName);  
584 if(err >= 0) 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 while((err >= 0) && (DD_Var[id]->LastPacketFlag == MOREDATA)); 588 while((err >= 0) && (DD_Var[id]->LastPacketFlag == MOREDATA));
@@ -663,7 +661,7 @@ int main(int argc, char **argv) @@ -663,7 +661,7 @@ int main(int argc, char **argv)
663 else if(((argv[1])[1] == 'v') || ((argv[1])[1] == 'V')) Verbose = 1; 661 else if(((argv[1])[1] == 'v') || ((argv[1])[1] == 'V')) Verbose = 1;
664 else Verbose = 0; 662 else Verbose = 0;
665 663
666 - CacheLock_Init(); 664 + Cache_Init();
667 665
668 if((ListenerID = SetListener()) < 0) 666 if((ListenerID = SetListener()) < 0)
669 { 667 {
@@ -702,7 +700,7 @@ int main(int argc, char **argv) @@ -702,7 +700,7 @@ int main(int argc, char **argv)
702 700
703 close(ListenerID); 701 close(ListenerID);
704 702
705 - CacheLock_Free(); 703 + Cache_Free();
706 704
707 return 0; 705 return 0;
708 } 706 }
src/SERVER/ncfileop.c
@@ -32,21 +32,21 @@ extern int Verbose; @@ -32,21 +32,21 @@ extern int Verbose;
32 *===========================================================*/ 32 *===========================================================*/
33 int CloseOldFile(DD_Var_t *D) 33 int CloseOldFile(DD_Var_t *D)
34 { 34 {
35 - size_t CashStart[2] = {0L,0L};  
36 - size_t CashCount[2] = {1L,MAXFILENAME};  
37 int status; 35 int status;
38 36
39 if(D->Maxnc_rec > 0) 37 if(D->Maxnc_rec > 0)
40 { 38 {
41 status = nc_close(D->ncID); 39 status = nc_close(D->ncID);
  40 + char name[MAXFILENAME];
  41 + strcpy(name,D->Cash.names[D->CurrCushN]);
  42 + Cache_ReleaseDataFileAccess(D);
42 if(status < 0) 43 if(status < 0)
43 { 44 {
44 D->LastFileStatus = DATAFILEERR; 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 return DATAFILEERR; 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 D->Maxnc_rec = 0; 50 D->Maxnc_rec = 0;
51 } 51 }
52 else if(Verbose) fprintf(stderr,"CloseOldFile: Nothing To close\n"); 52 else if(Verbose) fprintf(stderr,"CloseOldFile: Nothing To close\n");
@@ -77,8 +77,6 @@ int SetNewFile(DD_Var_t *D, int N) @@ -77,8 +77,6 @@ int SetNewFile(DD_Var_t *D, int N)
77 */ 77 */
78 { 78 {
79 static char TimeDimName[] = "Time"; 79 static char TimeDimName[] = "Time";
80 - static size_t CashStart[2] = {0L,0L};  
81 - static size_t CashCount[2] = {1L,MAXFILENAME};  
82 static size_t TimeCount[2] = {1,TIMELENGTH}; 80 static size_t TimeCount[2] = {1,TIMELENGTH};
83 81
84 char Name[MAXFILENAME]; /* Name of data nc file */ 82 char Name[MAXFILENAME]; /* Name of data nc file */
@@ -204,31 +202,6 @@ int SetNewFile(DD_Var_t *D, int N) @@ -204,31 +202,6 @@ int SetNewFile(DD_Var_t *D, int N)
204 } /* else just continue */ 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 /*----------- Close the old file ----------------------*/ 206 /*----------- Close the old file ----------------------*/
234 if((status = CloseOldFile(D)) < 0) return DATAFILEERR; 207 if((status = CloseOldFile(D)) < 0) return DATAFILEERR;
@@ -237,141 +210,17 @@ int SetNewFile(DD_Var_t *D, int N) @@ -237,141 +210,17 @@ int SetNewFile(DD_Var_t *D, int N)
237 strcpy(FullName+strlen(D->path), Name); 210 strcpy(FullName+strlen(D->path), Name);
238 // if(Verbose) fprintf(stderr,"SetNewFile(): New file to open: %s\n",FullName); 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 /*----------------- Open requested file -----------------------------------------------*/ 218 /*----------------- Open requested file -----------------------------------------------*/
370 219
371 status = nc_open(FullName,NC_NOWRITE,&(D->ncID)); 220 status = nc_open(FullName,NC_NOWRITE,&(D->ncID));
372 if(status != NC_NOERR) 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 D->LastFileStatus =DATAFILEERR ; 224 D->LastFileStatus =DATAFILEERR ;
376 return DATAFILEERR; 225 return DATAFILEERR;
377 } 226 }
@@ -496,3 +345,4 @@ size_t MaxRecord(int ncID) @@ -496,3 +345,4 @@ size_t MaxRecord(int ncID)
496 } 345 }
497 /*----------------------------------------------------------------------*/ 346 /*----------------------------------------------------------------------*/
498 347
  348 +