⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 factory.cpp

📁 linux下简单对象应用协议的开发库
💻 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 + -