📄 factory.cpp
字号:
/* factory.cpp Remote object factory The remote object factory uses a lease-based system. Remote objects are purged from the pool when the lease expires. Supports inheritance. Compile: soapcpp2 factory.h c++ -o factory factory.cpp stdsoap2.cpp soapC.cpp soapServer.cpp Run (e.g. in the background) factory <port> where <port> is a available port number, e.g. 18085 Copyright (C) 2000-2002 Robert A. van Engelen. All Rights Reserved.*/#include <sys/stat.h> // for open()#include "soapH.h"#include "factory.nsmap"#define POOLSIZE 1000 // max number of remote objects that can be alive at any instance#define LEASETERM 60 // lease term (in seconds). Also the rate at which objects are purged//////////////////////////////////////////////////////////////////////////////////// Factory class maintains pool of objects and can act as a simple ORB//////////////////////////////////////////////////////////////////////////////////class Factory{ public: t__root *ref[POOLSIZE]; // pool of objects (t__root is base class) unsigned int handle; // handle generation counter (is allowed to wrap around 32 bits) Factory(); ~Factory(); unsigned int create(struct soap *soap, enum t__object object, char *name); unsigned int lookup(enum t__object object, char *name); unsigned int rename(unsigned int handle, char *name); void release(unsigned int handle); void purge(struct soap* soap); t__root *get(unsigned int handle); t__root *root(unsigned int handle); t__adder *adder(unsigned int handle); t__counter *counter(unsigned int handle); int save(const char *file); int load(const char *file);};// Initialize empty pool and set handle generation counter to 0Factory::Factory(){ for (int i = 0; i < POOLSIZE; i++) ref[i] = NULL; handle = 0;}// Remove all objects from poolFactory::~Factory(){ for (int i = 0; i < POOLSIZE; i++) if (ref[i]) delete ref[i];}// Create a new object, place it in the pool, and return handleunsigned int Factory::create(struct soap *soap, enum t__object object, char *name){ for (int i = 0; i < POOLSIZE; i++) if (!ref[++handle % POOLSIZE]) // succeeds if this slot is available { t__root *r = NULL; if (!handle) handle += POOLSIZE; // make sure handle is never 0 (0 indicates invalid handle) switch (object) // type of object to instantiate { case ROOT: r = new t__root(); break; case ADDER: r = new t__adder(); break; case COUNTER: r = new t__counter(); break; } if (r) { ref[handle % POOLSIZE] = r; // add object to the pool r->object = object; // save type if (name) // save name (if assigned) { r->name = (char*)malloc(strlen(name+1)); strcpy(r->name, name); } else r->name = NULL; r->handle = handle; // keep handle for verification r->renew(); // renew its lease return handle; } return 0; } return 0;}// Lookup the name of an object and return handleunsigned int Factory::lookup(enum t__object object, char *name){ for (int i = 0; i < POOLSIZE; i++) if (ref[i] && ref[i]->object == object && ref[i]->name && !strcmp(ref[i]->name, name)) { ref[i]->renew(); return ref[i]->handle; } return 0;}// Rename object and return handle if successfulunsigned int Factory::rename(unsigned int handle, char *name){ t__root *r = get(handle); if (r) { if (r->name) free(r->name); r->name = (char*)malloc(strlen(name)+1); strcpy(r->name, name); r->renew(); return handle; } return 0;}// get ref to object from handlet__root *Factory::get(unsigned int handle){ t__root *r = ref[handle % POOLSIZE]; if (r && r->handle == handle) return r; return NULL;}// get ref to root object from handle and renew leaset__root *Factory::root(unsigned int handle){ t__root *r = get(handle); if (r) r->renew(); return r;}// get ref to adder object from handle and renew leaset__adder *Factory::adder(unsigned int handle){ t__adder *a = (t__adder*)get(handle); if (a) { if (a->object == ADDER || a->object == COUNTER) a->renew(); else a = NULL; } return a;}// get ref to counter object from handle and renew leaset__counter *Factory::counter(unsigned int handle){ t__counter *c = (t__counter*)get(handle); if (c) { if (c->object == COUNTER) c->renew(); else c = NULL; } return c;}// remove all objects from pool whose lease has expiredvoid Factory::purge(struct soap *soap){ time_t t = time(NULL); // current time int flag = 1; for (int i = 0; i < POOLSIZE; i++) { t__root *r = ref[i]; if (r && r->lease < t) // expired? { if (flag) fprintf(stderr, "\nPurging objects:"); if (r->name) fprintf(stderr, "%s(%u)\n", r->name, r->handle); else fprintf(stderr, "(%u)\n", r->handle); soap_delete(soap, r); ref[i] = NULL; flag = 0; } }}// remove object from pool and release slotvoid Factory::release(unsigned int handle){ t__root *r = get(handle); if (r) ref[handle % POOLSIZE] = NULL;}// save object pool to file (or stdout)int Factory::save(const char *file){ struct soap soap; // use a new local gSOAP environment soap_init(&soap); soap_begin(&soap); if (file) soap.sendfd = open(file, O_CREAT|O_TRUNC|O_WRONLY, S_IREAD|S_IWRITE); if (soap.sendfd < 0) return -1; soap_begin_send(&soap); for (int i = 0; i < POOLSIZE; i++) if (ref[i]) { ref[i]->soap_serialize(&soap); soap_begin_send(&soap); ref[i]->soap_put(&soap, "item", NULL); soap_end_send(&soap); } if (file) close(soap.sendfd); soap_end(&soap); soap_done(&soap); return 0;}// load object pool from file (or stdin)int Factory::load(const char *file){ struct soap soap; t__root *r; soap_init(&soap); if (file) soap.recvfd = open(file, O_RDONLY); if (soap.recvfd < 0) return -1; soap_begin_recv(&soap); for (int i = 0; i < POOLSIZE; i++) { if (ref[i]) { delete ref[i]; ref[i] = NULL; } } for (;;) { r = soap_in_t__root(&soap, "item", NULL, NULL); // use the 'in' routine ('get' will also attempt to parse the remaining XML) if (r) ref[r->handle % POOLSIZE] = r; else break; } if (file) close(soap.recvfd); if (soap.error != SOAP_OK && soap.error != SOAP_EOF) { soap_print_fault(&soap, stderr); soap_print_fault_location(&soap, stderr); } soap_free(&soap); // do not call soap_end: this would remove all deserialized data soap_done(&soap); return 0;}//////////////////////////////////////////////////////////////////////////////////// Main server program//////////////////////////////////////////////////////////////////////////////////int main(int argc, char **argv){ int m, s; struct soap soap; Factory factory; // create factory and simple ORB soap_init(&soap); soap.user = (void*)&factory; // associate factory with run-time soap.accept_timeout = 1; // check every second, if not too busy for purging objects if (argc < 2) { 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) factory.purge(&soap); soap_serve(&soap); factory.save("factory.dat"); // ... and save afterwards } else { m = soap_bind(&soap, NULL, atoi(argv[1]), 100); // use command line argument as port number if (m < 0) { soap_print_fault(&soap, stderr); exit(1); } fprintf(stderr, "Socket connection successful %d\n", m); for (int i = 1; ; i++) { s = soap_accept(&soap); if (s < 0) { if (soap.errnum) soap_print_fault(&soap, stderr); else // errnum is 0, which means a timeout has occurred { factory.purge(&soap); // purge objects whose lease has ran out continue; } exit(1); } 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); soap_serve(&soap); fprintf(stderr, "served\n"); soap_end(&soap); // clean up: this will remove deserialized data } } return 0;}//////////////////////////////////////////////////////////////////////////////////// Remote factory method implementations//////////////////////////////////////////////////////////////////////////////////int ns__create(struct soap *soap, enum t__object object, char *name, enum t__status &status){ Factory *factory = (Factory*)soap->user; // get factory from gSOAP environment if (!soap->header) soap->header = (struct SOAP_ENV__Header*)soap_malloc(soap, sizeof(struct SOAP_ENV__Header)); if (soap->header) { soap->header->h__handle = factory->create(soap, object, name); if (soap->header->h__handle) status = FACTORY_OK; else status = FACTORY_INVALID; } else status = FACTORY_RETRY; return SOAP_OK;}int ns__lookup(struct soap *soap, enum t__object object, char *name, enum t__status &status){ Factory *factory = (Factory*)soap->user; // get factory from gSOAP environment if (!soap->header) soap->header = (struct SOAP_ENV__Header*)soap_malloc(soap, sizeof(struct SOAP_ENV__Header)); if (soap->header) { soap->header->h__handle = factory->lookup(object, name); if (soap->header->h__handle) status = FACTORY_OK; else status = FACTORY_NOTFOUND; } else status = FACTORY_RETRY; return SOAP_OK;}int ns__rename(struct soap *soap, char *name, enum t__status &status){ Factory *factory = (Factory*)soap->user; // get factory from gSOAP environment if (soap->header) { soap->header->h__handle = factory->rename(soap->header->h__handle, name); if (soap->header->h__handle) status = FACTORY_OK; else status = FACTORY_INVALID; } else status = FACTORY_INVALID; return SOAP_OK;}int ns__release(struct soap *soap, enum t__status &status){ Factory *factory = (Factory*)soap->user; // get factory from gSOAP environment if (soap->header && soap->header->h__handle) { factory->release(soap->header->h__handle); status = FACTORY_OK; } else status = FACTORY_INVALID; return SOAP_OK;}//////////////////////////////////////////////////////////////////////////////////// Remote adder method implementations//////////////////////////////////////////////////////////////////////////////////int ns__set(struct soap *soap, double val, enum t__status &status){ Factory *factory = (Factory*)soap->user; // get factory from gSOAP environment if (soap->header) { t__adder *adder = factory->adder(soap->header->h__handle); if (adder) { adder->set(val); status = FACTORY_OK; } else status = FACTORY_INVALID; } else status = FACTORY_INVALID; return SOAP_OK;}int ns__get(struct soap *soap, double &val){ Factory *factory = (Factory*)soap->user; // get factory from gSOAP environment val = DBL_NAN; if (soap->header) { t__adder *adder = factory->adder(soap->header->h__handle); if (adder) val = adder->get(); } return SOAP_OK;}int ns__add(struct soap *soap, double val, enum t__status &status){ Factory *factory = (Factory*)soap->user; // get factory from gSOAP environment if (soap->header) { t__adder *adder = factory->adder(soap->header->h__handle); if (adder) { adder->add(val); status = FACTORY_OK; } else status = FACTORY_INVALID; } else status = FACTORY_INVALID; return SOAP_OK;}//////////////////////////////////////////////////////////////////////////////////// Remote counter method implementations//////////////////////////////////////////////////////////////////////////////////int ns__inc(struct soap *soap, enum t__status &status){ Factory *factory = (Factory*)soap->user; // get factory from gSOAP environment if (soap->header) { t__counter *counter = factory->counter(soap->header->h__handle); if (counter) { counter->inc(); status = FACTORY_OK; } else status = FACTORY_INVALID; } else status = FACTORY_INVALID; return SOAP_OK;}//////////////////////////////////////////////////////////////////////////////////// Server-side base factory class methods//////////////////////////////////////////////////////////////////////////////////t__root::t__root(){ }t__root::~t__root(){ if (name) free(name);}void t__root::renew(){ lease = time(NULL) + LEASETERM; // can adopt a leasing policy per class}//////////////////////////////////////////////////////////////////////////////////// Server-side adder class methods//////////////////////////////////////////////////////////////////////////////////void t__adder::set(double val){ this->val = val; // copy data to update state}double t__adder::get(){ return val;}void t__adder::add(double val){ this->val += val;}//////////////////////////////////////////////////////////////////////////////////// Server-side counter class methods//////////////////////////////////////////////////////////////////////////////////void t__counter::inc(){ add(1.0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -