~vcs-imports/simias/trunk

« back to all changes in this revision

Viewing changes to simias/tools/gsoap/gsoap-linux-2.7/samples/factory/factory.cpp

  • Committer: kalidasbala
  • Date: 2007-08-25 12:48:51 UTC
  • Revision ID: vcs-imports@canonical.com-20070825124851-vlfvzun3732ld196
Latest gsoap code update

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      factory.cpp
 
2
 
 
3
        Remote object factory
 
4
 
 
5
        The remote object factory uses a lease-based system. Remote objects
 
6
        are purged from the pool when the lease expires. Supports inheritance.
 
7
 
 
8
        Compile:
 
9
        soapcpp2 factory.h
 
10
        c++ -o factory factory.cpp stdsoap2.cpp soapC.cpp soapServer.cpp
 
11
 
 
12
        Run (e.g. in the background)
 
13
        factory <port>
 
14
        where <port> is a available port number, e.g. 18085
 
15
 
 
16
        Copyright (C) 2000-2002 Robert A. van Engelen. All Rights Reserved.
 
17
*/
 
18
 
 
19
#include <sys/stat.h>   // for open()
 
20
 
 
21
#include "soapH.h"
 
22
#include "factory.nsmap"
 
23
 
 
24
#define POOLSIZE 1000   // max number of remote objects that can be alive at any instance
 
25
 
 
26
#define LEASETERM 60    // lease term (in seconds). Also the rate at which objects are purged
 
27
 
 
28
////////////////////////////////////////////////////////////////////////////////
 
29
//
 
30
//  Factory class maintains pool of objects and can act as a simple ORB
 
31
//
 
32
////////////////////////////////////////////////////////////////////////////////
 
33
 
 
34
class Factory
 
35
{ public:
 
36
  t__root *ref[POOLSIZE];       // pool of objects (t__root is base class)
 
37
  unsigned int handle;          // handle generation counter (is allowed to wrap around 32 bits)
 
38
  Factory();
 
39
  ~Factory();
 
40
  unsigned int create(struct soap *soap, enum t__object object, char *name);
 
41
  unsigned int lookup(enum t__object object, char *name);
 
42
  unsigned int rename(unsigned int handle, char *name);
 
43
  void release(unsigned int handle);
 
44
  void purge(struct soap* soap);
 
45
  t__root *get(unsigned int handle);
 
46
  t__root *root(unsigned int handle);
 
47
  t__adder *adder(unsigned int handle);
 
48
  t__counter *counter(unsigned int handle);
 
49
  int save(const char *file);
 
50
  int load(const char *file);
 
51
};
 
52
 
 
53
// Initialize empty pool and set handle generation counter to 0
 
54
Factory::Factory()
 
55
{ for (int i = 0; i < POOLSIZE; i++)
 
56
    ref[i] = NULL;
 
57
  handle = 0;
 
58
}
 
59
 
 
60
// Remove all objects from pool
 
61
Factory::~Factory()
 
62
{ for (int i = 0; i < POOLSIZE; i++)
 
63
    if (ref[i])
 
64
      delete ref[i];
 
65
}
 
66
 
 
67
// Create a new object, place it in the pool, and return handle
 
68
unsigned int Factory::create(struct soap *soap, enum t__object object, char *name)
 
69
{ for (int i = 0; i < POOLSIZE; i++)
 
70
    if (!ref[++handle % POOLSIZE])      // succeeds if this slot is available
 
71
    { t__root *r = NULL;
 
72
      if (!handle)
 
73
        handle += POOLSIZE;             // make sure handle is never 0 (0 indicates invalid handle)
 
74
      switch (object)                   // type of object to instantiate
 
75
      { case ROOT:
 
76
          r = new t__root();
 
77
          break;
 
78
        case ADDER:
 
79
          r = new t__adder();
 
80
          break;
 
81
        case COUNTER:
 
82
          r = new t__counter();
 
83
          break;
 
84
      }
 
85
      if (r)
 
86
      { ref[handle % POOLSIZE] = r;             // add object to the pool
 
87
        r->object = object;                     // save type
 
88
        if (name)                               // save name (if assigned)
 
89
        { r->name = (char*)malloc(strlen(name+1));
 
90
          strcpy(r->name, name);
 
91
        }
 
92
        else
 
93
          r->name = NULL;
 
94
        r->handle = handle;                     // keep handle for verification
 
95
        r->renew();                             // renew its lease
 
96
        return handle;
 
97
      }
 
98
      return 0;
 
99
    }
 
100
  return 0;
 
101
}
 
102
 
 
103
// Lookup the name of an object and return handle
 
104
unsigned int Factory::lookup(enum t__object object, char *name)
 
105
{ for (int i = 0; i < POOLSIZE; i++)
 
106
    if (ref[i] && ref[i]->object == object && ref[i]->name && !strcmp(ref[i]->name, name))
 
107
    { ref[i]->renew();
 
108
      return ref[i]->handle;
 
109
    }
 
110
  return 0;
 
111
}
 
112
 
 
113
// Rename object and return handle if successful
 
114
unsigned int Factory::rename(unsigned int handle, char *name)
 
115
{ t__root *r = get(handle);
 
116
  if (r)
 
117
  { if (r->name)
 
118
      free(r->name);
 
119
    r->name = (char*)malloc(strlen(name)+1);
 
120
    strcpy(r->name, name);
 
121
    r->renew();
 
122
    return handle;
 
123
  }
 
124
  return 0;
 
125
}
 
126
 
 
127
// get ref to object from handle
 
128
t__root *Factory::get(unsigned int handle)
 
129
{ t__root *r = ref[handle % POOLSIZE];
 
130
  if (r && r->handle == handle)
 
131
    return r;
 
132
  return NULL;
 
133
}
 
134
 
 
135
// get ref to root object from handle and renew lease
 
136
t__root *Factory::root(unsigned int handle)
 
137
{ t__root *r = get(handle);
 
138
  if (r)
 
139
    r->renew();
 
140
  return r;
 
141
}
 
142
 
 
143
// get ref to adder object from handle and renew lease
 
144
t__adder *Factory::adder(unsigned int handle)
 
145
{ t__adder *a = (t__adder*)get(handle);
 
146
  if (a)
 
147
  { if (a->object == ADDER || a->object == COUNTER)
 
148
      a->renew();
 
149
    else
 
150
      a = NULL;
 
151
  }
 
152
  return a;
 
153
}
 
154
 
 
155
// get ref to counter object from handle and renew lease
 
156
t__counter *Factory::counter(unsigned int handle)
 
157
{ t__counter *c = (t__counter*)get(handle);
 
158
  if (c)
 
159
  { if (c->object == COUNTER)
 
160
      c->renew();
 
161
    else
 
162
      c = NULL;
 
163
  }
 
164
  return c;
 
165
}
 
166
 
 
167
// remove all objects from pool whose lease has expired
 
168
void Factory::purge(struct soap *soap)
 
169
{ time_t t = time(NULL);                // current time
 
170
  int flag = 1;
 
171
  for (int i = 0; i < POOLSIZE; i++)
 
172
  { t__root *r = ref[i];
 
173
    if (r && r->lease < t)              // expired?
 
174
    { if (flag)
 
175
        fprintf(stderr, "\nPurging objects:");
 
176
      if (r->name)
 
177
        fprintf(stderr, "%s(%u)\n", r->name, r->handle);
 
178
      else
 
179
        fprintf(stderr, "(%u)\n", r->handle);
 
180
      soap_delete(soap, r);
 
181
      ref[i] = NULL;
 
182
      flag = 0;
 
183
    }
 
184
  }
 
185
}
 
186
 
 
187
// remove object from pool and release slot
 
188
void Factory::release(unsigned int handle)
 
189
{ t__root *r = get(handle);
 
190
  if (r)
 
191
    ref[handle % POOLSIZE] = NULL;
 
192
}
 
193
 
 
194
// save object pool to file (or stdout)
 
195
int Factory::save(const char *file)
 
196
{ struct soap soap;     // use a new local gSOAP environment
 
197
  soap_init(&soap);
 
198
  soap_begin(&soap);
 
199
  if (file)
 
200
    soap.sendfd = open(file, O_CREAT|O_TRUNC|O_WRONLY, S_IREAD|S_IWRITE);
 
201
  if (soap.sendfd < 0)
 
202
    return -1;
 
203
  soap_begin_send(&soap);
 
204
  for (int i = 0; i < POOLSIZE; i++)
 
205
    if (ref[i])
 
206
    { ref[i]->soap_serialize(&soap);
 
207
      soap_begin_send(&soap);
 
208
      ref[i]->soap_put(&soap, "item", NULL);
 
209
      soap_end_send(&soap);
 
210
    }
 
211
  if (file)
 
212
    close(soap.sendfd);
 
213
  soap_end(&soap);
 
214
  soap_done(&soap);
 
215
  return 0;
 
216
}
 
217
 
 
218
// load object pool from file (or stdin)
 
219
int Factory::load(const char *file)
 
220
{ struct soap soap;
 
221
  t__root *r;
 
222
  soap_init(&soap);
 
223
  if (file)
 
224
    soap.recvfd = open(file, O_RDONLY);
 
225
  if (soap.recvfd < 0)
 
226
    return -1;
 
227
  soap_begin_recv(&soap);
 
228
  for (int i = 0; i < POOLSIZE; i++)
 
229
  { if (ref[i])
 
230
    { delete ref[i];
 
231
      ref[i] = NULL;
 
232
    }
 
233
  }
 
234
  for (;;)
 
235
  { r = soap_in_t__root(&soap, "item", NULL, NULL);     // use the 'in' routine ('get' will also attempt to parse the remaining XML)
 
236
    if (r)
 
237
      ref[r->handle % POOLSIZE] = r;
 
238
    else
 
239
      break;
 
240
  }
 
241
  if (file)
 
242
    close(soap.recvfd);
 
243
  if (soap.error != SOAP_OK && soap.error != SOAP_EOF)
 
244
  { soap_print_fault(&soap, stderr);
 
245
    soap_print_fault_location(&soap, stderr);
 
246
  }
 
247
  soap_free(&soap);     // do not call soap_end: this would remove all deserialized data
 
248
  soap_done(&soap);
 
249
  return 0;
 
250
}
 
251
 
 
252
////////////////////////////////////////////////////////////////////////////////
 
253
//
 
254
//  Main server program
 
255
//
 
256
////////////////////////////////////////////////////////////////////////////////
 
257
 
 
258
int main(int argc, char **argv)
 
259
{ int m, s;
 
260
  struct soap soap;
 
261
  Factory factory;                      // create factory and simple ORB
 
262
  soap_init(&soap);
 
263
  soap.user = (void*)&factory;          // associate factory with run-time
 
264
  soap.accept_timeout = 1;              // check every second, if not too busy for purging objects
 
265
  if (argc < 2)
 
266
  { factory.load("factory.dat");        // if CGI is used, load the entire pool (not very efficient and there may be a competition for access to this file! This is just to demonstrate load/save of the entire pool)
 
267
    factory.purge(&soap);
 
268
    soap_serve(&soap);
 
269
    factory.save("factory.dat");        // ... and save afterwards
 
270
  }
 
271
  else
 
272
  { m = soap_bind(&soap, NULL, atoi(argv[1]), 100);     // use command line argument as port number
 
273
    if (m < 0)
 
274
    { soap_print_fault(&soap, stderr);
 
275
      exit(1);
 
276
    }
 
277
    fprintf(stderr, "Socket connection successful %d\n", m);
 
278
    for (int i = 1; ; i++)
 
279
    { s = soap_accept(&soap);
 
280
      if (s < 0)
 
281
      { if (soap.errnum)
 
282
          soap_print_fault(&soap, stderr);
 
283
        else                    // errnum is 0, which means a timeout has occurred
 
284
        { factory.purge(&soap); // purge objects whose lease has ran out
 
285
          continue;
 
286
        }
 
287
        exit(1);
 
288
      }
 
289
      fprintf(stderr, "%d: accepted %d IP=%d.%d.%d.%d ... ", i, s, (int)(soap.ip>>24)&0xFF, (int)(soap.ip>>16)&0xFF, (int)(soap.ip>>8)&0xFF, (int)soap.ip&0xFF);
 
290
      soap_serve(&soap);
 
291
      fprintf(stderr, "served\n");
 
292
      soap_end(&soap);          // clean up: this will remove deserialized data
 
293
    }
 
294
  }
 
295
  return 0;
 
296
}
 
297
 
 
298
////////////////////////////////////////////////////////////////////////////////
 
299
//
 
300
//  Remote factory method implementations
 
301
//
 
302
////////////////////////////////////////////////////////////////////////////////
 
303
 
 
304
int ns__create(struct soap *soap, enum t__object object, char *name, enum t__status &status)
 
305
{ Factory *factory = (Factory*)soap->user;      // get factory from gSOAP environment
 
306
  if (!soap->header)
 
307
    soap->header = (struct SOAP_ENV__Header*)soap_malloc(soap, sizeof(struct SOAP_ENV__Header));
 
308
  if (soap->header)
 
309
  { soap->header->h__handle = factory->create(soap, object, name);
 
310
    if (soap->header->h__handle)
 
311
      status = FACTORY_OK;
 
312
    else
 
313
      status = FACTORY_INVALID;
 
314
  }
 
315
  else
 
316
    status = FACTORY_RETRY;
 
317
  return SOAP_OK;
 
318
}
 
319
 
 
320
int ns__lookup(struct soap *soap, enum t__object object, char *name, enum t__status &status)
 
321
{ Factory *factory = (Factory*)soap->user;      // get factory from gSOAP environment
 
322
  if (!soap->header)
 
323
    soap->header = (struct SOAP_ENV__Header*)soap_malloc(soap, sizeof(struct SOAP_ENV__Header));
 
324
  if (soap->header)
 
325
  { soap->header->h__handle = factory->lookup(object, name);
 
326
    if (soap->header->h__handle)
 
327
      status = FACTORY_OK;
 
328
    else
 
329
      status = FACTORY_NOTFOUND;
 
330
  }
 
331
  else
 
332
    status = FACTORY_RETRY;
 
333
  return SOAP_OK;
 
334
}
 
335
 
 
336
int ns__rename(struct soap *soap, char *name, enum t__status &status)
 
337
{ Factory *factory = (Factory*)soap->user;      // get factory from gSOAP environment
 
338
  if (soap->header)
 
339
  { soap->header->h__handle = factory->rename(soap->header->h__handle, name);
 
340
    if (soap->header->h__handle)
 
341
      status = FACTORY_OK;
 
342
    else
 
343
      status = FACTORY_INVALID;
 
344
  }
 
345
  else
 
346
    status = FACTORY_INVALID;
 
347
  return SOAP_OK;
 
348
}
 
349
 
 
350
int ns__release(struct soap *soap, enum t__status &status)
 
351
{ Factory *factory = (Factory*)soap->user;      // get factory from gSOAP environment
 
352
  if (soap->header && soap->header->h__handle)
 
353
  { factory->release(soap->header->h__handle);
 
354
    status = FACTORY_OK;
 
355
  }
 
356
  else
 
357
    status = FACTORY_INVALID;
 
358
  return SOAP_OK;
 
359
}
 
360
 
 
361
////////////////////////////////////////////////////////////////////////////////
 
362
//
 
363
//  Remote adder method implementations
 
364
//
 
365
////////////////////////////////////////////////////////////////////////////////
 
