Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

commcenter.cc

Go to the documentation of this file.
00001 /*
00002   svas_server -- virtual World Server of Svas
00003   Copyright (c) 2001, 2002 David Moreno Montero
00004  
00005  
00006   This program is free software; you can redistribute it and/or modify
00007   it under the terms of the GNU General Public License as published by
00008   the Free Software Foundation; either version 2 of the License, or
00009   (at your option) any later version.
00010  
00011   This program is distributed in the hope that it will be useful, but
00012   WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   General Public License for more details.
00015  
00016   You should have received a copy of the GNU General Public License
00017   along with this program; if not, write to the Free Software
00018   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00019   02111-1307, USA.  
00020 
00021 */
00022 
00023 #include <thread.h>
00024 #include <math.h>
00025 #include <stdlib.h>
00026 #include "commcenter.h"
00027 #include "baseClient.h"
00028 #include "client.h"
00029 #include "controlClient.h"
00030 #include "graphicClient.h"
00031 #include "log.h"
00032 #include "world.h"
00033 #include <unistd.h>
00034 #include <persist.h>
00035 #include <sched.h>
00036 
00037 /**
00038  * Creates the communication center. It opens several ports to accept
00039  * incomming conections; these ports include: 
00040  *
00041  * * client port (2002)
00042  * * graphic client port (3003)
00043  * * control client port (3004)
00044  * * server port (8888)
00045  */
00046 CommCenter::CommCenter(){
00047   try{
00048     clientPort=new ost::TCPSocket(ost::InetAddress(), 2002);
00049     graphicClientPort=new ost::TCPSocket(ost::InetAddress(), 3003);
00050     controlClientPort=new ost::TCPSocket(ost::InetAddress(), 3004);
00051     
00052     serverPort=new ost::TCPSocket(ost::InetAddress(), 8888);
00053   }
00054   catch(...){
00055     log <<"Can't bind one of the TCPSockets, desired ports are 2002, 3003, 3004 and 8888"<<endl;
00056     throw ost::Exception("Can't Bind socket");
00057   }
00058 
00059   world=new World(this);
00060   if (NULL==world){
00061     log <<"Can't create a world!"<<endl;
00062     throw ost::Exception("No world, no fun");
00063   }
00064   
00065 }
00066 
00067 /**
00068  * Destroys the comm center; the open ports are closed.
00069  */
00070 CommCenter::~CommCenter(){
00071   delete clientPort;
00072   delete graphicClientPort;
00073   delete controlClientPort;
00074 
00075   delete serverPort;
00076 
00077   log<<"Deleting clients"<<endl;
00078 
00079   /// A bug here, in deleting clients, it blocks. FIXME
00080   unsigned int i;
00081   for (i=0;i<clients.size();i++)
00082     delete clients[i];
00083   
00084   clients.clear();
00085 
00086   log<<"Goodbye!"<<endl;
00087 }
00088 
00089 /**
00090  * Loops thruogh the open ports to check for new conections; if one
00091  * appears the correct handler is called
00092  */
00093 void CommCenter::loop(){
00094   log <<"Entering in the main thread loop"<<endl;
00095 
00096   while (world->getQuit()==false){
00097     checkForConections();
00098 
00099     waitForClients();
00100 
00101     makeMovements();
00102     if (clients.size()!=0)
00103       andTimePasses(); // Only if there is anyone to look at it...
00104   }
00105 
00106   log <<"Quitting the main thread loop"<<endl;
00107 }
00108 
00109 /** 
00110  * Creates a new client, and starts it.
00111  */
00112 void CommCenter::newClient(){
00113   Client *cl;
00114   clients.push_back(cl=new Client(*clientPort,world));
00115   cl->Start();
00116   clientMap[cl->getName()].push_back(cl); // Add it to the dictionary of AgentClients
00117 
00118   //  clients[clients.size()-1]->dontWalk();
00119 }
00120 
00121 /** 
00122  * Creates a new graphic client, starts it, and stop it's execution (I
00123  * can ensure that it's safe to let it run any time before dontWalk is
00124  * issued
00125  */
00126 void CommCenter::newGraphicClient(){
00127   clients.push_back(new GraphicClient(*graphicClientPort,world));
00128   clients[clients.size()-1]->Start();
00129   //  clients[clients.size()-1]->dontWalk();
00130 }
00131 
00132 /** 
00133  * Creates a new control client, and starts it.
00134  */
00135 void CommCenter::newControlClient(){
00136   clients.push_back(new ControlClient(*controlClientPort,world));
00137   clients[clients.size()-1]->Start();
00138   //  clients[clients.size()-1]->dontWalk();
00139 }
00140 
00141 /** 
00142  * Creates a new server channel, and starts it.
00143  */
00144 void CommCenter::newServer(){
00145   log <<"New Server"<<endl;
00146 }
00147 
00148 
00149 /**
00150  * Checks if there are new conections on any of the client ports, or
00151  * in the server port, and creates the threads and clients 
00152  */
00153 void CommCenter::checkForConections(){
00154   if (clientPort->isPendingConnection(0)) newClient();
00155   if (graphicClientPort->isPendingConnection(0)) newGraphicClient();
00156   if (controlClientPort->isPendingConnection(0)) newControlClient();
00157   if (serverPort->isPendingConnection(0)) newServer();
00158 }
00159 
00160 /** 
00161  * Checks if there are dead clients, and decrements the numClients to
00162  * wait
00163  */
00164 void CommCenter::checkForDeadClients(){
00165   unsigned int i;
00166   for (i=0;i<clients.size();i++)
00167     if (!clients[i]->isAlive())
00168       --(world->numClients);
00169 }
00170 
00171 /**
00172  * Deletes not Alive clients
00173  */
00174 void CommCenter::removeDeadClients(){
00175   unsigned int i;
00176   for (i=clients.size();i--;)
00177     if (!clients[i]->isAlive()){
00178       delete clients[i];
00179       clients.erase(&clients[i]);
00180     }
00181 }
00182 
00183 /** 
00184  * Waits till all clients have finished the run cycle
00185  */
00186 void CommCenter::waitForClients(){
00187   /// First Wake up clients
00188   world->numClients=clients.size();
00189   unsigned int i;
00190   for (i=clients.size();i--;)
00191     clients[i]->walk();
00192 
00193 
00194   /// Poll till all clients sleep again, or if none, just yield
00195   /// (usleep(3) yields, see sched_yield(2))
00196   do{
00197     checkForDeadClients();
00198     //sched_yield();
00199     usleep(10000);
00200     //usleep(1000);
00201   }while (world->numClients>0);
00202   if (clients.size()==0)
00203     usleep(10);
00204 
00205   /// Remove dead clients
00206   removeDeadClients();
00207 }
00208 
00209 /**
00210  * Make the movements done
00211  */
00212 void CommCenter::makeMovements(){
00213   world->step();
00214 }
00215 
00216 /**
00217  * Searches a suitable client for migration of an agent
00218  *
00219  * Actually it does it selecting one pseudo-random agentClient from
00220  * the list of clients with the same name of actual agent
00221  */
00222 Client *CommCenter::getClientForMigration(string name){
00223   static unsigned int i=0;
00224   if (clientMap.count(name)!=0){
00225     unsigned int n=(i++)%clientMap[name].size();
00226     log <<"Migration to number "<<n<<" of "<<clientMap[name].size()<<"("<<i<<")"<<endl;
00227     return clientMap[name][n];
00228   }
00229   return NULL;
00230 }

Generated on Mon Jun 17 19:53:44 2002 for Svas Server by doxygen1.2.16