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

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

Added some recent changes from trunk (r889), including some new utility functions and exception handling and new (conditional) definition of type bool. Added some new logic concerning Python and Mono environment and search paths. Fixed problem with Mono updateStatus function. Changed response_print.h to #include locale.h unconditionally and xlocale.h conditionally; xlocale.h is non-standard and can probably be dropped.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 24.5 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2009-2018 GeoLabs SARL
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#define _LARGEFILE64_SOURCE 1
26#ifdef USE_MS
27#include "service_internal_ms.h"
28#else
29#include "cpl_vsi.h"
30#endif
31#include "service_internal.h"
32
33#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}
85#endif
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);
113#endif
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}
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;
204    fclose(s->lockfile);
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;
208    if(fcntl(fileno(s->lockfile), F_GETLK, &s->lock)!=-1 && s->lock.l_type == F_UNLCK){
209#endif
210      zUnlink(s->filename);
211#ifndef WIN32
212    }
213#endif
214    free(s->filename);
215    free(s);
216  }
217  return res;
218}
219
220#ifndef RELY_ON_DB
221#include "dirent.h"
222
223/**
224 * Read the sid file attached of a service if any
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)
228 * @return the reported status char* (temporary/final result)
229 */
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){
238    long flen;
239    char *fcontent;
240    fseek (f0, 0, SEEK_END);
241    flen = ftell (f0);
242    fseek (f0, 0, SEEK_SET);
243    fcontent = (char *) malloc ((flen + 1) * sizeof (char));
244    fread(fcontent,flen,1,f0);
245    fcontent[flen]=0;
246    fclose(f0);
247    return fcontent;
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);
263  if(
264#ifdef WIN32
265     lockid==NULL
266#else
267     lockid<0
268#endif
269     ){
270#ifdef WIN32
271    return NULL;
272#else
273    return -1;
274#endif
275  }
276  if(lockShm(lockid)<0){
277#ifdef WIN32
278      return NULL;
279#else
280    if(itn<ZOO_LOCK_MAX_RETRY){
281      itn++;
282      goto toRetry1;
283    }else
284      return -1;
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    }
317  }
318  if(hasFile>0){
319    semid lockid;
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
328    //FILE* f0 = fopen (fileName, "r");
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"); 
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");
371  if(f0!=NULL){   
372    semid lockid = NULL;
373    char* stat;
374    long flen;
375    stat=getStatusId(conf,lid);
376    if(stat!=NULL){
377      setMapInMaps(conf,"lenv","lid",stat);
378      lockid=acquireLock(conf);
379      if(lockid<0)
380        return NULL;
381    }
382    fseek (f0, 0, SEEK_END);
383    flen = ftell (f0);
384    if(flen>0){
385      char *fcontent;
386      fseek (f0, 0, SEEK_SET);
387      fcontent = (char *) malloc ((flen + 1) * sizeof (char));
388      fread(fcontent,flen,1,f0);
389      fcontent[flen]=0;
390      fclose(f0);
391      free(fbkpid);
392      if(stat!=NULL){
393#ifndef WIN32
394        removeShmLock(conf,1);
395#else
396        unlockShm(lockid);
397#endif
398        free(stat);
399      }
400      return fcontent;
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);
413    removeShmLock(conf,1);
414    return NULL;
415  }
416}
417
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);
430  zUnlink(fbkpid);
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){
442       
443  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
444  map* sid = getMapFromMaps (conf, "lenv", "usid");
445 
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 && 
454     strlen(status->value)>0 && strlen(msg->value)>1){   
455    semid lockid = NULL;
456       
457    char* stat=getStatusId(conf,sid->value);
458    if(stat!=NULL){
459      lockid=acquireLock(conf);
460      if(lockid<0){
461        dumpMap(status);
462        return ZOO_LOCK_ACQUIRE_FAILED;
463      }
464    }
465    FILE* fstatus=fopen(fbkpid,"w");
466    if(fstatus!=NULL){
467      fprintf(fstatus,"%s|%s",status->value,msg->value);
468      fflush(fstatus);
469      fclose(fstatus);
470    }
471    if(stat!=NULL){
472      unlockShm(lockid);
473      free(stat);
474    }
475  }
476
477  return 0;
478}
479
480#endif
481
482#ifdef WIN32
483
484#define SHMEMSIZE 4096
485
486size_t getKeyValue(maps* conf, char* key, size_t length){
487  if(conf==NULL) {
488    strncpy(key, "700666", length);
489    return strlen(key);
490  }
491 
492  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
493  if(tmpMap==NULL)
494    tmpMap=getMapFromMaps(conf,"lenv","osid");
495
496  if(tmpMap!=NULL){
497    snprintf(key, length, "zoo_sem_%s", tmpMap->value);     
498  }
499  else {
500    strncpy(key, "-1", length);
501  }
502  return strlen(key);
503}
504
505
506semid getShmLockId(maps* conf, int nsems){
507  semid sem_id;
508  char key[MAX_PATH];
509  getKeyValue(conf, key, MAX_PATH);
510 
511  sem_id = CreateSemaphore( NULL, nsems, nsems+1, key);
512  if(sem_id==NULL){
513#ifdef DEBUG
514    fprintf(stderr,"Semaphore failed to create: %s\n", getLastErrorMessage());
515#endif
516    return NULL;
517  }
518#ifdef DEBUG
519  fprintf(stderr,"%s Accessed !\n",key);
520#endif
521  return sem_id;
522}
523
524int removeShmLock(maps* conf, int nsems){
525  semid sem_id=getShmLockId(conf,1);
526  if (CloseHandle(sem_id) == 0) {
527#ifdef DEBUG
528    fprintf(stderr,"Unable to remove semaphore: %s\n", getLastErrorMessage());
529#endif
530    return -1;
531  }
532#ifdef DEBUG
533  fprintf(stderr,"%d Removed !\n",sem_id);
534#endif
535  return 0;
536}
537
538int lockShm(semid id){
539  DWORD dwWaitResult=WaitForSingleObject(id,INFINITE);
540  switch (dwWaitResult){
541    case WAIT_OBJECT_0:
542      return 0;
543      break;
544    case WAIT_TIMEOUT:
545      return -1;
546      break;
547    default:
548      return -2;
549      break;
550  }
551  return 0;
552}
553
554int unlockShm(semid id){
555  if(!ReleaseSemaphore(id,1,NULL)){
556    return -1;
557  }
558  return 0;
559}
560
561static LPVOID lpvMemG = NULL;      // pointer to shared memory
562static HANDLE hMapObjectG = NULL;  // handle to file mapping
563
564
565char* getStatus(int pid){
566  char *lpszBuf=(char*) malloc(SHMEMSIZE*sizeof(char));
567  int i=0;
568  LPWSTR lpszTmp=NULL;
569  LPVOID lpvMem = NULL;
570  HANDLE hMapObject = NULL;
571  BOOL fIgnore,fInit;
572  char tmp[1024];
573  sprintf(tmp,"%d",pid);
574  if(hMapObject==NULL)
575    hMapObject = CreateFileMapping( 
576                                   INVALID_HANDLE_VALUE,   // use paging file
577                                   NULL,                   // default security attributes
578                                   PAGE_READWRITE,         // read/write access
579                                   0,                      // size: high 32-bits
580                                   4096,                   // size: low 32-bits
581                                   TEXT(tmp));   // name of map object
582  if (hMapObject == NULL){
583#ifdef DEBUG
584    fprintf(stderr,"ERROR on line %d\n",__LINE__);
585#endif
586    return "-1";
587  }
588  if((GetLastError() != ERROR_ALREADY_EXISTS)){
589#ifdef DEBUG
590    fprintf(stderr,"ERROR on line %d\n",__LINE__);
591    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
592#endif
593    fIgnore = UnmapViewOfFile(lpvMem); 
594    fIgnore = CloseHandle(hMapObject);
595    return "-1";
596  }
597  fInit=TRUE;
598  if(lpvMem==NULL)
599    lpvMem = MapViewOfFile( 
600                           hMapObject,     // object to map view of
601                           FILE_MAP_READ,  // read/write access
602                           0,              // high offset:  map from
603                           0,              // low offset:   beginning
604                           0);             // default: map entire file
605  if (lpvMem == NULL){
606#ifdef DEBUG
607    fprintf(stderr,"READING STRING S %d\n",__LINE__);
608    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
609#endif
610    return "-1"; 
611  }
612  lpszTmp = (LPWSTR) lpvMem;
613  while (*lpszTmp){
614    lpszBuf[i] = (char)*lpszTmp;
615    *lpszTmp++; 
616    lpszBuf[i+1] = '\0'; 
617    i++;
618  }
619  return (char*)lpszBuf;
620}
621
622#else
623/**
624 * Number of time to try to access a semaphores set
625 * @see getShmLockId
626 */
627#define MAX_RETRIES 10
628
629#ifndef __APPLE__
630/**
631 * arg for semctl system calls.
632 */
633union semun {
634  int val; //!< value for SETVAL
635  struct semid_ds *buf; //!< buffer for IPC_STAT & IPC_SET
636  ushort *array; //!< array for GETALL & SETALL
637};
638#endif
639
640/**
641 * Set in the pre-allocated key the zoo_sem_[OSID] string
642 * where [OSID] is the lid (if any) or osid value from the [lenv] section.
643 *
644 * @param conf the map containing the setting of the main.cfg file
645 */
646int getKeyValue(maps* conf){
647  if(conf==NULL)
648     return 700666;
649  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
650  if(tmpMap==NULL)
651    tmpMap=getMapFromMaps(conf,"lenv","osid");
652  int key=-1;
653  if(tmpMap!=NULL)
654    key=atoi(tmpMap->value);
655  return key;
656}
657
658/**
659 * Try to create or access a semaphore set.
660 *
661 * @see getKeyValue
662 * @param conf the map containing the setting of the main.cfg file
663 * @param nsems number of semaphores
664 * @return a semaphores set indentifier on success, -1 in other case
665 */
666int getShmLockId(maps* conf, int nsems){
667    int i;
668    union semun arg;
669    struct semid_ds buf;
670    struct sembuf sb;
671    semid sem_id;
672    int key=getKeyValue(conf);
673   
674    sem_id = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
675
676    if (sem_id >= 0) { /* we got it first */
677        sb.sem_op = 1; 
678        sb.sem_flg = 0;
679        arg.val=1;
680        for(sb.sem_num = 0; sb.sem_num < nsems; sb.sem_num++) { 
681            /* do a semop() to "free" the semaphores. */
682            /* this sets the sem_otime field, as needed below. */
683            if (semop(sem_id, &sb, 1) == -1) {
684                int e = errno;
685                semctl(sem_id, 0, IPC_RMID); /* clean up */
686                errno = e;
687                return -1; /* error, check errno */
688            }
689        }
690    } else if (errno == EEXIST) { /* someone else got it first */
691        int ready = 0;
692
693        sem_id = semget(key, nsems, 0); /* get the id */
694        if (sem_id < 0) return sem_id; /* error, check errno */
695
696        /* wait for other process to initialize the semaphore: */
697        arg.buf = &buf;
698        for(i = 0; i < MAX_RETRIES && !ready; i++) {
699            semctl(sem_id, nsems-1, IPC_STAT, arg);
700            if (arg.buf->sem_otime != 0) {
701#ifdef DEBUG
702              fprintf(stderr,"Semaphore acquired ...\n");
703#endif
704              ready = 1;
705            } else {
706#ifdef DEBUG
707              fprintf(stderr,"Retry to access the semaphore later ...\n");
708#endif
709              zSleep(1000);
710            }
711        }
712        errno = ZOO_LOCK_ACQUIRE_FAILED;
713        if (!ready) {
714#ifdef DEBUG
715          fprintf(stderr,"Unable to access the semaphore ...\n");
716#endif
717          errno = ETIME;
718          return -1;
719        }
720    } else {
721        return sem_id; /* error, check errno */
722    }
723#ifdef DEBUG
724    fprintf(stderr,"%d Created !\n",sem_id);
725#endif
726    return sem_id;
727}
728
729/**
730 * Try to remove a semaphore set.
731 *
732 * @param conf the map containing the setting of the main.cfg file
733 * @param nsems number of semaphores
734 * @return 0 if the semaphore can be removed, -1 in other case.
735 */
736int removeShmLock(maps* conf, int nsems){
737  union semun arg;
738  int sem_id=getShmLockId(conf,nsems);
739  if (semctl(sem_id, 0, IPC_RMID, arg) == -1) {
740#ifdef DEBUG
741    perror("semctl remove");
742#endif
743    return -1;
744  }
745#ifdef DEBUG
746  fprintf(stderr,"Semaphore removed!\n");
747#endif
748  return 0;
749}
750
751/**
752 * Lock a semaphore set.
753 *
754 * @param id the semaphores set indetifier
755 * @return 0 if the semaphore can be locked, -1 in other case.
756 */
757int lockShm(int id){
758  struct sembuf sb;
759  sb.sem_num = 0;
760  sb.sem_op = -1;  /* set to allocate resource */
761  sb.sem_flg = SEM_UNDO;
762  if (semop(id, &sb, 1) == -1){
763#ifdef DEBUG
764    perror("semop lock");
765#endif
766    return -1;
767  }
768  return 0;
769}
770
771/**
772 * unLock a semaphore set.
773 *
774 * @param id the semaphores set indetifier
775 * @return 0 if the semaphore can be locked, -1 in other case.
776 */
777int unlockShm(int id){
778  struct sembuf sb;
779  sb.sem_num = 0;
780  sb.sem_op = 1;  /* free resource */
781  sb.sem_flg = SEM_UNDO;
782  if (semop(id, &sb, 1) == -1) {
783#ifdef DEBUG
784    perror("semop unlock");
785#endif
786    return -1;
787  }
788  return 0;
789}
790
791/**
792 * Get the current status of the running service.
793 *
794 * @see getKeyValue, getShmLockId, lockShm
795 * @param pid the semaphores
796 * @return 0 on success, -2 if shmget failed, -1 if shmat failed
797 */
798char* getStatus(int pid){
799  int shmid;
800  key_t key;
801  void *shm;
802  key=pid;
803  if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
804#ifdef DEBUG
805    fprintf(stderr,"shmget failed in getStatus\n");
806#endif
807  }else{
808    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
809#ifdef DEBUG
810      fprintf(stderr,"shmat failed in getStatus\n");
811#endif
812    }else{
813      char *ret=strdup((char*)shm);
814      shmdt((void *)shm);
815      return ret;
816    }
817  }
818  return (char*)"-1";
819}
820
821#endif
822
823/**
824 * Update the status of an ongoing service
825 *
826 * @param conf the maps containing the settings of the main.cfg file
827 * @param percentCompleted percentage of completude of execution of the service
828 * @param message information about the current step executed
829 * @return the value of _updateStatus
830 * @see _updateStatus
831 */
832int updateStatus( maps* conf, const int percentCompleted, const char* message ){
833  char tmp[4];
834  snprintf(tmp,4,"%d",percentCompleted);
835  setMapInMaps( conf, "lenv", "status", tmp );
836  setMapInMaps( conf, "lenv", "message", message);
837  return _updateStatus( conf );
838}
839
840/**
841 * Access an input value
842 *
843 * @param inputs the maps to search for the input value
844 * @param parameterName the input name to fetch the value
845 * @param numberOfBytes the resulting size of the value to add (for binary
846 *  values), -1 for basic char* data
847 * @return a pointer to the input value if found, NULL in other case.
848 */
849char* getInputValue( maps* inputs, const char* parameterName, size_t* numberOfBytes){
850  map* res=getMapFromMaps(inputs,parameterName,"value");
851  if(res!=NULL){
852    map* size=getMapFromMaps(inputs,parameterName,"size");
853    if(size!=NULL){
854      *numberOfBytes=(size_t)atoi(size->value);
855      return res->value;
856    }else{
857      *numberOfBytes=strlen(res->value);
858      return res->value;
859    }
860  }
861  return NULL;
862}
863
864/**
865 * Read a file using the GDAL VSI API
866 *
867 * @param conf the maps containing the settings of the main.cfg file
868 * @param dataSource the datasource name to read
869 * @warning make sure to free resources returned by this function
870 */
871char *readVSIFile(maps* conf,const char* dataSource){
872    VSILFILE * fichier=VSIFOpenL(dataSource,"rb");
873    VSIStatBufL file_status;
874    VSIStatL(dataSource, &file_status);
875    if(fichier==NULL){
876      char tmp[1024];
877      sprintf(tmp,"Failed to open file %s for reading purpose. File seems empty %lld.",
878              dataSource,file_status.st_size);
879      setMapInMaps(conf,"lenv","message",tmp);
880      return NULL;
881    }
882    char *res1=(char *)malloc(file_status.st_size*sizeof(char));
883    VSIFReadL(res1,1,file_status.st_size*sizeof(char),fichier);
884    res1[file_status.st_size-1]=0;
885    VSIFCloseL(fichier);
886    VSIUnlink(dataSource);
887    return res1;
888}
889
890/**
891 * Set an output value
892 *
893 * @param outputs the maps to define the output value
894 * @param parameterName the output name to set the value
895 * @param data the value to set
896 * @param numberOfBytes size of the value to add (for binary values), -1 for
897 *  basic char* data
898 * @return 0
899 */
900int  setOutputValue( maps* outputs, const char* parameterName, char* data, size_t numberOfBytes ){
901  if(numberOfBytes==-1){
902    setMapInMaps(outputs,parameterName,"value",data);
903  }else{
904    char size[1024];
905    map* tmp=getMapFromMaps(outputs,parameterName,"value");
906    if(tmp==NULL){
907      setMapInMaps(outputs,parameterName,"value","");
908      tmp=getMapFromMaps(outputs,parameterName,"value");
909    }
910    free(tmp->value);
911    tmp->value=(char*) malloc((numberOfBytes+1)*sizeof(char));
912    memcpy(tmp->value,data,numberOfBytes);
913    sprintf(size,"%lu",numberOfBytes);
914    setMapInMaps(outputs,parameterName,"size",size);
915  }
916  return 0;
917}
918
919/**
920 * Check if file exists in specified folder
921 *
922 * @param dir the folder in which to search for file
923 * @param name the name of the file (not full path)
924 * @return a character string with the full path [dir/name], or NULL if the file does not exist
925 *
926 * @attention Caller is responsible for applying free() to the returned pointer
927 */
928char* file_exists(const char* dir, const char* name) {
929        char* d = (dir != NULL ? dir : ".");
930        if (name != NULL) {
931                size_t length = strlen(d) + strlen(name) + 2; // including file separator and \0 character
932                char* path = (char*)calloc(length, sizeof(char));
933                snprintf(path, length, "%s/%s", d, name);
934
935                struct stat buffer;
936                if (stat(path, &buffer) != 0) {
937                        free(path);
938                        path = NULL;
939                }
940                return path;
941        }
942        else {
943                return NULL;
944        }
945}
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