366
 
 
367
int ns__set(struct soap *soap, double val, enum t__status &status)
 
368
{ Factory *factory = (Factory*)soap->user;      // get factory from gSOAP environment
 
369
  if (soap->header)
 
370
  { t__adder *adder = factory->adder(soap->header->h__handle);
 
371
    if (adder)
 
372
    { adder->set(val);
 
373
      status = FACTORY_OK;
 
374
    }
 
375
    else
 
376
      status = FACTORY_INVALID;
 
377
  }
 
378
  else
 
379
    status = FACTORY_INVALID;
 
380
  return SOAP_OK;
 
381
}
 
382
 
 
383
int ns__get(struct soap *soap, double &val)
 
384
{ Factory *factory = (Factory*)soap->user;      // get factory from gSOAP environment
 
385
  val = DBL_NAN;
 
386
  if (soap->header)
 
387
  { t__adder *adder = factory->adder(soap->header->h__handle);
 
388
    if (adder)
 
389
      val = adder->get();
 
390
  }
 
391
  return SOAP_OK;
 
392
}
 
393
 
 
394
int ns__add(struct soap *soap, double val, enum t__status &status)
 
395
{ Factory *factory = (Factory*)soap->user;      // get factory from gSOAP environment
 
396
  if (soap->header)
 
397
  { t__adder *adder = factory->adder(soap->header->h__handle);
 
398
    if (adder)
 
399
    { adder->add(val);
 
400
      status = FACTORY_OK;
 
401
    }
 
402
    else
 
403
      status = FACTORY_INVALID;
 
404
  }
 
405
  else
 
406
    status = FACTORY_INVALID;
 
407
  return SOAP_OK;
 
408
}
 
409
 
 
410
////////////////////////////////////////////////////////////////////////////////
 
411
//
 
412
//  Remote counter method implementations
 
413
//
 
414
////////////////////////////////////////////////////////////////////////////////
 
415
 
 
416
int ns__inc(struct soap *soap, enum t__status &status)
 
417
{ Factory *factory = (Factory*)soap->user;      // get factory from gSOAP environment
 
418
  if (soap->header)
 
419
  { t__counter *counter = factory->counter(soap->header->h__handle);
 
420
    if (counter)
 
421
    { counter->inc();
 
422
      status = FACTORY_OK;
 
423
    }
 
424
    else
 
425
      status = FACTORY_INVALID;
 
426
  }
 
427
  else
 
428
    status = FACTORY_INVALID;
 
429
  return SOAP_OK;
 
430
}
 
431
 
 
432
////////////////////////////////////////////////////////////////////////////////
 
433
//
 
434
//  Server-side base factory class methods
 
435
//
 
436
////////////////////////////////////////////////////////////////////////////////
 
437
 
 
438
t__root::t__root()
 
439
{ }
 
440
 
 
441
t__root::~t__root()
 
442
{ if (name)
 
443
    free(name);
 
444
}
 
445
 
 
446
void t__root::renew()
 
447
{ lease = time(NULL) + LEASETERM;       // can adopt a leasing policy per class
 
448
}
 
449
 
 
450
////////////////////////////////////////////////////////////////////////////////
 
451
//
 
452
//  Server-side adder class methods
 
453
//
 
454
////////////////////////////////////////////////////////////////////////////////
 
455
 
 
456
void t__adder::set(double val)
 
457
{ this->val = val;      // copy data to update state
 
458
}
 
459
 
 
460
double t__adder::get()
 
461
{ return val;
 
462
}
 
463
 
 
464
void t__adder::add(double val)
 
465
{ this->val += val;
 
466
}
 
467
 
 
468
////////////////////////////////////////////////////////////////////////////////
 
469
//
 
470
//  Server-side counter class methods
 
471
//
 
472
////////////////////////////////////////////////////////////////////////////////
 
473
 
 
474
void t__counter::inc()
 
475
{ add(1.0);
 
476
}
 
477