source: branches/prototype-v0/zoo-project/zoo-kernel/service_internal.c @ 877

Last change on this file since 877 was 877, checked in by djay, 6 years ago

Fixes for supporting properly the memory=protect which force the ZOO-Kernel to not store any downloaded files in memory. Add footer to the HPC support. Fix the autotools to build service_json and sshapi only when required so, when HPC support is activated, this also avoid adding too much dependencies at compilation time. Store md5 of the downloaded files to avoid uploading on HPC server the same file more than once, in case the md5 correspond.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 27.2 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2009-2018 GeoLabs SARL
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#define _LARGEFILE64_SOURCE 1
26#ifdef USE_MS
27#include "service_internal_ms.h"
28#else
29#include "cpl_vsi.h"
30#endif
31#include "service_internal.h"
32
33#ifndef TRUE
34#define TRUE 1
35#endif
36#ifndef FALSE
37#define FALSE -1
38#endif
39
40#ifdef WIN32
41// cf. https://stackoverflow.com/questions/3168504/lockfileex-read-write-upgrade-downgrade
42// only works for (SEEK_SET, start=0, len=0) file locking.
43__inline int fcntl(int fd, int cmd, ...)
44{
45    va_list a;
46    va_start(a, cmd);
47    switch(cmd)
48    {
49    case F_SETLK:
50        {
51            struct flock *l = va_arg(a, struct flock*);
52            switch(l->l_type)
53            {
54            case F_RDLCK:
55                {
56                    LPOVERLAPPED o = { 0 };
57                    HANDLE h = (HANDLE)_get_osfhandle(fd);
58                    if (l->l_whence != SEEK_SET || l->l_start != 0 || l->l_len != 0)
59                    {
60                        _set_errno(ENOTSUP);
61                        return -1;
62                    }
63                    if (!LockFileEx(h, LOCKFILE_FAIL_IMMEDIATELY, 0, 0, 1, o)) // read lock
64                    {
65                        unsigned long x = GetLastError();
66                        _set_errno(GetLastError() == ERROR_LOCK_VIOLATION ? EAGAIN : EBADF);
67                        return -1;
68                    }
69                    UnlockFile(h, 0, 0, 1, 1); // write lock
70                }
71                break;
72            case F_WRLCK:
73                {
74                    LPOVERLAPPED o = { 0 };
75                    HANDLE h = (HANDLE)_get_osfhandle(fd);
76                    if (l->l_whence != SEEK_SET || l->l_start != 0 || l->l_len != 0)
77                    {
78                        _set_errno(ENOTSUP);
79                        return -1;
80                    }
81                    if (!LockFileEx(h, LOCKFILE_FAIL_IMMEDIATELY|LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 1, o)) // write lock
82                    {
83                        unsigned long x = GetLastError();
84                        _set_errno(GetLastError() == ERROR_LOCK_VIOLATION ? EAGAIN : EBADF);
85                        return -1;
86                    }
87                    UnlockFile(h, 0, 0, 0, 1); // read lock
88                }
89                break;
90            case F_UNLCK:
91                {
92                    HANDLE h = (HANDLE)_get_osfhandle(fd);
93                    if (l->l_whence != SEEK_SET || l->l_start != 0 || l->l_len != 0)
94                    {
95                        _set_errno(ENOTSUP);
96                        return -1;
97                    }
98                    UnlockFile(h, 0, 0, 0, 1); // read lock
99                    UnlockFile(h, 0, 0, 1, 1); // write lock
100                }
101                break;
102            default:
103                _set_errno(ENOTSUP);
104                return -1;
105            }
106        }
107        break;
108    case F_SETLKW:
109        {
110            struct flock *l = va_arg(a, struct flock*);
111            switch(l->l_type)
112            {
113            case F_RDLCK:
114                {
115                    LPOVERLAPPED o = { 0 };
116                    HANDLE h = (HANDLE)_get_osfhandle(fd);
117                    if (l->l_whence != SEEK_SET || l->l_start != 0 || l->l_len != 0)
118                    {
119                        _set_errno(ENOTSUP);
120                        return -1;
121                    }
122                    if(!LockFileEx(h, 0, 0, 0, 1, o)) // read lock
123                    {
124                        unsigned long x = GetLastError();
125                        return -1;
126                    }
127                    UnlockFile(h, 0, 0, 1, 1); // write lock
128                }
129                break;
130            case F_WRLCK:
131                {
132                    LPOVERLAPPED o = { 0 };
133                    HANDLE h = (HANDLE)_get_osfhandle(fd);
134                    if (l->l_whence != SEEK_SET || l->l_start != 0 || l->l_len != 0)
135                    {
136                        _set_errno(ENOTSUP);
137                        return -1;
138                    }
139                    if (!LockFileEx(h, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 1, o)) // write lock
140                    {
141                        unsigned long x = GetLastError();
142                        return -1;
143                    }
144                    UnlockFile(h, 0, 0, 0, 1); // read lock
145                }
146                break;
147            case F_UNLCK:
148                {
149                    flock *l = va_arg(a, flock*);
150                    HANDLE h = (HANDLE)_get_osfhandle(fd);
151                    if (l->l_whence != SEEK_SET || l->l_start != 0 || l->l_len != 0)
152                    {
153                        _set_errno(ENOTSUP);
154                        return -1;
155                    }
156                    UnlockFile(h, 0, 0, 0, 1); // read lock
157                    UnlockFile(h, 0, 0, 1, 1); // write lock
158                }
159                break;
160            default:
161                _set_errno(ENOTSUP);
162                return -1;
163            }
164        }
165        break;
166    default:
167        _set_errno(ENOTSUP);
168        return -1;
169    }
170
171    return 0;
172}
173#endif
174
175#define ERROR_MSG_MAX_LENGTH 1024
176
177/**
178 * Lock a file for read, write and upload.
179 * @param conf the main configuration maps
180 * @param filename the file to lock
181 * @param mode define access: 'r' for read, 'w' for write
182 * @return a new zooLock structure on sucess, NULL on failure
183 */
184struct zooLock* lockFile(maps* conf,const char* filename,const char mode){
185  struct stat f_status;
186  int itn=0;
187  int s;
188  struct zooLock* myLock=(struct zooLock*)malloc(sizeof(struct flock)+sizeof(FILE*)+sizeof(char*));
189  int len=6;
190  char *myTemplate="%s.lock";
191  int res=-1;
192 retryLockFile:
193  myLock->filename=(char*)malloc((strlen(filename)+len)*sizeof(char));
194  sprintf(myLock->filename,myTemplate,filename);
195  s=stat(myLock->filename, &f_status);
196  if(s==0 && mode!='r'){
197    if(itn<ZOO_LOCK_MAX_RETRY){
198      itn++;
199      fprintf(stderr,"(%d) Wait for write lock on %s, tried %d times (sleep) ... \n",getpid(),myLock->filename,itn);
200      fflush(stderr);
201      zSleep(5);
202      free(myLock->filename);
203      goto retryLockFile;
204    }else{
205      free(myLock->filename);
206      free(myLock);
207      return NULL;
208    }
209  }else{
210    char local_mode[3];
211    memset(local_mode,0,3);
212    if(mode=='w')
213      sprintf(local_mode,"%c+",mode);
214    else
215      sprintf(local_mode,"%c",mode);
216    myLock->lockfile=fopen(myLock->filename,local_mode);
217    char tmp[512];
218    sprintf(tmp,"%d",getpid());
219    if(myLock->lockfile==NULL){
220      myLock->lockfile=fopen(myLock->filename,"w+");
221      fwrite(tmp,sizeof(char),strlen(tmp),myLock->lockfile);
222      fflush(myLock->lockfile);
223      fclose(myLock->lockfile);
224      myLock->lockfile=fopen(myLock->filename,local_mode);
225    }/*else
226       fprintf(stderr,"%s %d %d\n",__FILE__,__LINE__,(myLock->lockfile==NULL));*/
227    if(mode!='r'){
228      fwrite(tmp,sizeof(char),strlen(tmp),myLock->lockfile);
229      fflush(myLock->lockfile);
230    }
231    int cnt=0;
232    if(mode=='r'){
233      myLock->lock.l_type = F_RDLCK;
234    }else
235      myLock->lock.l_type = F_WRLCK;
236    myLock->lock.l_whence = 0;
237    myLock->lock.l_start = 0;
238    myLock->lock.l_len = strlen(tmp)*sizeof(char);
239    while (true) {
240      if((res=fcntl(fileno(myLock->lockfile), F_SETLK, &(myLock->lock)))==-1 &&
241         (errno==EAGAIN || errno==EACCES)){
242          if(cnt >= ZOO_LOCK_MAX_RETRY){
243            char message[51];     
244            sprintf(message,"Unable to get the lock after %d attempts.\n",cnt);
245            setMapInMaps(conf,"lenv","message",message);
246            fclose(myLock->lockfile);
247            free(myLock->filename);
248            free(myLock);
249            return NULL;
250          }
251          fprintf(stderr,"(%d) Wait for lock on  %s, tried %d times ... \n",getpid(),myLock->filename,cnt);
252          fflush(stderr);
253          zSleep(1);
254          cnt++;
255        }else
256           break;
257    }
258    if(res<0){
259      char *tmp;
260      if(errno==EBADF)
261        tmp="Either: the filedes argument is invalid; you requested a read lock but the filedes is not open for read access; or, you requested a write lock but the filedes is not open for write access.";
262      else
263        if(errno==EINVAL)
264          tmp="Either the lockp argument doesn’t specify valid lock information, or the file associated with filedes doesn’t support locks.";
265        else
266          tmp="The system has run out of file lock resources; there are already too many file locks in place.";
267      fprintf(stderr,"Unable to get the lock on %s due to the following error: %s\n",myLock->filename,tmp);
268      return NULL;
269    }
270    return myLock;
271  }
272}
273
274/**
275 * Remove a lock.
276 * @param conf the main configuration maps
277 * @param s the zooLock structure
278 * @return 0 on success, -1 on failure.
279 */
280int unlockFile(maps* conf,struct zooLock* s){
281  int res=-1;
282  if(s!=NULL){
283    s->lock.l_type = F_UNLCK;
284    res=fcntl(fileno(s->lockfile), F_SETLK, &s->lock);
285    if(res==-1)
286      return res;
287    // Check if there is any process locking a file and delete the lock if not.
288    s->lock.l_type = F_WRLCK;
289    if(fcntl(fileno(s->lockfile), F_GETLK, &s->lock)!=-1 && s->lock.l_type == F_UNLCK){
290      unlink(s->filename);
291    }
292    fclose(s->lockfile);
293    free(s->filename);
294    free(s);
295  }
296  return res;
297}
298
299#ifndef RELY_ON_DB
300#include "dirent.h"
301
302/**
303 * Read the sid file attached of a service if any
304 *
305 * @param conf the maps containing the setting of the main.cfg file
306 * @param pid the service identifier (usid key from the [lenv] section)
307 * @return the reported status char* (temporary/final result)
308 */
309char* getStatusId(maps* conf,char* pid){
310  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
311  char* fbkpid =
312    (char *)
313    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
314  sprintf (fbkpid, "%s/%s.sid", r_inputs->value, pid);
315  FILE* f0 = fopen (fbkpid, "r");
316  if(f0!=NULL){
317    long flen;
318    char *fcontent;
319    fseek (f0, 0, SEEK_END);
320    flen = ftell (f0);
321    fseek (f0, 0, SEEK_SET);
322    fcontent = (char *) malloc ((flen + 1) * sizeof (char));
323    fread(fcontent,flen,1,f0);
324    fcontent[flen]=0;
325    fclose(f0);
326    return fcontent;
327  }else
328    return NULL;
329}
330
331/**
332 * Acquire the global lock
333 *
334 * @param conf the maps containing the setting of the main.cfg file
335 * @return a semid
336 */
337semid acquireLock(maps* conf){
338  semid lockid;
339  int itn=0;
340 toRetry1:
341  lockid=getShmLockId(conf,1);
342  if(
343#ifdef WIN32
344     lockid==NULL
345#else
346     lockid<0
347#endif
348     ){
349#ifdef WIN32
350    return NULL;
351#else
352    return -1;
353#endif
354  }
355  if(lockShm(lockid)<0){
356#ifdef WIN32
357      return NULL;
358#else
359    if(itn<ZOO_LOCK_MAX_RETRY){
360      itn++;
361      goto toRetry1;
362    }else
363      return -1;
364#endif
365  }else
366    return lockid;
367}
368
369/**
370 * Read the cache file of a running service
371 *
372 * @param conf the maps containing the setting of the main.cfg file
373 * @param pid the service identifier (usid key from the [lenv] section)
374 * @return the reported status char* (temporary/final result)
375 */
376char* _getStatusFile(maps* conf,char* pid){
377  map* tmpTmap = getMapFromMaps (conf, "main", "tmpPath");
378
379  struct dirent *dp;
380  DIR *dirp = opendir(tmpTmap->value);
381  char fileName[1024];
382  int hasFile=-1;
383  if(dirp!=NULL){
384    char tmp[128];
385    sprintf(tmp,"_%s.xml",pid);
386    while ((dp = readdir(dirp)) != NULL){
387#ifdef DEBUG
388      fprintf(stderr,"File : %s searched : %s\n",dp->d_name,tmp);
389#endif
390      if(strstr(dp->d_name,"final_")==0 && strstr(dp->d_name,tmp)!=0){
391        sprintf(fileName,"%s/%s",tmpTmap->value,dp->d_name);
392        hasFile=1;
393        break;
394      }
395    }
396  }
397  if(hasFile>0){
398    semid lockid;
399    char* stat=getStatusId(conf,pid);
400    if(stat!=NULL){
401      setMapInMaps(conf,"lenv","lid",stat);
402      lockid=acquireLock(conf);
403      if(lockid<0)
404        return NULL;
405    }
406
407    //FILE* f0 = fopen (fileName, "r");
408    // knut: open file in binary mode to avoid conversion of line endings (yielding extra bytes) on Windows platforms
409    FILE* f0 = fopen(fileName, "rb"); 
410    if(f0!=NULL){
411      fseek (f0, 0, SEEK_END);
412      long flen = ftell (f0);
413      fseek (f0, 0, SEEK_SET);
414      char *tmps1 = (char *) malloc ((flen + 1) * sizeof (char));
415      fread(tmps1,flen,1,f0);
416      tmps1[flen]=0;
417      fclose(f0);
418      if(stat!=NULL){
419        unlockShm(lockid);
420        free(stat);
421      }
422      return tmps1;
423    }
424    else{
425      if(stat!=NULL){
426        unlockShm(lockid);
427        free(stat);
428      }
429      return NULL;
430    }
431  }
432  else
433    return NULL;
434}
435
436/**
437 * Get the ongoing status of a running service
438 *
439 * @param conf the maps containing the setting of the main.cfg file
440 * @param pid the service identifier (usid key from the [lenv] section)
441 * @return the reported status char* (MESSAGE|POURCENTAGE)
442 */
443char* _getStatus(maps* conf,char* lid){
444  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
445  char* fbkpid =
446    (char *)
447    malloc ((strlen (r_inputs->value) + strlen (lid) + 9) * sizeof (char));
448  sprintf (fbkpid, "%s/%s.status", r_inputs->value, lid);
449  FILE* f0 = fopen (fbkpid, "r");
450  if(f0!=NULL){   
451    semid lockid = NULL;
452    char* stat;
453    long flen;
454    stat=getStatusId(conf,lid);
455    if(stat!=NULL){
456      setMapInMaps(conf,"lenv","lid",stat);
457      lockid=acquireLock(conf);
458      if(lockid<0)
459        return NULL;
460    }
461    fseek (f0, 0, SEEK_END);
462    flen = ftell (f0);
463    if(flen>0){
464      char *fcontent;
465      fseek (f0, 0, SEEK_SET);
466      fcontent = (char *) malloc ((flen + 1) * sizeof (char));
467      fread(fcontent,flen,1,f0);
468      fcontent[flen]=0;
469      fclose(f0);
470      free(fbkpid);
471      if(stat!=NULL){
472#ifndef WIN32
473        removeShmLock(conf,1);
474#else
475        unlockShm(lockid);
476#endif
477        free(stat);
478      }
479      return fcontent;
480    }
481    fclose(f0);
482    free(fbkpid);
483    if(stat!=NULL){
484      removeShmLock(conf,1);
485      free(stat);
486    }
487    return NULL;
488  }else{
489    free(fbkpid);
490    char* stat=getStatusId(conf,lid);
491    setMapInMaps(conf,"lenv","lid",stat);
492    removeShmLock(conf,1);
493    return NULL;
494  }
495}
496
497/**
498 * Stop handling status repport.
499 *
500 * @param conf the map containing the setting of the main.cfg file
501 */
502void unhandleStatus(maps *conf){
503  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
504  map* usid = getMapFromMaps (conf, "lenv", "usid");
505  char* fbkpid =
506    (char *) malloc ((strlen (r_inputs->value) + strlen (usid->value) + 9) 
507                     * sizeof (char));
508  sprintf (fbkpid, "%s/%s.status", r_inputs->value, usid->value);
509  unlink(fbkpid);
510  free(fbkpid);
511}
512
513/**
514 * Update the current status of the running service.
515 *
516 * @see acquireLock, lockShm
517 * @param conf the map containing the setting of the main.cfg file
518 * @return 0 on success, -2 if shmget failed, -1 if shmat failed
519 */
520int _updateStatus(maps *conf){
521       
522  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
523  map* sid = getMapFromMaps (conf, "lenv", "usid");
524 
525  char* fbkpid =
526    (char *)
527    malloc ((strlen (r_inputs->value) + strlen (sid->value) + 9) * sizeof (char));
528  sprintf (fbkpid, "%s/%s.status", r_inputs->value, sid->value);
529  map* status=getMapFromMaps(conf,"lenv","status");
530  map* msg=getMapFromMaps(conf,"lenv","message");
531  if(status!=NULL && msg!=NULL &&
532     status->value!=NULL && msg->value!=NULL && 
533     strlen(status->value)>0 && strlen(msg->value)>1){   
534    semid lockid = NULL;
535       
536    char* stat=getStatusId(conf,sid->value);
537    if(stat!=NULL){
538      lockid=acquireLock(conf);
539      if(lockid<0){
540        dumpMap(status);
541        return ZOO_LOCK_ACQUIRE_FAILED;
542      }
543    }
544    FILE* fstatus=fopen(fbkpid,"w");
545    if(fstatus!=NULL){
546      fprintf(fstatus,"%s|%s",status->value,msg->value);
547      fflush(fstatus);
548      fclose(fstatus);
549    }
550    if(stat!=NULL){
551      unlockShm(lockid);
552      free(stat);
553    }
554  }
555
556  return 0;
557}
558
559#endif
560
561#ifdef WIN32
562
563#define SHMEMSIZE 4096
564
565size_t getKeyValue(maps* conf, char* key, size_t length){
566  if(conf==NULL) {
567    strncpy(key, "700666", length);
568    return strlen(key);
569  }
570 
571  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
572  if(tmpMap==NULL)
573    tmpMap=getMapFromMaps(conf,"lenv","osid");
574
575  if(tmpMap!=NULL){
576    snprintf(key, length, "zoo_sem_%s", tmpMap->value);     
577  }
578  else {
579    strncpy(key, "-1", length);
580  }
581  return strlen(key);
582}
583
584
585semid getShmLockId(maps* conf, int nsems){
586  semid sem_id;
587  char key[MAX_PATH];
588  getKeyValue(conf, key, MAX_PATH);
589 
590  sem_id = CreateSemaphore( NULL, nsems, nsems+1, key);
591  if(sem_id==NULL){
592#ifdef DEBUG
593    fprintf(stderr,"Semaphore failed to create: %s\n", getLastErrorMessage());
594#endif
595    return NULL;
596  }
597#ifdef DEBUG
598  fprintf(stderr,"%s Accessed !\n",key);
599#endif
600  return sem_id;
601}
602
603int removeShmLock(maps* conf, int nsems){
604  semid sem_id=getShmLockId(conf,1);
605  if (CloseHandle(sem_id) == 0) {
606#ifdef DEBUG
607    fprintf(stderr,"Unable to remove semaphore: %s\n", getLastErrorMessage());
608#endif
609    return -1;
610  }
611#ifdef DEBUG
612  fprintf(stderr,"%d Removed !\n",sem_id);
613#endif
614  return 0;
615}
616
617int lockShm(semid id){
618  DWORD dwWaitResult=WaitForSingleObject(id,INFINITE);
619  switch (dwWaitResult){
620    case WAIT_OBJECT_0:
621      return 0;
622      break;
623    case WAIT_TIMEOUT:
624      return -1;
625      break;
626    default:
627      return -2;
628      break;
629  }
630  return 0;
631}
632
633int unlockShm(semid id){
634  if(!ReleaseSemaphore(id,1,NULL)){
635    return -1;
636  }
637  return 0;
638}
639
640static LPVOID lpvMemG = NULL;      // pointer to shared memory
641static HANDLE hMapObjectG = NULL;  // handle to file mapping
642
643
644char* getStatus(int pid){
645  char *lpszBuf=(char*) malloc(SHMEMSIZE*sizeof(char));
646  int i=0;
647  LPWSTR lpszTmp=NULL;
648  LPVOID lpvMem = NULL;
649  HANDLE hMapObject = NULL;
650  BOOL fIgnore,fInit;
651  char tmp[1024];
652  sprintf(tmp,"%d",pid);
653  if(hMapObject==NULL)
654    hMapObject = CreateFileMapping( 
655                                   INVALID_HANDLE_VALUE,   // use paging file
656                                   NULL,                   // default security attributes
657                                   PAGE_READWRITE,         // read/write access
658                                   0,                      // size: high 32-bits
659                                   4096,                   // size: low 32-bits
660                                   TEXT(tmp));   // name of map object
661  if (hMapObject == NULL){
662#ifdef DEBUG
663    fprintf(stderr,"ERROR on line %d\n",__LINE__);
664#endif
665    return "-1";
666  }
667  if((GetLastError() != ERROR_ALREADY_EXISTS)){
668#ifdef DEBUG
669    fprintf(stderr,"ERROR on line %d\n",__LINE__);
670    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
671#endif
672    fIgnore = UnmapViewOfFile(lpvMem); 
673    fIgnore = CloseHandle(hMapObject);
674    return "-1";
675  }
676  fInit=TRUE;
677  if(lpvMem==NULL)
678    lpvMem = MapViewOfFile( 
679                           hMapObject,     // object to map view of
680                           FILE_MAP_READ,  // read/write access
681                           0,              // high offset:  map from
682                           0,              // low offset:   beginning
683                           0);             // default: map entire file
684  if (lpvMem == NULL){
685#ifdef DEBUG
686    fprintf(stderr,"READING STRING S %d\n",__LINE__);
687    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
688#endif
689    return "-1"; 
690  }
691  lpszTmp = (LPWSTR) lpvMem;
692  while (*lpszTmp){
693    lpszBuf[i] = (char)*lpszTmp;
694    *lpszTmp++; 
695    lpszBuf[i+1] = '\0'; 
696    i++;
697  }
698  return (char*)lpszBuf;
699}
700
701#else
702/**
703 * Number of time to try to access a semaphores set
704 * @see getShmLockId
705 */
706#define MAX_RETRIES 10
707
708#ifndef __APPLE__
709/**
710 * arg for semctl system calls.
711 */
712union semun {
713  int val; //!< value for SETVAL
714  struct semid_ds *buf; //!< buffer for IPC_STAT & IPC_SET
715  ushort *array; //!< array for GETALL & SETALL
716};
717#endif
718
719/**
720 * Set in the pre-allocated key the zoo_sem_[OSID] string
721 * where [OSID] is the lid (if any) or osid value from the [lenv] section.
722 *
723 * @param conf the map containing the setting of the main.cfg file
724 */
725int getKeyValue(maps* conf){
726  if(conf==NULL)
727     return 700666;
728  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
729  if(tmpMap==NULL)
730    tmpMap=getMapFromMaps(conf,"lenv","osid");
731  int key=-1;
732  if(tmpMap!=NULL)
733    key=atoi(tmpMap->value);
734  return key;
735}
736
737/**
738 * Try to create or access a semaphore set.
739 *
740 * @see getKeyValue
741 * @param conf the map containing the setting of the main.cfg file
742 * @param nsems number of semaphores
743 * @return a semaphores set indentifier on success, -1 in other case
744 */
745int getShmLockId(maps* conf, int nsems){
746    int i;
747    union semun arg;
748    struct semid_ds buf;
749    struct sembuf sb;
750    semid sem_id;
751    int key=getKeyValue(conf);
752   
753    sem_id = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
754
755    if (sem_id >= 0) { /* we got it first */
756        sb.sem_op = 1; 
757        sb.sem_flg = 0;
758        arg.val=1;
759        for(sb.sem_num = 0; sb.sem_num < nsems; sb.sem_num++) { 
760            /* do a semop() to "free" the semaphores. */
761            /* this sets the sem_otime field, as needed below. */
762            if (semop(sem_id, &sb, 1) == -1) {
763                int e = errno;
764                semctl(sem_id, 0, IPC_RMID); /* clean up */
765                errno = e;
766                return -1; /* error, check errno */
767            }
768        }
769    } else if (errno == EEXIST) { /* someone else got it first */
770        int ready = 0;
771
772        sem_id = semget(key, nsems, 0); /* get the id */
773        if (sem_id < 0) return sem_id; /* error, check errno */
774
775        /* wait for other process to initialize the semaphore: */
776        arg.buf = &buf;
777        for(i = 0; i < MAX_RETRIES && !ready; i++) {
778            semctl(sem_id, nsems-1, IPC_STAT, arg);
779            if (arg.buf->sem_otime != 0) {
780#ifdef DEBUG
781              fprintf(stderr,"Semaphore acquired ...\n");
782#endif
783              ready = 1;
784            } else {
785#ifdef DEBUG
786              fprintf(stderr,"Retry to access the semaphore later ...\n");
787#endif
788              zSleep(1000);
789            }
790        }
791        errno = ZOO_LOCK_ACQUIRE_FAILED;
792        if (!ready) {
793#ifdef DEBUG
794          fprintf(stderr,"Unable to access the semaphore ...\n");
795#endif
796          errno = ETIME;
797          return -1;
798        }
799    } else {
800        return sem_id; /* error, check errno */
801    }
802#ifdef DEBUG
803    fprintf(stderr,"%d Created !\n",sem_id);
804#endif
805    return sem_id;
806}
807
808/**
809 * Try to remove a semaphore set.
810 *
811 * @param conf the map containing the setting of the main.cfg file
812 * @param nsems number of semaphores
813 * @return 0 if the semaphore can be removed, -1 in other case.
814 */
815int removeShmLock(maps* conf, int nsems){
816  union semun arg;
817  int sem_id=getShmLockId(conf,nsems);
818  if (semctl(sem_id, 0, IPC_RMID, arg) == -1) {
819#ifdef DEBUG
820    perror("semctl remove");
821#endif
822    return -1;
823  }
824#ifdef DEBUG
825  fprintf(stderr,"Semaphore removed!\n");
826#endif
827  return 0;
828}
829
830/**
831 * Lock a semaphore set.
832 *
833 * @param id the semaphores set indetifier
834 * @return 0 if the semaphore can be locked, -1 in other case.
835 */
836int lockShm(int id){
837  struct sembuf sb;
838  sb.sem_num = 0;
839  sb.sem_op = -1;  /* set to allocate resource */
840  sb.sem_flg = SEM_UNDO;
841  if (semop(id, &sb, 1) == -1){
842#ifdef DEBUG
843    perror("semop lock");
844#endif
845    return -1;
846  }
847  return 0;
848}
849
850/**
851 * unLock a semaphore set.
852 *
853 * @param id the semaphores set indetifier
854 * @return 0 if the semaphore can be locked, -1 in other case.
855 */
856int unlockShm(int id){
857  struct sembuf sb;
858  sb.sem_num = 0;
859  sb.sem_op = 1;  /* free resource */
860  sb.sem_flg = SEM_UNDO;
861  if (semop(id, &sb, 1) == -1) {
862#ifdef DEBUG
863    perror("semop unlock");
864#endif
865    return -1;
866  }
867  return 0;
868}
869
870/**
871 * Get the current status of the running service.
872 *
873 * @see getKeyValue, getShmLockId, lockShm
874 * @param pid the semaphores
875 * @return 0 on success, -2 if shmget failed, -1 if shmat failed
876 */
877char* getStatus(int pid){
878  int shmid;
879  key_t key;
880  void *shm;
881  key=pid;
882  if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
883#ifdef DEBUG
884    fprintf(stderr,"shmget failed in getStatus\n");
885#endif
886  }else{
887    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
888#ifdef DEBUG
889      fprintf(stderr,"shmat failed in getStatus\n");
890#endif
891    }else{
892      char *ret=strdup((char*)shm);
893      shmdt((void *)shm);
894      return ret;
895    }
896  }
897  return (char*)"-1";
898}
899
900#endif
901
902/**
903 * Update the status of an ongoing service
904 *
905 * @param conf the maps containing the settings of the main.cfg file
906 * @param percentCompleted percentage of completude of execution of the service
907 * @param message information about the current step executed
908 * @return the value of _updateStatus
909 * @see _updateStatus
910 */
911int updateStatus( maps* conf, const int percentCompleted, const char* message ){
912  char tmp[4];
913  snprintf(tmp,4,"%d",percentCompleted);
914  setMapInMaps( conf, "lenv", "status", tmp );
915  setMapInMaps( conf, "lenv", "message", message);
916  return _updateStatus( conf );
917}
918
919/**
920 * Access an input value
921 *
922 * @param inputs the maps to search for the input value
923 * @param parameterName the input name to fetch the value
924 * @param numberOfBytes the resulting size of the value to add (for binary
925 *  values), -1 for basic char* data
926 * @return a pointer to the input value if found, NULL in other case.
927 */
928char* getInputValue( maps* inputs, const char* parameterName, size_t* numberOfBytes){
929  map* res=getMapFromMaps(inputs,parameterName,"value");
930  if(res!=NULL){
931    map* size=getMapFromMaps(inputs,parameterName,"size");
932    if(size!=NULL){
933      *numberOfBytes=(size_t)atoi(size->value);
934      return res->value;
935    }else{
936      *numberOfBytes=strlen(res->value);
937      return res->value;
938    }
939  }
940  return NULL;
941}
942
943/**
944 * Read a file using the GDAL VSI API
945 *
946 * @param conf the maps containing the settings of the main.cfg file
947 * @param dataSource the datasource name to read
948 * @warning make sure to free resources returned by this function
949 */
950char *readVSIFile(maps* conf,const char* dataSource){
951    VSILFILE * fichier=VSIFOpenL(dataSource,"rb");
952    VSIStatBufL file_status;
953    VSIStatL(dataSource, &file_status);
954    if(fichier==NULL){
955      char tmp[1024];
956      sprintf(tmp,"Failed to open file %s for reading purpose. File seems empty %lld.",
957              dataSource,file_status.st_size);
958      setMapInMaps(conf,"lenv","message",tmp);
959      return NULL;
960    }
961    char *res1=(char *)malloc(file_status.st_size*sizeof(char));
962    VSIFReadL(res1,1,file_status.st_size*sizeof(char),fichier);
963    res1[file_status.st_size-1]=0;
964    VSIFCloseL(fichier);
965    VSIUnlink(dataSource);
966    return res1;
967}
968
969/**
970 * Set an output value
971 *
972 * @param outputs the maps to define the output value
973 * @param parameterName the output name to set the value
974 * @param data the value to set
975 * @param numberOfBytes size of the value to add (for binary values), -1 for
976 *  basic char* data
977 * @return 0
978 */
979int  setOutputValue( maps* outputs, const char* parameterName, char* data, size_t numberOfBytes ){
980  if(numberOfBytes==-1){
981    setMapInMaps(outputs,parameterName,"value",data);
982  }else{
983    char size[1024];
984    map* tmp=getMapFromMaps(outputs,parameterName,"value");
985    if(tmp==NULL){
986      setMapInMaps(outputs,parameterName,"value","");
987      tmp=getMapFromMaps(outputs,parameterName,"value");
988    }
989    free(tmp->value);
990    tmp->value=(char*) malloc((numberOfBytes+1)*sizeof(char));
991    memcpy(tmp->value,data,numberOfBytes);
992    sprintf(size,"%lu",numberOfBytes);
993    setMapInMaps(outputs,parameterName,"size",size);
994  }
995  return 0;
996}
997
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png