Panda3D
 All Classes Functions Variables Enumerations
pStatServer.cxx
00001 // Filename: pStatServer.cxx
00002 // Created by:  drose (09Jul00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pStatServer.h"
00016 #include "pStatReader.h"
00017 #include "thread.h"
00018 #include "config_pstats.h"
00019 
00020 ////////////////////////////////////////////////////////////////////
00021 //     Function: PStatServer::Constructor
00022 //       Access: Public
00023 //  Description:
00024 ////////////////////////////////////////////////////////////////////
00025 PStatServer::
00026 PStatServer() {
00027   _listener = new PStatListener(this);
00028   _next_udp_port = 0;
00029 }
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: PStatServer::Destructor
00033 //       Access: Public
00034 //  Description:
00035 ////////////////////////////////////////////////////////////////////
00036 PStatServer::
00037 ~PStatServer() {
00038   delete _listener;
00039 }
00040 
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: PStatServer::listen
00044 //       Access: Public
00045 //  Description: Establishes a port number that the manager will
00046 //               listen on for TCP connections.  This may be called
00047 //               more than once to listen simulataneously on multiple
00048 //               connections, as if that were at all useful.
00049 //
00050 //               The default parameter, -1, indicates the use of
00051 //               whatever port number has been indicated in the Config
00052 //               file.
00053 //
00054 //               This function returns true if the port was
00055 //               successfully opened, or false if it could not open
00056 //               the port.
00057 ////////////////////////////////////////////////////////////////////
00058 bool PStatServer::
00059 listen(int port) {
00060   if (port < 0) {
00061     port = pstats_port;
00062   }
00063 
00064   // Now try to listen to the port.
00065   PT(Connection) rendezvous = open_TCP_server_rendezvous(port, 5);
00066 
00067   if (rendezvous.is_null()) {
00068     // Couldn't get it.
00069     return false;
00070   }
00071 
00072   // Tell the listener about the new port.
00073   _listener->add_connection(rendezvous);
00074 
00075   if (_next_udp_port == 0) {
00076     _next_udp_port = port + 1;
00077   }
00078   return true;
00079 }
00080 
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: PStatServer::poll
00084 //       Access: Public
00085 //  Description: Checks for any network activity and handles it, if
00086 //               appropriate, and then returns.  This must be called
00087 //               periodically unless is_thread_safe() is redefined to
00088 //               return true on this class and also on all
00089 //               PStatMonitors in use.
00090 //
00091 //               Alternatively, a program may call main_loop() and
00092 //               yield control of the program entirely to the
00093 //               PStatServer.
00094 ////////////////////////////////////////////////////////////////////
00095 void PStatServer::
00096 poll() {
00097   // Delete all the readers that we couldn't delete before.
00098   while (!_lost_readers.empty()) {
00099     PStatReader *reader = _lost_readers.back();
00100     _lost_readers.pop_back();
00101 
00102     reader->lost_connection();
00103     delete reader;
00104   }
00105   while (!_removed_readers.empty()) {
00106     PStatReader *reader = _removed_readers.back();
00107     _removed_readers.pop_back();
00108     delete reader;
00109   }
00110 
00111   _listener->poll();
00112 
00113   Readers::const_iterator ri = _readers.begin();
00114   while (ri != _readers.end()) {
00115     // Preincrement the iterator, in case we remove it as a result of
00116     // calling poll().
00117     Readers::const_iterator rnext = ri;
00118     ++rnext;
00119     PStatReader *reader = (*ri).second;
00120 
00121     reader->poll();
00122     reader->idle();
00123     
00124     ri = rnext;
00125   }
00126 }
00127 
00128 ////////////////////////////////////////////////////////////////////
00129 //     Function: PStatServer::main_loop
00130 //       Access: Public
00131 //  Description: An alternative to repeatedly calling poll(), this
00132 //               function yields control of the program to the
00133 //               PStatServer.  It does not return until the program
00134 //               is done.
00135 //
00136 //               If interrupt_flag is non-NULL, it is the address of a
00137 //               bool variable that is initially false, and may be
00138 //               asynchronously set true to indicate the loop should
00139 //               terminate.
00140 ////////////////////////////////////////////////////////////////////
00141 void PStatServer::
00142 main_loop(bool *interrupt_flag) {
00143   while (interrupt_flag == (bool *)NULL || !*interrupt_flag) {
00144     poll();
00145     Thread::sleep(0.1);
00146   }
00147 }
00148 
00149 ////////////////////////////////////////////////////////////////////
00150 //     Function: PStatServer::add_reader
00151 //       Access: Public
00152 //  Description: Adds the newly-created PStatReader to the list of
00153 //               currently active readers.
00154 ////////////////////////////////////////////////////////////////////
00155 void PStatServer::
00156 add_reader(Connection *connection, PStatReader *reader) {
00157   _readers[connection] = reader;
00158 }
00159 
00160 ////////////////////////////////////////////////////////////////////
00161 //     Function: PStatServer::remove_reader
00162 //       Access: Public
00163 //  Description: Removes the indicated reader.
00164 ////////////////////////////////////////////////////////////////////
00165 void PStatServer::
00166 remove_reader(Connection *connection, PStatReader *reader) {
00167   Readers::iterator ri;
00168   ri = _readers.find(connection);
00169   if (ri == _readers.end() || (*ri).second != reader) {
00170     nout << "Attempt to remove undefined reader.\n";
00171   } else {
00172     _readers.erase(ri);
00173     _removed_readers.push_back(reader);
00174   }
00175 }
00176 
00177 ////////////////////////////////////////////////////////////////////
00178 //     Function: PStatServer::get_udp_port
00179 //       Access: Public
00180 //  Description: Returns a new port number that will probably be free
00181 //               to use as a UDP port.  The caller should be prepared
00182 //               to accept the possibility that it will be already in
00183 //               use by another process, however.
00184 ////////////////////////////////////////////////////////////////////
00185 int PStatServer::
00186 get_udp_port() {
00187   if (_available_udp_ports.empty()) {
00188     return _next_udp_port++;
00189   }
00190   int udp_port = _available_udp_ports.front();
00191   _available_udp_ports.pop_front();
00192   return udp_port;
00193 }
00194 
00195 ////////////////////////////////////////////////////////////////////
00196 //     Function: PStatServer::release_udp_port
00197 //       Access: Public
00198 //  Description: Indicates that the given UDP port is once again free
00199 //               for use.
00200 ////////////////////////////////////////////////////////////////////
00201 void PStatServer::
00202 release_udp_port(int port) {
00203   _available_udp_ports.push_back(port);
00204 }
00205 
00206 ////////////////////////////////////////////////////////////////////
00207 //     Function: PStatServer::get_num_user_guide_bars
00208 //       Access: Public
00209 //  Description: Returns the current number of user-defined guide
00210 //               bars.
00211 ////////////////////////////////////////////////////////////////////
00212 int PStatServer::
00213 get_num_user_guide_bars() const {
00214   return _user_guide_bars.size();
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: PStatServer::get_user_guide_bar_height
00219 //       Access: Public
00220 //  Description: Returns the height of the nth user-defined guide bar.
00221 ////////////////////////////////////////////////////////////////////
00222 double PStatServer::
00223 get_user_guide_bar_height(int n) const {
00224   nassertr(n >= 0 && n < (int)_user_guide_bars.size(), 0.0f);
00225   return _user_guide_bars[n];
00226 }
00227 
00228 ////////////////////////////////////////////////////////////////////
00229 //     Function: PStatServer::move_user_guide_bar
00230 //       Access: Public
00231 //  Description: Adjusts the height of the nth user-defined guide bar.
00232 ////////////////////////////////////////////////////////////////////
00233 void PStatServer::
00234 move_user_guide_bar(int n, double height) {
00235   nassertv(n >= 0 && n < (int)_user_guide_bars.size());
00236   _user_guide_bars[n] = height;
00237   user_guide_bars_changed();
00238 }
00239 
00240 ////////////////////////////////////////////////////////////////////
00241 //     Function: PStatServer::add_user_guide_bar
00242 //       Access: Public
00243 //  Description: Creates a new user guide bar and returns its index
00244 //               number.
00245 ////////////////////////////////////////////////////////////////////
00246 int PStatServer::
00247 add_user_guide_bar(double height) {
00248   int n = (int)_user_guide_bars.size();
00249   _user_guide_bars.push_back(height);
00250   user_guide_bars_changed();
00251 
00252   return n;
00253 }
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: PStatServer::remove_user_guide_bar
00257 //       Access: Public
00258 //  Description: Removes the user guide bar with the indicated index
00259 //               number.  All subsequent index numbers are adjusted
00260 //               down one.
00261 ////////////////////////////////////////////////////////////////////
00262 void PStatServer::
00263 remove_user_guide_bar(int n) {
00264   nassertv(n >= 0 && n < (int)_user_guide_bars.size());
00265   _user_guide_bars.erase(_user_guide_bars.begin() + n);
00266   user_guide_bars_changed();
00267 }
00268 
00269 ////////////////////////////////////////////////////////////////////
00270 //     Function: PStatServer::find_user_guide_bar
00271 //       Access: Public
00272 //  Description: Returns the index number of the first user guide bar
00273 //               found whose height is within the indicated range, or
00274 //               -1 if no user guide bars fall within the range.
00275 ////////////////////////////////////////////////////////////////////
00276 int PStatServer::
00277 find_user_guide_bar(double from_height, double to_height) const {
00278   GuideBars::const_iterator gbi;
00279   for (gbi = _user_guide_bars.begin();
00280        gbi != _user_guide_bars.end();
00281        ++gbi) {
00282     double height = (*gbi);
00283     if (height >= from_height && height <= to_height) {
00284       return (int)(gbi - _user_guide_bars.begin());
00285     }
00286   }
00287 
00288   return -1;
00289 }
00290 
00291 ////////////////////////////////////////////////////////////////////
00292 //     Function: PStatServer::user_guide_bars_changed
00293 //       Access: Priate
00294 //  Description: Called when the user guide bars have been changed.
00295 ////////////////////////////////////////////////////////////////////
00296 void PStatServer::
00297 user_guide_bars_changed() {
00298   Readers::iterator ri;
00299   for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
00300     (*ri).second->get_monitor()->user_guide_bars_changed();
00301   }
00302 }
00303 
00304 ////////////////////////////////////////////////////////////////////
00305 //     Function: PStatServer::is_thread_safe
00306 //       Access: Public
00307 //  Description: This should be redefined to return true in derived
00308 //               classes that want to deal with multithreaded readers
00309 //               and such.  If this returns true, the manager will
00310 //               create the listener in its own thread, and thus the
00311 //               PStatReader constructors at least will run in a
00312 //               different thread.
00313 //
00314 //               This is not related to the question of whether the
00315 //               reader can handle multiple different
00316 //               PStatThreadDatas; it's strictly a question of whether
00317 //               the readers themselves can run in a separate thread.
00318 ////////////////////////////////////////////////////////////////////
00319 bool PStatServer::
00320 is_thread_safe() {
00321   return false;
00322 }
00323 
00324 ////////////////////////////////////////////////////////////////////
00325 //     Function: PStatServer::connection_reset
00326 //       Access: Protected, Virtual
00327 //  Description: Called when a lost connection is detected by the net
00328 //               code, this should pass the word on to the interested
00329 //               parties and clean up gracefully.
00330 ////////////////////////////////////////////////////////////////////
00331 void PStatServer::
00332 connection_reset(const PT(Connection) &connection, bool okflag) {
00333   // Was this a client connection?  Tell the reader about it if it
00334   // was.
00335   close_connection(connection);
00336 
00337   Readers::iterator ri;
00338   ri = _readers.find(connection);
00339   if (ri != _readers.end()) {
00340     PStatReader *reader = (*ri).second;
00341     _readers.erase(ri);
00342 
00343     // Unfortunately, we can't delete the reader right away, because
00344     // we might have been called from a method on the reader!  We'll
00345     // have to save the reader pointer and delete it some time later.
00346     _lost_readers.push_back(reader);
00347   }
00348 }
 All Classes Functions Variables Enumerations