source: trunk/zoo-project/zoo-kernel/service_internal.c @ 972

Last change on this file since 972 was 972, checked in by djay, 3 years ago

Small fix to build when json is activated and mapserver is not

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

Search

Context Navigation

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