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

Last change on this file since 640 was 640, checked in by djay, 9 years ago

First version including zoo_service shared library

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 16.3 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2009-2015 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#include "fcgi_stdio.h"
26#include "service_internal.h"
27
28#ifndef TRUE
29#define TRUE 1
30#endif
31#ifndef FALSE
32#define FALSE -1
33#endif
34
35#define ERROR_MSG_MAX_LENGTH 1024
36
37/**
38 * Get the ongoing status of a running service
39 *
40 * @param conf the maps containing the setting of the main.cfg file
41 * @param pid the service identifier (usid key from the [lenv] section)
42 * @return the reported status char* (MESSAGE|POURCENTAGE)
43 */
44char* _getStatus(maps* conf,int pid){
45  char lid[1024];
46  sprintf(lid,"%d",pid);
47  setMapInMaps(conf,"lenv","lid",lid);
48  semid lockid=getShmLockId(conf,1);
49  if(
50#ifdef WIN32
51     lockid==NULL
52#else
53     lockid<0
54#endif
55     ){
56        char* tmp = (char*) malloc(3*sizeof(char));
57    sprintf(tmp,"%d",ZOO_LOCK_CREATE_FAILED);
58    return tmp;
59  }
60  if(lockShm(lockid)<0){
61    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
62    fflush(stderr);   
63        char* tmp = (char*) malloc(3*sizeof(char));
64    sprintf(tmp,"%d",ZOO_LOCK_ACQUIRE_FAILED);
65    return tmp;
66  }
67  char *tmp=getStatus(pid);
68  unlockShm(lockid);
69  if(tmp==NULL || strncmp(tmp,"-1",2)==0){
70    removeShmLock(conf,1);
71  }
72  return tmp;
73}
74
75#ifdef WIN32
76
77#include <windows.h>
78#include <fcgi_stdio.h>
79#include <stdio.h>
80#include <conio.h>
81#include <tchar.h>
82
83#define SHMEMSIZE 4096
84
85size_t getKeyValue(maps* conf, char* key, size_t length){
86  if(conf==NULL) {
87    strncpy(key, "700666", length);
88    return strlen(key);
89  }
90 
91  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
92  if(tmpMap==NULL)
93        tmpMap=getMapFromMaps(conf,"lenv","usid");
94
95  if(tmpMap!=NULL){
96        snprintf(key, length, "zoo_sem_%s", tmpMap->value);     
97  }
98  else {
99        strncpy(key, "-1", length); 
100  }
101  return strlen(key);
102}
103
104
105semid getShmLockId(maps* conf, int nsems){
106    semid sem_id;
107    char key[MAX_PATH];
108    getKeyValue(conf, key, MAX_PATH);
109   
110    sem_id = CreateSemaphore( NULL, nsems, nsems+1, key);
111    if(sem_id==NULL){
112#ifdef DEBUG
113      fprintf(stderr,"Semaphore failed to create: %s\n", getLastErrorMessage());
114#endif
115      return NULL;
116    }
117#ifdef DEBUG
118    fprintf(stderr,"%s Accessed !\n",key);
119#endif
120
121    return sem_id;
122}
123
124int removeShmLock(maps* conf, int nsems){
125  semid sem_id=getShmLockId(conf,1);
126  if (CloseHandle(sem_id) == 0) {
127    fprintf(stderr,"Unable to remove semaphore: %s\n", getLastErrorMessage());
128    return -1;
129  }
130#ifdef DEBUG
131  fprintf(stderr,"%d Removed !\n",sem_id);
132#endif
133  return 0;
134}
135
136int lockShm(semid id){
137  DWORD dwWaitResult=WaitForSingleObject(id,INFINITE);
138  switch (dwWaitResult){
139    case WAIT_OBJECT_0:
140      return 0;
141      break;
142    case WAIT_TIMEOUT:
143      return -1;
144      break;
145    default:
146      return -2;
147      break;
148  }
149  return 0;
150}
151
152int unlockShm(semid id){
153  if(!ReleaseSemaphore(id,1,NULL)){
154    return -1;
155  }
156  return 0;
157}
158
159static LPVOID lpvMemG = NULL;      // pointer to shared memory
160static HANDLE hMapObjectG = NULL;  // handle to file mapping
161
162int _updateStatus(maps *conf){
163  LPWSTR lpszTmp;
164  BOOL fInit;
165  char *final_string=NULL;
166  char *s=NULL;
167  map *tmpMap1;
168  map *tmpMap=getMapFromMaps(conf,"lenv","usid");
169  semid lockid=getShmLockId(conf,1);
170  if(lockid==NULL){
171#ifdef DEBUG
172    fprintf(stderr,"Unable to create semaphore on line %d!! \n",__LINE__);
173#endif
174    return ZOO_LOCK_CREATE_FAILED;
175  }
176  if(lockShm(lockid)<0){
177#ifdef DEBUG
178    fprintf(stderr,"Unable to create semaphore on line %d!! \n",__LINE__);
179#endif
180    return ZOO_LOCK_ACQUIRE_FAILED;
181  }
182 
183  if(hMapObjectG==NULL)
184    hMapObjectG = CreateFileMapping( 
185                                    INVALID_HANDLE_VALUE,   // use paging file
186                                    NULL,                   // default security attributes
187                                    PAGE_READWRITE,         // read/write access
188                                    0,                      // size: high 32-bits
189                                    SHMEMSIZE,              // size: low 32-bits
190                                    TEXT(tmpMap->value));   // name of map object
191  if (hMapObjectG == NULL){
192#ifdef DEBUG
193    fprintf(stderr,"Unable to create shared memory segment: %s\n", getLastErrorMessage());
194#endif
195    return -2;
196  }
197  fInit = (GetLastError() != ERROR_ALREADY_EXISTS); 
198  if(lpvMemG==NULL)
199    lpvMemG = MapViewOfFile( 
200                            hMapObjectG,     // object to map view of
201                            FILE_MAP_WRITE, // read/write access
202                            0,              // high offset:  map from
203                            0,              // low offset:   beginning
204                            0);             // default: map entire file
205  if (lpvMemG == NULL){
206#ifdef DEBUG
207    fprintf(stderr,"Unable to create or access the shared memory segment %s !! \n",tmpMap->value);
208#endif
209    return -1;
210  } 
211  memset(lpvMemG, '\0', SHMEMSIZE);
212  tmpMap=getMapFromMaps(conf,"lenv","status");
213  tmpMap1=NULL;
214  tmpMap1=getMapFromMaps(conf,"lenv","message");
215  lpszTmp = (LPWSTR) lpvMemG;
216  final_string=(char*)malloc((strlen(tmpMap1->value)+strlen(tmpMap->value)+2)*sizeof(char));
217  sprintf(final_string,"%s|%s",tmpMap->value,tmpMap1->value);
218  for(s=final_string;*s!='\0';*s++){
219    *lpszTmp++ = *s;
220  }
221  *lpszTmp++ = '\0';
222  free(final_string);
223  unlockShm(lockid);
224  return 0;
225}
226
227char* getStatus(int pid){
228  char *lpszBuf=(char*) malloc(SHMEMSIZE*sizeof(char));
229  int i=0;
230  LPWSTR lpszTmp=NULL;
231  LPVOID lpvMem = NULL;
232  HANDLE hMapObject = NULL;
233  BOOL fIgnore,fInit;
234  char tmp[1024];
235  sprintf(tmp,"%d",pid);
236  if(hMapObject==NULL)
237    hMapObject = CreateFileMapping( 
238                                   INVALID_HANDLE_VALUE,   // use paging file
239                                   NULL,                   // default security attributes
240                                   PAGE_READWRITE,         // read/write access
241                                   0,                      // size: high 32-bits
242                                   4096,                   // size: low 32-bits
243                                   TEXT(tmp));   // name of map object
244  if (hMapObject == NULL){
245#ifdef DEBUG
246    fprintf(stderr,"ERROR on line %d\n",__LINE__);
247#endif
248    return "-1";
249  }
250  if((GetLastError() != ERROR_ALREADY_EXISTS)){
251#ifdef DEBUG
252    fprintf(stderr,"ERROR on line %d\n",__LINE__);
253    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
254#endif
255    fIgnore = UnmapViewOfFile(lpvMem); 
256    fIgnore = CloseHandle(hMapObject);
257    return "-1";
258  }
259  fInit=TRUE;
260  if(lpvMem==NULL)
261    lpvMem = MapViewOfFile( 
262                           hMapObject,     // object to map view of
263                           FILE_MAP_READ,  // read/write access
264                           0,              // high offset:  map from
265                           0,              // low offset:   beginning
266                           0);             // default: map entire file
267  if (lpvMem == NULL){
268#ifdef DEBUG
269    fprintf(stderr,"READING STRING S %d\n",__LINE__);
270    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
271#endif
272    return "-1"; 
273  }
274  lpszTmp = (LPWSTR) lpvMem;
275  while (*lpszTmp){
276    lpszBuf[i] = (char)*lpszTmp;
277    *lpszTmp++; 
278    lpszBuf[i+1] = '\0'; 
279    i++;
280  }
281  return (char*)lpszBuf;
282}
283
284void unhandleStatus(maps *conf){
285  BOOL fIgnore;
286  fIgnore = UnmapViewOfFile(lpvMemG); 
287  fIgnore = CloseHandle(hMapObjectG);
288}
289
290#else
291/**
292 * Number of time to try to access a semaphores set
293 * @see getShmLockId
294 */
295#define MAX_RETRIES 10
296
297#ifndef __APPLE__
298/**
299 * arg for semctl system calls.
300 */
301union semun {
302  int val; //!< value for SETVAL
303  struct semid_ds *buf; //!< buffer for IPC_STAT & IPC_SET
304  ushort *array; //!< array for GETALL & SETALL
305};
306#endif
307
308/**
309 * Set in the pre-allocated key the zoo_sem_[SID] string
310 * where [SID] is the lid (if any) or usid value from the [lenv] section.
311 *
312 * @param conf the map containing the setting of the main.cfg file
313 */
314int getKeyValue(maps* conf){
315  if(conf==NULL)
316     return 700666;
317  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
318  if(tmpMap==NULL)
319    tmpMap=getMapFromMaps(conf,"lenv","usid");
320  int key=-1;
321  if(tmpMap!=NULL)
322    key=atoi(tmpMap->value);
323  return key;
324}
325
326/**
327 * Try to create or access a semaphore set.
328 *
329 * @see getKeyValue
330 * @param conf the map containing the setting of the main.cfg file
331 * @param nsems number of semaphores
332 * @return a semaphores set indentifier on success, -1 in other case
333 */
334int getShmLockId(maps* conf, int nsems){
335    int i;
336    union semun arg;
337    struct semid_ds buf;
338    struct sembuf sb;
339    semid sem_id;
340    int key=getKeyValue(conf);
341   
342    sem_id = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
343
344    if (sem_id >= 0) { /* we got it first */
345        sb.sem_op = 1; 
346        sb.sem_flg = 0;
347        arg.val=1;
348        for(sb.sem_num = 0; sb.sem_num < nsems; sb.sem_num++) { 
349            /* do a semop() to "free" the semaphores. */
350            /* this sets the sem_otime field, as needed below. */
351            if (semop(sem_id, &sb, 1) == -1) {
352                int e = errno;
353                semctl(sem_id, 0, IPC_RMID); /* clean up */
354                errno = e;
355                return -1; /* error, check errno */
356            }
357        }
358    } else if (errno == EEXIST) { /* someone else got it first */
359        int ready = 0;
360
361        sem_id = semget(key, nsems, 0); /* get the id */
362        if (sem_id < 0) return sem_id; /* error, check errno */
363
364        /* wait for other process to initialize the semaphore: */
365        arg.buf = &buf;
366        for(i = 0; i < MAX_RETRIES && !ready; i++) {
367            semctl(sem_id, nsems-1, IPC_STAT, arg);
368            if (arg.buf->sem_otime != 0) {
369#ifdef DEBUG
370              fprintf(stderr,"Semaphore acquired ...\n");
371#endif
372              ready = 1;
373            } else {
374#ifdef DEBUG
375              fprintf(stderr,"Retry to access the semaphore later ...\n");
376#endif
377              sleep(1);
378            }
379        }
380        errno = ZOO_LOCK_ACQUIRE_FAILED;
381        if (!ready) {
382#ifdef DEBUG
383          fprintf(stderr,"Unable to access the semaphore ...\n");
384#endif
385          errno = ETIME;
386          return -1;
387        }
388    } else {
389        return sem_id; /* error, check errno */
390    }
391#ifdef DEBUG
392    fprintf(stderr,"%d Created !\n",sem_id);
393#endif
394    return sem_id;
395}
396
397/**
398 * Try to remove a semaphore set.
399 *
400 * @param conf the map containing the setting of the main.cfg file
401 * @param nsems number of semaphores
402 * @return 0 if the semaphore can be removed, -1 in other case.
403 */
404int removeShmLock(maps* conf, int nsems){
405  union semun arg;
406  int sem_id=getShmLockId(conf,nsems);
407  if (semctl(sem_id, 0, IPC_RMID, arg) == -1) {
408    perror("semctl");
409    return -1;
410  }
411  return 0;
412}
413
414/**
415 * Lock a semaphore set.
416 *
417 * @param id the semaphores set indetifier
418 * @return 0 if the semaphore can be locked, -1 in other case.
419 */
420int lockShm(int id){
421  struct sembuf sb;
422  sb.sem_num = 0;
423  sb.sem_op = -1;  /* set to allocate resource */
424  sb.sem_flg = SEM_UNDO;
425  if (semop(id, &sb, 1) == -1){
426    perror("semop");
427    return -1;
428  }
429  return 0;
430}
431
432/**
433 * unLock a semaphore set.
434 *
435 * @param id the semaphores set indetifier
436 * @return 0 if the semaphore can be locked, -1 in other case.
437 */
438int unlockShm(int id){
439  struct sembuf sb;
440  sb.sem_num = 0;
441  sb.sem_op = 1;  /* free resource */
442  sb.sem_flg = SEM_UNDO;
443  if (semop(id, &sb, 1) == -1) {
444    perror("semop");
445    return -1;
446  }
447  return 0;
448}
449
450/**
451 * Stop handling status repport.
452 *
453 * @param conf the map containing the setting of the main.cfg file
454 */
455void unhandleStatus(maps *conf){
456  int shmid;
457  key_t key;
458  void *shm;
459  struct shmid_ds shmids;
460  map *tmpMap=getMapFromMaps(conf,"lenv","usid");
461  if(tmpMap!=NULL){
462    key=atoi(tmpMap->value);
463    if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
464#ifdef DEBUG
465      fprintf(stderr,"shmget failed to update value\n");
466#endif
467    }else{
468      if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
469#ifdef DEBUG
470        fprintf(stderr,"shmat failed to update value\n");
471#endif
472      }else{
473        shmdt(shm);
474        shmctl(shmid,IPC_RMID,&shmids);
475      }
476    }
477  }
478}
479
480/**
481 * Update the current of the running service.
482 *
483 * @see getKeyValue, getShmLockId, lockShm
484 * @param conf the map containing the setting of the main.cfg file
485 * @return 0 on success, -2 if shmget failed, -1 if shmat failed
486 */
487int _updateStatus(maps *conf){
488  int shmid;
489  char *shm,*s,*s1;
490  map *tmpMap=NULL;
491  key_t key=getKeyValue(conf);
492  if(key!=-1){
493    semid lockid=getShmLockId(conf,1);
494    if(lockid<0)
495      return ZOO_LOCK_CREATE_FAILED;
496    if(lockShm(lockid)<0){
497      return ZOO_LOCK_ACQUIRE_FAILED;
498    }
499    if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
500#ifdef DEBUG
501      fprintf(stderr,"shmget failed to create new Shared memory segment\n");
502#endif
503      unlockShm(lockid);
504      return -2;
505    }else{
506      if ((shm = (char*) shmat(shmid, NULL, 0)) == (char *) -1) {
507#ifdef DEBUG
508        fprintf(stderr,"shmat failed to update value\n");
509#endif
510        unlockShm(lockid);
511        return -1;
512      }
513      else{
514        tmpMap=getMapFromMaps(conf,"lenv","status");
515        s1=shm;
516        for(s=tmpMap->value;*s!=NULL && *s!=0;s++){
517          *s1++=*s;
518        }
519        *s1++='|';
520        tmpMap=getMapFromMaps(conf,"lenv","message");
521        if(tmpMap!=NULL)
522          for(s=tmpMap->value;*s!=NULL && *s!=0;s++){
523            *s1++=*s;
524        }
525        *s1=NULL;
526        shmdt((void *)shm);
527        unlockShm(lockid);
528      }
529    }
530  }
531  return 0;
532}
533
534/**
535 * Update the current of the running service.
536 *
537 * @see getKeyValue, getShmLockId, lockShm
538 * @param pid the semaphores
539 * @return 0 on success, -2 if shmget failed, -1 if shmat failed
540 */
541char* getStatus(int pid){
542  int shmid;
543  key_t key;
544  void *shm;
545  key=pid;
546  if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
547#ifdef DEBUG
548    fprintf(stderr,"shmget failed in getStatus\n");
549#endif
550  }else{
551    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
552#ifdef DEBUG
553      fprintf(stderr,"shmat failed in getStatus\n");
554#endif
555    }else{
556      char *ret=strdup((char*)shm);
557      shmdt((void *)shm);
558      return ret;
559    }
560  }
561  return (char*)"-1";
562}
563
564#endif
565
566/**
567 * Update the status of an ongoing service
568 *
569 * @param conf the maps containing the settings of the main.cfg file
570 * @param percentCompleted percentage of completude of execution of the service
571 * @param message information about the current step executed
572 * @return the value of _updateStatus
573 * @see _updateStatus
574 */
575int updateStatus( maps* conf, const int percentCompleted, const char* message ){
576  char tmp[4];
577  snprintf(tmp,4,"%d",percentCompleted);
578  setMapInMaps( conf, "lenv", "status", tmp );
579  setMapInMaps( conf, "lenv", "message", message);
580  return _updateStatus( conf );
581}
582
583/**
584 * Access an input value
585 *
586 * @param inputs the maps to search for the input value
587 * @param parameterName the input name to fetch the value
588 * @param numberOfBytes the resulting size of the value to add (for binary
589 *  values), -1 for basic char* data
590 * @return a pointer to the input value if found, NULL in other case.
591 */
592char* getInputValue( maps* inputs, const char* parameterName, size_t* numberOfBytes){
593  map* res=getMapFromMaps(inputs,parameterName,"value");
594  if(res!=NULL){
595    map* size=getMapFromMaps(inputs,parameterName,"size");
596    if(size!=NULL){
597      *numberOfBytes=(size_t)atoi(size->value);
598      return res->value;
599    }else{
600      *numberOfBytes=strlen(res->value);
601      return res->value;
602    }
603  }
604  return NULL;
605}
606
607/**
608 * Set an output value
609 *
610 * @param outputs the maps to define the output value
611 * @param parameterName the output name to set the value
612 * @param data the value to set
613 * @param numberOfBytes size of the value to add (for binary values), -1 for
614 *  basic char* data
615 * @return 0
616 */
617int  setOutputValue( maps* outputs, const char* parameterName, char* data, size_t numberOfBytes ){
618  if(numberOfBytes==-1){
619    setMapInMaps(outputs,parameterName,"value",data);
620  }else{
621    char size[1024];
622    map* tmp=getMapFromMaps(outputs,parameterName,"value");
623    if(tmp==NULL){
624      setMapInMaps(outputs,parameterName,"value","");
625      tmp=getMapFromMaps(outputs,parameterName,"value");
626    }
627    free(tmp->value);
628    tmp->value=(char*) malloc((numberOfBytes+1)*sizeof(char));
629    memcpy(tmp->value,data,numberOfBytes);
630    sprintf(size,"%lu",numberOfBytes);
631    setMapInMaps(outputs,parameterName,"size",size);
632  }
633  return 0;
634}
635
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