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

Last change on this file since 933 was 933, checked in by knut, 5 years ago

Resolve certain string-related type conflicts, e.g., char* vs. const char* or char[N], that may cause errors in some build environments. Resolve a problem with the include order of fcgi_stdio.h (note: should verify that this harmonizes with resolution of same problem in trunk).

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