Commit 58faca3ff01761c84934a5c597366332754815b4
1 parent
e9c962b4
Exists in
master
and in
10 other branches
First implementation of new cache system
Showing
6 changed files
with
693 additions
and
352 deletions
Show diff stats
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)}; |
@@ -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 | + |