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

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

Added some new logging functionality (function logMessage(), macros zooLog, zooLogMsg). Added utility functions setErrorMessage(), hasvalue(), and nonempty() in service.c. Added enum WPSException and arrays WPSExceptionText and WPSExceptionCode (see also function setErrorMessage). New conditional definition of type bool in service.c (to fix issue with bool). Null pointer check in function addToMap. Added missing return values and explicit type casts in some functions. Removed Windows-specific code in function dumpBackFinalFile (zoo_service_loader.c) that may cause error for async raw data output in formats other than XML.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 18.6 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#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#ifndef TRUE
34#define TRUE 1
35#endif
36#ifndef FALSE
37#define FALSE -1
38#endif
39
40#define ERROR_MSG_MAX_LENGTH 1024
41#ifndef RELY_ON_DB
42#include <dirent.h>
43
44/**
45 * Read the sid file attached of a service if any
46 *
47 * @param conf the maps containing the setting of the main.cfg file
48 * @param pid the service identifier (usid key from the [lenv] section)
49 * @return the reported status char* (temporary/final result)
50 */
51char* getStatusId(maps* conf,char* pid){
52  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
53  char* fbkpid =
54    (char *)
55    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
56  sprintf (fbkpid, "%s/%s.sid", r_inputs->value, pid);
57  FILE* f0 = fopen (fbkpid, "r");
58  if(f0!=NULL){
59    long flen;
60    char *fcontent;
61    fseek (f0, 0, SEEK_END);
62    flen = ftell (f0);
63    fseek (f0, 0, SEEK_SET);
64    fcontent = (char *) malloc ((flen + 1) * sizeof (char));
65    fread(fcontent,flen,1,f0);
66    fcontent[flen]=0;
67    fclose(f0);
68    return fcontent;
69  }else
70    return NULL;
71}
72
73/**
74 * Acquire the global lock
75 *
76 * @param conf the maps containing the setting of the main.cfg file
77 * @return a semid
78 */
79semid acquireLock(maps* conf){
80  semid lockid;
81  int itn=0;
82 toRetry1:
83  lockid=getShmLockId(conf,1);
84  if(
85#ifdef WIN32
86     lockid==NULL
87#else
88     lockid<0
89#endif
90     ){
91#ifdef WIN32
92    return NULL;
93#else
94    return -1;
95#endif
96  }
97  if(lockShm(lockid)<0){
98#ifdef WIN32
99      return NULL;
100#else
101    if(itn<ZOO_LOCK_MAX_RETRY){
102      itn++;
103      goto toRetry1;
104    }else
105      return -1;
106#endif
107  }else
108    return lockid;
109}
110
111/**
112 * Read the cache file of a running service
113 *
114 * @param conf the maps containing the setting of the main.cfg file
115 * @param pid the service identifier (usid key from the [lenv] section)
116 * @return the reported status char* (temporary/final result)
117 */
118char* _getStatusFile(maps* conf,char* pid){
119  map* tmpTmap = getMapFromMaps (conf, "main", "tmpPath");
120
121  struct dirent *dp;
122  DIR *dirp = opendir(tmpTmap->value);
123  char fileName[1024];
124  int hasFile=-1;
125  if(dirp!=NULL){
126    char tmp[128];
127    sprintf(tmp,"_%s.xml",pid);
128    while ((dp = readdir(dirp)) != NULL){
129#ifdef DEBUG
130      fprintf(stderr,"File : %s searched : %s\n",dp->d_name,tmp);
131#endif
132      if(strstr(dp->d_name,"final_")==0 && strstr(dp->d_name,tmp)!=0){
133        sprintf(fileName,"%s/%s",tmpTmap->value,dp->d_name);
134        hasFile=1;
135        break;
136      }
137    }
138  }
139  if(hasFile>0){
140    semid lockid;
141    char* stat=getStatusId(conf,pid);
142    if(stat!=NULL){
143      setMapInMaps(conf,"lenv","lid",stat);
144      lockid=acquireLock(conf);
145      if(lockid<0)
146        return NULL;
147    }
148
149    //FILE* f0 = fopen (fileName, "r");
150        // knut: open file in binary mode to avoid conversion of line endings (yielding extra bytes) on Windows platforms
151        FILE* f0 = fopen(fileName, "rb"); 
152    if(f0!=NULL){
153      fseek (f0, 0, SEEK_END);
154      long flen = ftell (f0);
155      fseek (f0, 0, SEEK_SET);
156      char *tmps1 = (char *) malloc ((flen + 1) * sizeof (char));
157      fread(tmps1,flen,1,f0);
158      tmps1[flen]=0;
159      fclose(f0);
160      if(stat!=NULL){
161        unlockShm(lockid);
162        free(stat);
163      }
164
165      return tmps1;
166    }
167    else{
168      if(stat!=NULL){
169        unlockShm(lockid);
170        free(stat);
171      }
172      return NULL;
173    }
174  }
175  else
176    return NULL;
177}
178
179/**
180 * Get the ongoing status of a running service
181 *
182 * @param conf the maps containing the setting of the main.cfg file
183 * @param pid the service identifier (usid key from the [lenv] section)
184 * @return the reported status char* (MESSAGE|POURCENTAGE)
185 */
186char* _getStatus(maps* conf,char* lid){
187  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
188  char* fbkpid =
189    (char *)
190    malloc ((strlen (r_inputs->value) + strlen (lid) + 9) * sizeof (char));
191  sprintf (fbkpid, "%s/%s.status", r_inputs->value, lid);
192  FILE* f0 = fopen (fbkpid, "r");
193  if(f0!=NULL){   
194    semid lockid = NULL;
195    char* stat;
196    long flen;
197    stat=getStatusId(conf,lid);
198    if(stat!=NULL){
199      setMapInMaps(conf,"lenv","lid",stat);
200      lockid=acquireLock(conf);
201      if(lockid<0)
202        return NULL;
203    }
204    fseek (f0, 0, SEEK_END);
205    flen = ftell (f0);
206    if(flen>0){
207      char *fcontent;
208      fseek (f0, 0, SEEK_SET);
209      fcontent = (char *) malloc ((flen + 1) * sizeof (char));
210      fread(fcontent,flen,1,f0);
211      fcontent[flen]=0;
212      fclose(f0);
213      free(fbkpid);
214      if(stat!=NULL){
215#ifndef WIN32
216        removeShmLock(conf,1);
217#else
218        unlockShm(lockid);
219#endif
220        free(stat);
221      }
222      return fcontent;
223    }
224    fclose(f0);
225    free(fbkpid);
226    if(stat!=NULL){
227      removeShmLock(conf,1);
228      free(stat);
229    }
230    return NULL;
231  }else{
232    free(fbkpid);
233    char* stat=getStatusId(conf,lid);
234    setMapInMaps(conf,"lenv","lid",stat);
235    removeShmLock(conf,1);
236    return NULL;
237  }
238}
239
240/**
241 * Stop handling status repport.
242 *
243 * @param conf the map containing the setting of the main.cfg file
244 */
245void unhandleStatus(maps *conf){       
246  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
247  map* usid = getMapFromMaps (conf, "lenv", "usid");
248  char* fbkpid =
249    (char *) malloc ((strlen (r_inputs->value) + strlen (usid->value) + 9) 
250                     * sizeof (char));
251  sprintf (fbkpid, "%s/%s.status", r_inputs->value, usid->value);
252  unlink(fbkpid);
253  free(fbkpid);
254}
255
256/**
257 * Update the current status of the running service.
258 *
259 * @see acquireLock, lockShm
260 * @param conf the map containing the setting of the main.cfg file
261 * @return 0 on success, -2 if shmget failed, -1 if shmat failed
262 */
263int _updateStatus(maps *conf){
264       
265  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
266  map* sid = getMapFromMaps (conf, "lenv", "usid");
267 
268  char* fbkpid =
269    (char *)
270    malloc ((strlen (r_inputs->value) + strlen (sid->value) + 9) * sizeof (char));
271  sprintf (fbkpid, "%s/%s.status", r_inputs->value, sid->value);
272  map* status=getMapFromMaps(conf,"lenv","status");
273  map* msg=getMapFromMaps(conf,"lenv","message");
274  if(status!=NULL && msg!=NULL &&
275     status->value!=NULL && msg->value!=NULL && 
276     strlen(status->value)>0 && strlen(msg->value)>1){   
277    semid lockid = NULL;
278       
279    char* stat=getStatusId(conf,sid->value);
280    if(stat!=NULL){
281      lockid=acquireLock(conf);
282      if(lockid<0){
283        dumpMap(status);
284        return ZOO_LOCK_ACQUIRE_FAILED;
285      }
286    }
287    FILE* fstatus=fopen(fbkpid,"w");
288    if(fstatus!=NULL){
289      fprintf(fstatus,"%s|%s",status->value,msg->value);
290      fflush(fstatus);
291      fclose(fstatus);
292    }
293    if(stat!=NULL){
294      unlockShm(lockid);
295      free(stat);
296    }
297  }
298
299  return 0;
300}
301
302#endif
303
304#ifdef WIN32
305
306#define SHMEMSIZE 4096
307
308size_t getKeyValue(maps* conf, char* key, size_t length){
309  if(conf==NULL) {
310    strncpy(key, "700666", length);
311    return strlen(key);
312  }
313 
314  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
315  if(tmpMap==NULL)
316    tmpMap=getMapFromMaps(conf,"lenv","osid");
317
318  if(tmpMap!=NULL){
319    snprintf(key, length, "zoo_sem_%s", tmpMap->value);     
320  }
321  else {
322    strncpy(key, "-1", length);
323  }
324  return strlen(key);
325}
326
327
328semid getShmLockId(maps* conf, int nsems){
329  semid sem_id;
330  char key[MAX_PATH];
331  getKeyValue(conf, key, MAX_PATH);
332 
333  sem_id = CreateSemaphore( NULL, nsems, nsems+1, key);
334  if(sem_id==NULL){
335#ifdef DEBUG
336    fprintf(stderr,"Semaphore failed to create: %s\n", getLastErrorMessage());
337#endif
338    return NULL;
339  }
340#ifdef DEBUG
341  fprintf(stderr,"%s Accessed !\n",key);
342#endif
343  return sem_id;
344}
345
346int removeShmLock(maps* conf, int nsems){
347  semid sem_id=getShmLockId(conf,1);
348  if (CloseHandle(sem_id) == 0) {
349#ifdef DEBUG
350    fprintf(stderr,"Unable to remove semaphore: %s\n", getLastErrorMessage());
351#endif
352    return -1;
353  }
354#ifdef DEBUG
355  fprintf(stderr,"%d Removed !\n",sem_id);
356#endif
357  return 0;
358}
359
360int lockShm(semid id){
361  DWORD dwWaitResult=WaitForSingleObject(id,INFINITE);
362  switch (dwWaitResult){
363    case WAIT_OBJECT_0:
364      return 0;
365      break;
366    case WAIT_TIMEOUT:
367      return -1;
368      break;
369    default:
370      return -2;
371      break;
372  }
373  return 0;
374}
375
376int unlockShm(semid id){
377  if(!ReleaseSemaphore(id,1,NULL)){
378    return -1;
379  }
380  return 0;
381}
382
383static LPVOID lpvMemG = NULL;      // pointer to shared memory
384static HANDLE hMapObjectG = NULL;  // handle to file mapping
385
386
387char* getStatus(int pid){
388  char *lpszBuf=(char*) malloc(SHMEMSIZE*sizeof(char));
389  int i=0;
390  LPWSTR lpszTmp=NULL;
391  LPVOID lpvMem = NULL;
392  HANDLE hMapObject = NULL;
393  BOOL fIgnore,fInit;
394  char tmp[1024];
395  sprintf(tmp,"%d",pid);
396  if(hMapObject==NULL)
397    hMapObject = CreateFileMapping( 
398                                   INVALID_HANDLE_VALUE,   // use paging file
399                                   NULL,                   // default security attributes
400                                   PAGE_READWRITE,         // read/write access
401                                   0,                      // size: high 32-bits
402                                   4096,                   // size: low 32-bits
403                                   TEXT(tmp));   // name of map object
404  if (hMapObject == NULL){
405#ifdef DEBUG
406    fprintf(stderr,"ERROR on line %d\n",__LINE__);
407#endif
408    return "-1";
409  }
410  if((GetLastError() != ERROR_ALREADY_EXISTS)){
411#ifdef DEBUG
412    fprintf(stderr,"ERROR on line %d\n",__LINE__);
413    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
414#endif
415    fIgnore = UnmapViewOfFile(lpvMem); 
416    fIgnore = CloseHandle(hMapObject);
417    return "-1";
418  }
419  fInit=TRUE;
420  if(lpvMem==NULL)
421    lpvMem = MapViewOfFile( 
422                           hMapObject,     // object to map view of
423                           FILE_MAP_READ,  // read/write access
424                           0,              // high offset:  map from
425                           0,              // low offset:   beginning
426                           0);             // default: map entire file
427  if (lpvMem == NULL){
428#ifdef DEBUG
429    fprintf(stderr,"READING STRING S %d\n",__LINE__);
430    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
431#endif
432    return "-1"; 
433  }
434  lpszTmp = (LPWSTR) lpvMem;
435  while (*lpszTmp){
436    lpszBuf[i] = (char)*lpszTmp;
437    *lpszTmp++; 
438    lpszBuf[i+1] = '\0'; 
439    i++;
440  }
441  return (char*)lpszBuf;
442}
443
444#else
445/**
446 * Number of time to try to access a semaphores set
447 * @see getShmLockId
448 */
449#define MAX_RETRIES 10
450
451#ifndef __APPLE__
452/**
453 * arg for semctl system calls.
454 */
455union semun {
456  int val; //!< value for SETVAL
457  struct semid_ds *buf; //!< buffer for IPC_STAT & IPC_SET
458  ushort *array; //!< array for GETALL & SETALL
459};
460#endif
461
462/**
463 * Set in the pre-allocated key the zoo_sem_[OSID] string
464 * where [OSID] is the lid (if any) or osid value from the [lenv] section.
465 *
466 * @param conf the map containing the setting of the main.cfg file
467 */
468int getKeyValue(maps* conf){
469  if(conf==NULL)
470     return 700666;
471  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
472  if(tmpMap==NULL)
473    tmpMap=getMapFromMaps(conf,"lenv","osid");
474  int key=-1;
475  if(tmpMap!=NULL)
476    key=atoi(tmpMap->value);
477  return key;
478}
479
480/**
481 * Try to create or access a semaphore set.
482 *
483 * @see getKeyValue
484 * @param conf the map containing the setting of the main.cfg file
485 * @param nsems number of semaphores
486 * @return a semaphores set indentifier on success, -1 in other case
487 */
488int getShmLockId(maps* conf, int nsems){
489    int i;
490    union semun arg;
491    struct semid_ds buf;
492    struct sembuf sb;
493    semid sem_id;
494    int key=getKeyValue(conf);
495   
496    sem_id = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
497
498    if (sem_id >= 0) { /* we got it first */
499        sb.sem_op = 1; 
500        sb.sem_flg = 0;
501        arg.val=1;
502        for(sb.sem_num = 0; sb.sem_num < nsems; sb.sem_num++) { 
503            /* do a semop() to "free" the semaphores. */
504            /* this sets the sem_otime field, as needed below. */
505            if (semop(sem_id, &sb, 1) == -1) {
506                int e = errno;
507                semctl(sem_id, 0, IPC_RMID); /* clean up */
508                errno = e;
509                return -1; /* error, check errno */
510            }
511        }
512    } else if (errno == EEXIST) { /* someone else got it first */
513        int ready = 0;
514
515        sem_id = semget(key, nsems, 0); /* get the id */
516        if (sem_id < 0) return sem_id; /* error, check errno */
517
518        /* wait for other process to initialize the semaphore: */
519        arg.buf = &buf;
520        for(i = 0; i < MAX_RETRIES && !ready; i++) {
521            semctl(sem_id, nsems-1, IPC_STAT, arg);
522            if (arg.buf->sem_otime != 0) {
523#ifdef DEBUG
524              fprintf(stderr,"Semaphore acquired ...\n");
525#endif
526              ready = 1;
527            } else {
528#ifdef DEBUG
529              fprintf(stderr,"Retry to access the semaphore later ...\n");
530#endif
531              zSleep(1);
532            }
533        }
534        errno = ZOO_LOCK_ACQUIRE_FAILED;
535        if (!ready) {
536#ifdef DEBUG
537          fprintf(stderr,"Unable to access the semaphore ...\n");
538#endif
539          errno = ETIME;
540          return -1;
541        }
542    } else {
543        return sem_id; /* error, check errno */
544    }
545#ifdef DEBUG
546    fprintf(stderr,"%d Created !\n",sem_id);
547#endif
548    return sem_id;
549}
550
551/**
552 * Try to remove a semaphore set.
553 *
554 * @param conf the map containing the setting of the main.cfg file
555 * @param nsems number of semaphores
556 * @return 0 if the semaphore can be removed, -1 in other case.
557 */
558int removeShmLock(maps* conf, int nsems){
559  union semun arg;
560  int sem_id=getShmLockId(conf,nsems);
561  if (semctl(sem_id, 0, IPC_RMID, arg) == -1) {
562#ifdef DEBUG
563    perror("semctl remove");
564#endif
565    return -1;
566  }
567#ifdef DEBUG
568  fprintf(stderr,"Semaphore removed!\n");
569#endif
570  return 0;
571}
572
573/**
574 * Lock a semaphore set.
575 *
576 * @param id the semaphores set indetifier
577 * @return 0 if the semaphore can be locked, -1 in other case.
578 */
579int lockShm(int id){
580  struct sembuf sb;
581  sb.sem_num = 0;
582  sb.sem_op = -1;  /* set to allocate resource */
583  sb.sem_flg = SEM_UNDO;
584  if (semop(id, &sb, 1) == -1){
585#ifdef DEBUG
586    perror("semop lock");
587#endif
588    return -1;
589  }
590  return 0;
591}
592
593/**
594 * unLock a semaphore set.
595 *
596 * @param id the semaphores set indetifier
597 * @return 0 if the semaphore can be locked, -1 in other case.
598 */
599int unlockShm(int id){
600  struct sembuf sb;
601  sb.sem_num = 0;
602  sb.sem_op = 1;  /* free resource */
603  sb.sem_flg = SEM_UNDO;
604  if (semop(id, &sb, 1) == -1) {
605#ifdef DEBUG
606    perror("semop unlock");
607#endif
608    return -1;
609  }
610  return 0;
611}
612
613/**
614 * Get the current status of the running service.
615 *
616 * @see getKeyValue, getShmLockId, lockShm
617 * @param pid the semaphores
618 * @return 0 on success, -2 if shmget failed, -1 if shmat failed
619 */
620char* getStatus(int pid){
621  int shmid;
622  key_t key;
623  void *shm;
624  key=pid;
625  if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
626#ifdef DEBUG
627    fprintf(stderr,"shmget failed in getStatus\n");
628#endif
629  }else{
630    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
631#ifdef DEBUG
632      fprintf(stderr,"shmat failed in getStatus\n");
633#endif
634    }else{
635      char *ret=strdup((char*)shm);
636      shmdt((void *)shm);
637      return ret;
638    }
639  }
640  return (char*)"-1";
641}
642
643#endif
644
645/**
646 * Update the status of an ongoing service
647 *
648 * @param conf the maps containing the settings of the main.cfg file
649 * @param percentCompleted percentage of completude of execution of the service
650 * @param message information about the current step executed
651 * @return the value of _updateStatus
652 * @see _updateStatus
653 */
654int updateStatus( maps* conf, const int percentCompleted, const char* message ){
655  char tmp[4];
656  snprintf(tmp,4,"%d",percentCompleted);
657  setMapInMaps( conf, "lenv", "status", tmp );
658  setMapInMaps( conf, "lenv", "message", message);
659  return _updateStatus( conf );
660}
661
662/**
663 * Access an input value
664 *
665 * @param inputs the maps to search for the input value
666 * @param parameterName the input name to fetch the value
667 * @param numberOfBytes the resulting size of the value to add (for binary
668 *  values), -1 for basic char* data
669 * @return a pointer to the input value if found, NULL in other case.
670 */
671char* getInputValue( maps* inputs, const char* parameterName, size_t* numberOfBytes){
672  map* res=getMapFromMaps(inputs,parameterName,"value");
673  if(res!=NULL){
674    map* size=getMapFromMaps(inputs,parameterName,"size");
675    if(size!=NULL){
676      *numberOfBytes=(size_t)atoi(size->value);
677      return res->value;
678    }else{
679      *numberOfBytes=strlen(res->value);
680      return res->value;
681    }
682  }
683  return NULL;
684}
685
686/**
687 * Read a file using the GDAL VSI API
688 *
689 * @param conf the maps containing the settings of the main.cfg file
690 * @param dataSource the datasource name to read
691 * @warning make sure to free resources returned by this function
692 */
693char *readVSIFile(maps* conf,const char* dataSource){
694    VSILFILE * fichier=VSIFOpenL(dataSource,"rb");
695    VSIStatBufL file_status;
696    VSIStatL(dataSource, &file_status);
697    if(fichier==NULL){
698      char tmp[1024];
699      sprintf(tmp,"Failed to open file %s for reading purpose. File seems empty %lld.",
700              dataSource,file_status.st_size);
701      setMapInMaps(conf,"lenv","message",tmp);
702      return NULL;
703    }
704    char *res1=(char *)malloc(file_status.st_size*sizeof(char));
705    VSIFReadL(res1,1,file_status.st_size*sizeof(char),fichier);
706    res1[file_status.st_size-1]=0;
707    VSIFCloseL(fichier);
708    VSIUnlink(dataSource);
709    return res1;
710}
711
712/**
713 * Set an output value
714 *
715 * @param outputs the maps to define the output value
716 * @param parameterName the output name to set the value
717 * @param data the value to set
718 * @param numberOfBytes size of the value to add (for binary values), -1 for
719 *  basic char* data
720 * @return 0
721 */
722int  setOutputValue( maps* outputs, const char* parameterName, char* data, size_t numberOfBytes ){
723  if(numberOfBytes==-1){
724    setMapInMaps(outputs,parameterName,"value",data);
725  }else{
726    char size[1024];
727    map* tmp=getMapFromMaps(outputs,parameterName,"value");
728    if(tmp==NULL){
729      setMapInMaps(outputs,parameterName,"value","");
730      tmp=getMapFromMaps(outputs,parameterName,"value");
731    }
732    free(tmp->value);
733    tmp->value=(char*) malloc((numberOfBytes+1)*sizeof(char));
734    memcpy(tmp->value,data,numberOfBytes);
735    sprintf(size,"%lu",numberOfBytes);
736    setMapInMaps(outputs,parameterName,"size",size);
737  }
738  return 0;
739}
740
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