NetworkReturn * ScarabServer::startListening() { NetworkReturn * rc = new NetworkReturn(); mdebug("startListening()"); if(listening) { rc->setMWorksCode(NR_SUCCESS_NETWORK_MESSAGE); rc->setInformation("Server is already running."); return rc; } if(listenUri.size() == 0) { rc->setMWorksCode(NR_FAILED); rc->setInformation("URI not specified for server"); return rc; } std::string fullUri = createScarabURI(); if(fullUri.size() == 0) { rc->setMWorksCode(NR_FAILED); rc->setInformation("Could not create a valid URI"); return rc; } int error = 1; // mnetwork("Trying listening socket at %s on port %d", // listenAddress.c_str(), // listenPort); // mprintf("URI = %s", fullUri.c_str()); listeningSocket = scarab_session_listen(fullUri.c_str()); error = getScarabError(listeningSocket); while(error) { mnetwork("Failed to open a listening socket at %s on port %d", listenAddress.c_str(), listenPort); //mdebug("Maybe print out why here??"); // if there is another available port we will try again if(!chooseNewPort()) { rc->setMWorksCode(NR_FATAL_ERROR); rc->setPackageCode(error); rc->setOSErrorCode(getScarabOSError(listeningSocket)); rc->setInformation("Ran out of ports to listen on. Networking impossible"); rc->appendInformation(getScarabErrorDescription(error)); rc->appendInformation(getOSErrorDescription( getScarabOSError(listeningSocket))); return rc; } fullUri = createScarabURI(); listeningSocket = scarab_session_listen(fullUri.c_str()); error = getScarabError(listeningSocket); } mnetwork("Listening socket started at %s on port %d", listenAddress.c_str(), listenPort); listening = true; return rc; }
int getScarabOSError(ScarabSession * session) { if(getScarabError(session)) { return scarab_session_getoserr(session); } else { return 0; } }
void logDescriptiveScarabMessage(ScarabSession * s) { int scCode = getScarabError(s); // scarab error code int oserr = getScarabOSError(s); const char *scarab_error_string = scarab_strerror(scCode); mnetwork("ERROR: SCR-%5.5i: %s: %s", scCode, scarab_moderror(scCode), scarab_error_string); if(oserr) { const char *scarab_os_error_string = scarab_os_strerror(oserr); mnetwork("OSERR: %i: %s", oserr, scarab_os_error_string); } }
int ScarabWriteConnection::service() { boost::mutex::scoped_lock lock(connectLock); static int n_written = 0; shared_ptr <Clock> clock = Clock::instance(); static MWTime start_time = clock->getCurrentTimeUS(); // static int functionCount = 0; // mdebug("entering write service"); // struct timespec time_to_sleep; // time_to_sleep.tv_sec = 0; // time_to_sleep.tv_nsec = 200000000; //200 ms // while(1) { // mdebug("start write while loop"); // if(servicing) { // // we are already servicing this connection. // mdebug("Already Servicing Writing"); // M_ISUNLOCK; // continue; // //1return 1; // } servicing = true; // mdebug("Started servicing write function count = %d", functionCount); // functionCount++; if(getScarabError(pipe)) { mwarning(M_NETWORK_MESSAGE_DOMAIN, "Session Failure on ID %ld", cid); servicing = false; if(sibling) { sibling->setInterrupt(true); } term = true; return -1; } // if we have been requested to get interrupted // if we are interrupted while processing events there will be a // slight delay while out task is re-scheduled if(interrupt) { mwarning(M_NETWORK_MESSAGE_DOMAIN, "Write Service Routine Interrupted on id %ld", cid); if(sibling) { sibling->setInterrupt(true); } ScarabDatum * termEvent; // puts a control event of type termination into a scarab package // and sends the package termEvent = scarab_list_new(SCARAB_EVENT_N_TOPLEVEL_ELEMENTS); ScarabDatum *termCode = scarab_new_integer(RESERVED_TERMINATION_CODE); scarab_list_put(termEvent, SCARAB_EVENT_CODEC_CODE_INDEX, termCode); scarab_free_datum(termCode); shared_ptr <Clock> clock = Clock::instance(); ScarabDatum *time = scarab_new_integer(clock->getCurrentTimeUS()); scarab_list_put(termEvent, SCARAB_EVENT_TIME_INDEX, time); scarab_free_datum(time); if(scarab_write(pipe, termEvent) == 0) { // success mdebug("Wrote termination message from id %ld", cid); servicing = false; term = true; // mark the connection for termination scarab_free_datum(termEvent); return 0; } else { mwarning(M_NETWORK_MESSAGE_DOMAIN, "Failed to Write Termination Sequence on socket %ld", cid); // even though there was an error we are going to // terminate term = true; // mark the connection for termination scarab_free_datum(termEvent); return -1; } scarab_free_datum(termEvent); } // while we have events to process but havent been requested for // interruption. while(buffer_reader->nextEventExists() && !interrupt) { //MWTime event_time = newevent->getTime(); //mEventType type = newevent->getEventType(); //mVariable *var = newevent->getParam(); ScarabDatum * scarab_event; #define USE_EXPLICIT_BUFFERING 1 #define BUFFER_HIGH_WATER_MARK 1 #define MAX_EVENTS_TO_BUFFER 10000 if(USE_EXPLICIT_BUFFERING && buffer_reader->hasAtLeastNEvents(BUFFER_HIGH_WATER_MARK)) { scarab_force_buffering(pipe, 1); // fill up the macro event int numEventsBuffered = 0; bool buffering = true; do { shared_ptr<Event> newevent = buffer_reader->getNextEvent(); if(newevent == NULL) { // don't send anything if an event was NULL. servicing = false; scarab_free_datum(scarab_event); return 1; } scarab_event = newevent->toScarabDatum(); // stop buffering when you run out of events, or you hit the max events if(!(buffering = buffer_reader->nextEventExists() && numEventsBuffered<MAX_EVENTS_TO_BUFFER)) { scarab_force_buffering(pipe, 0); } if(scarab_write(pipe, scarab_event) == 0) { n_written++; } else { merror(M_SYSTEM_MESSAGE_DOMAIN, "scarab buffered write error"); servicing = false; return -1; } scarab_free_datum(scarab_event); ++numEventsBuffered; } while(buffering); } else { // Single event write shared_ptr<Event> newevent = buffer_reader->getNextEvent(); if(newevent == NULL) { // don't send anything if an event was NULL. servicing = false; return 1; } scarab_event = newevent->toScarabDatum(); if(scarab_write(pipe, scarab_event) == 0) { n_written++; } else { merror(M_SYSTEM_MESSAGE_DOMAIN, "scarab write error"); servicing = false; return -1; } scarab_free_datum(scarab_event); } // Some reporting #define N 1000 static int last_nwritten = 0; if(n_written - last_nwritten >= N){ last_nwritten = n_written; MWTime now = clock->getCurrentTimeUS(); /*fprintf(stderr, "last: %lld, now: %lld\n", start_time, now ); */ // fprintf(stderr, "%g events / sec (%d event in %lld usec)\n", // (double)N / howlong, // N, now - start_time // ); // fprintf(stderr, "Number of items unserviced: %d\n", // buffer_reader->getNItemsUnserviced()); // fflush(stderr); start_time = now; } } servicing = false; return 1; // } }
int ScarabServer::service() { if(1){ //while(1) { if(getScarabError(listeningSocket)) { merror(M_NETWORK_MESSAGE_DOMAIN, "Session failure on listening socket"); logDescriptiveScarabMessage(listeningSocket); return -1; } // this number should eventually come from the network // manager at construction time. connectionLock->lock(); int check = numberOfConnectedClients; connectionLock->unlock(); if(check == maxConnections) { mwarning(M_NETWORK_MESSAGE_DOMAIN, "Maximum number of clients connected"); return -1; } // the clients here are accept clients who wait for // connection clients to connect to them. tempClient = new ScarabServerConnection(incoming_event_buffer, outgoing_event_buffer, clientThreadInterval); shared_ptr<NetworkReturn> acceptRet; acceptRet = tempClient->accept(listeningSocket); mprintf("Accepting remote client"); if(!acceptRet->wasSuccessful()) { // the accept failed but it may have just timed out delete tempClient; tempClient = NULL; if(scarab_did_select_timeout(acceptRet->getPackageCode())) { // return from the service function and reschedule it boolLock->lock(); if(accepting) { boolLock->unlock(); return 1; //continue; } else { boolLock->unlock(); return 1; } } else { merror(M_NETWORK_MESSAGE_DOMAIN, "Server failed to accept client"); return -1; } } // the connection was established. mnetwork("Connection accepted from ..."); tempClient->start(); M_HASLOCK(connectionLock); clients[numberOfConnectedClients] = tempClient; numberOfConnectedClients++; M_HASUNLOCK(connectionLock); outgoing_event_buffer->putEvent(SystemEventFactory::serverConnectedClientResponse()); } // Some omissions by Paul: // Need to reschedule the accept thread (otherwise, this will be the last // client we accept). Also, we need to startListening again (which seems // like it probably ought to have been rolled into accepting, but that // is a another mess to clean up on another day... startListening(); scheduleAccept(); // we also should send a fresh codec so that this new client knows what is // up if it is joining the party late //buffer_manager->putEvent(SystemEventFactory::codecPackageEvent()); outgoing_event_buffer->putEvent(SystemEventFactory::componentCodecPackage()); outgoing_event_buffer->putEvent(SystemEventFactory::codecPackage()); // TODO: move this out into some sort of "announceSystemState" call? if(GlobalDataFileManager != NULL && GlobalDataFileManager->isFileOpen()){ std::string fname = GlobalDataFileManager->getFilename(); outgoing_event_buffer->putEvent(SystemEventFactory::dataFileOpenedResponse(fname, M_COMMAND_SUCCESS)); } outgoing_event_buffer->putEvent(SystemEventFactory::currentExperimentState()); outgoing_event_buffer->putEvent(SystemEventFactory::protocolPackage()); global_variable_registry->announceAll(); return 0; }