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

Last change on this file since 962 was 962, checked in by djay, 4 years ago

Update OGC API - Processes documentation and implementation, providing a browsable User Interface to Processes.

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