af::Msg* threadProcessMsgCase( ThreadArgs * i_args, af::Msg * i_msg) { //i_msg->stdOut(); //printf("IM=%d LM=%d MM=%d\n", i_msg->getMagicNumber(), af::Msg::Magic, af::Environment::getMagicMode()); af::Msg * o_msg_response = NULL; switch( i_msg->type()) { case af::Msg::TVersionMismatch: { AFCommon::QueueLogError( i_msg->v_generateInfoString( false)); o_msg_response = new af::Msg( af::Msg::TVersionMismatch, 1); break; } case af::Msg::TMagicMismatch: { std::string err = "Magick number mismatch: recieved "; err += af::itos( i_msg->getMagicNumber()) + " != " + af::itos( af::Msg::Magic) += " local."; AFCommon::QueueLogError( err); o_msg_response = new af::Msg( af::Msg::TMagicMismatch, 1); break; } case af::Msg::TMagicNumber: { std::string msg = "Magick Number " + af::itos( af::Msg::Magic) + " changed to " + af::itos( i_msg->int32()); AFCommon::QueueLog( msg); o_msg_response = new af::Msg(); o_msg_response->setString( msg); af::Msg::Magic = i_msg->int32(); break; } case af::Msg::TInvalid: { AFCommon::QueueLogError( std::string("Invalid message recieved: ") + i_msg->v_generateInfoString( false)); break; } case af::Msg::TNULL: case af::Msg::TDATA: case af::Msg::TTESTDATA: case af::Msg::TStringList: { i_msg->stdOutData(); break; } case af::Msg::THTTP: case af::Msg::TJSON: { return threadProcessJSON( i_args, i_msg); } case af::Msg::TString: { std::string str = i_msg->getString(); if( str.empty()) break; AFCommon::QueueLog( str); AfContainerLock mLock( i_args->monitors, AfContainerLock::WRITELOCK); i_args->monitors->sendMessage( str); break; } case af::Msg::TStatRequest: { o_msg_response = new af::Msg; af::statwrite( o_msg_response); break; } case af::Msg::TConfirm: { printf("Thread process message: Msg::TConfirm: %d\n", i_msg->int32()); i_args->msgQueue->pushMsg( new af::Msg( af::Msg::TConfirm, 1)); o_msg_response = new af::Msg( af::Msg::TConfirm, 1 - i_msg->int32()); break; } case af::Msg::TConfigLoad: { AfContainerLock jlock( i_args->jobs, AfContainerLock::WRITELOCK); AfContainerLock rlock( i_args->renders, AfContainerLock::WRITELOCK); AfContainerLock tlock( i_args->talks, AfContainerLock::WRITELOCK); AfContainerLock ulock( i_args->users, AfContainerLock::WRITELOCK); printf("\n ========= RELOADING CONFIG =========\n\n"); std::string message; if( af::Environment::reload()) { message = "Reloaded successfully."; printf("\n ========= CONFIG RELOADED SUCCESSFULLY =========\n\n"); } else { message = "Failed, see server logs fo details."; printf("\n ========= CONFIG RELOADING FAILED =========\n\n"); } o_msg_response = new af::Msg(); o_msg_response->setString( message); break; } case af::Msg::TFarmLoad: { AfContainerLock mLock( i_args->monitors, AfContainerLock::WRITELOCK); AfContainerLock rlock( i_args->renders, AfContainerLock::WRITELOCK); printf("\n ========= RELOADING FARM =========\n\n"); std::string message; if( af::loadFarm( true)) { RenderContainerIt rendersIt( i_args->renders); for( RenderAf *render = rendersIt.render(); render != NULL; rendersIt.next(), render = rendersIt.render()) { render->getFarmHost(); i_args->monitors->addEvent( af::Msg::TMonitorRendersChanged, render->getId()); } message = "Reloaded successfully."; printf("\n ========= FARM RELOADED SUCCESSFULLY =========\n\n"); } else { message = "Failed, see server logs fo details. Check farm with \"afcmd fcheck\" at first."; printf("\n ========= FARM RELOADING FAILED =========\n\n"); } o_msg_response = new af::Msg(); o_msg_response->setString( message); break; } // ---------------------------------- Monitor ---------------------------------// case af::Msg::TMonitorRegister: { AfContainerLock lock( i_args->monitors, AfContainerLock::WRITELOCK); MonitorAf * newMonitor = new MonitorAf( i_msg); newMonitor->setAddressIP( i_msg->getAddress()); o_msg_response = i_args->monitors->addMonitor( newMonitor); break; } case af::Msg::TMonitorUpdateId: { AfContainerLock lock( i_args->monitors, AfContainerLock::READLOCK); if( i_args->monitors->updateId( i_msg->int32())) { o_msg_response = new af::Msg( af::Msg::TMonitorId, i_msg->int32()); } else { o_msg_response = new af::Msg( af::Msg::TMonitorId, 0); } break; } case af::Msg::TMonitorsListRequest: { AfContainerLock lock( i_args->monitors, AfContainerLock::READLOCK); o_msg_response = i_args->monitors->generateList( af::Msg::TMonitorsList); break; } case af::Msg::TMonitorsListRequestIds: { AfContainerLock lock( i_args->monitors, AfContainerLock::READLOCK); af::MCGeneral ids( i_msg); o_msg_response = i_args->monitors->generateList( af::Msg::TMonitorsList, ids); break; } case af::Msg::TMonitorLogRequestId: { AfContainerLock lock( i_args->monitors, AfContainerLock::READLOCK); MonitorContainerIt it( i_args->monitors); MonitorAf* node = it.getMonitor( i_msg->int32()); if( node == NULL ) { // FIXME: Better to return some message in any case. break; } o_msg_response = new af::Msg(); o_msg_response->setStringList( node->getLog()); break; } // ---------------------------------- Talk ---------------------------------// case af::Msg::TTalkRegister: { AfContainerLock mlock( i_args->monitors, AfContainerLock::WRITELOCK); AfContainerLock tlock( i_args->talks, AfContainerLock::WRITELOCK); TalkAf * newTalk = new TalkAf( i_msg); newTalk->setAddressIP( i_msg->getAddress()); o_msg_response = i_args->talks->addTalk( newTalk, i_args->monitors); break; } case af::Msg::TTalksListRequest: { AfContainerLock lock( i_args->talks, AfContainerLock::READLOCK); o_msg_response = i_args->talks->generateList( af::Msg::TTalksList); break; } case af::Msg::TTalksListRequestIds: { AfContainerLock lock( i_args->talks, AfContainerLock::READLOCK); af::MCGeneral ids( i_msg); o_msg_response = i_args->talks->generateList( af::Msg::TTalksList, ids); break; } case af::Msg::TTalkUpdateId: { AfContainerLock lock( i_args->talks, AfContainerLock::READLOCK); if( i_args->talks->updateId( i_msg->int32())) { o_msg_response = i_args->talks->generateList( af::Msg::TTalksList); } else { o_msg_response = new af::Msg( af::Msg::TTalkId, 0); } break; } case af::Msg::TTalkDistributeData: { AfContainerLock lock( i_args->talks, AfContainerLock::READLOCK); i_args->talks->distributeData( i_msg); break; } // ---------------------------------- Render -------------------------------// case af::Msg::TRenderRegister: { //printf("case af::Msg::TRenderRegister:\n"); AfContainerLock mLock( i_args->monitors, AfContainerLock::WRITELOCK); AfContainerLock rLock( i_args->renders, AfContainerLock::WRITELOCK); RenderAf * newRender = new RenderAf( i_msg); newRender->setAddressIP( i_msg->getAddress()); o_msg_response = i_args->renders->addRender( newRender, i_args->monitors); break; } case af::Msg::TRenderUpdate: { //printf("case af::Msg::TRenderUpdate:\n"); AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK); af::Render render_up( i_msg); //printf("Msg::TRenderUpdate: %s - %s\n", render_up.getName().toUtf8().data(), time2Qstr( time(NULL)).toUtf8().data()); RenderContainerIt rendersIt( i_args->renders); RenderAf* render = rendersIt.getRender( render_up.getId()); int id = 0; // If there is not such render, a zero id will be send. // It is a signal for client to register again (may be server was restarted). if((render != NULL) && ( render->update( &render_up))) { id = render->getId(); } o_msg_response = new af::Msg( af::Msg::TRenderId, id); break; } case af::Msg::TRendersListRequest: { AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK); o_msg_response = i_args->renders->generateList( af::Msg::TRendersList); break; } case af::Msg::TRendersListRequestIds: { AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK); af::MCGeneral ids( i_msg); o_msg_response = i_args->renders->generateList( af::Msg::TRendersList, ids); break; } case af::Msg::TRendersResourcesRequestIds: { AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK); af::MCGeneral ids( i_msg); o_msg_response = i_args->renders->generateList( af::Msg::TRendersResources, ids); break; } case af::Msg::TRenderLogRequestId: { AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK); RenderContainerIt rendersIt( i_args->renders); RenderAf* render = rendersIt.getRender( i_msg->int32()); if( render == NULL ) { // FIXME: Better to return some message in any case. break; } o_msg_response = new af::Msg; o_msg_response->setStringList( render->getLog()); break; } case af::Msg::TRenderTasksLogRequestId: { AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK); RenderContainerIt rendersIt( i_args->renders); RenderAf* render = rendersIt.getRender( i_msg->int32()); if( render == NULL ) { // FIXME: Better to return some message in any case. break; } o_msg_response = new af::Msg; if( render->getTasksLog().empty()) { o_msg_response->setString("No tasks execution log."); } else { o_msg_response->setStringList( render->getTasksLog()); } break; } case af::Msg::TRenderInfoRequestId: { AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK); RenderContainerIt rendersIt( i_args->renders); RenderAf* render = rendersIt.getRender( i_msg->int32()); if( render == NULL ) { // FIXME: Better to return some message in any case. break; } o_msg_response = render->writeFullInfo(); break; } // ---------------------------------- Users -------------------------------// case af::Msg::TUserIdRequest: { AfContainerLock lock( i_args->users, AfContainerLock::READLOCK); af::MsgClassUserHost usr( i_msg); std::string name = usr.getUserName(); int id = 0; UserContainerIt usersIt( i_args->users); for( af::User *user = usersIt.user(); user != NULL; usersIt.next(), user = usersIt.user()) { if( user->getName() == name) { id = user->getId(); } } o_msg_response = new af::Msg( af::Msg::TUserId, id); break; } case af::Msg::TUsersListRequest: { AfContainerLock lock( i_args->users, AfContainerLock::READLOCK); o_msg_response = i_args->users->generateList( af::Msg::TUsersList); break; } case af::Msg::TUsersListRequestIds: { AfContainerLock lock( i_args->users, AfContainerLock::READLOCK); af::MCGeneral ids( i_msg); o_msg_response = i_args->users->generateList( af::Msg::TUsersList, ids); break; } case af::Msg::TUserLogRequestId: { AfContainerLock lock( i_args->users, AfContainerLock::READLOCK); UserContainerIt usersIt( i_args->users); UserAf* user = usersIt.getUser( i_msg->int32()); if( user == NULL ) { // FIXME: Better to return some message in any case. break; } o_msg_response = new af::Msg(); o_msg_response->setStringList( user->getLog()); break; } case af::Msg::TUserJobsOrderRequestId: { AfContainerLock lock( i_args->users, AfContainerLock::READLOCK); UserContainerIt usersIt( i_args->users); UserAf* user = usersIt.getUser( i_msg->int32()); if( user == NULL ) { // FIXME: Better to return some message in any case. break; } af::MCGeneral ids; ids.setId( user->getId()); ids.setList( user->generateJobsIds()); o_msg_response = new af::Msg( af::Msg::TUserJobsOrder, &ids); break; } // ------------------------------------- Job -------------------------------// case af::Msg::TJobRequestId: { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); JobContainerIt jobsIt( i_args->jobs); JobAf* job = jobsIt.getJob( i_msg->int32()); if( job == NULL ) { o_msg_response = new af::Msg( af::Msg::TJobRequestId, 0); break; } o_msg_response = new af::Msg( af::Msg::TJob, job); break; } case af::Msg::TJobLogRequestId: { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); JobContainerIt jobsIt( i_args->jobs); JobAf* job = jobsIt.getJob( i_msg->int32()); if( job == NULL ) { // FIXME: Better to return some message in any case. break; } o_msg_response = new af::Msg(); o_msg_response->setStringList( job->getLog()); break; } case af::Msg::TJobErrorHostsRequestId: { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); JobContainerIt jobsIt( i_args->jobs); JobAf* job = jobsIt.getJob( i_msg->int32()); if( job == NULL ) { // FIXME: Better to return some message in any case. break; } o_msg_response = new af::Msg(); o_msg_response->setString( job->v_getErrorHostsListString()); break; } case af::Msg::TJobProgressRequestId: { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); JobContainerIt jobsIt( i_args->jobs); JobAf* job = jobsIt.getJob( i_msg->int32()); if( job == NULL ) { // FIXME: Send back the same message on error - is it good? o_msg_response = new af::Msg( af::Msg::TJobProgressRequestId, 0); break; } o_msg_response = new af::Msg; job->writeProgress( *o_msg_response); break; } case af::Msg::TJobsListRequest: { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); o_msg_response = i_args->jobs->generateList( af::Msg::TJobsList); break; } case af::Msg::TJobsListRequestIds: { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); af::MCGeneral ids( i_msg); o_msg_response = i_args->jobs->generateList( af::Msg::TJobsList, ids); break; } case af::Msg::TJobsListRequestUserId: { AfContainerLock jLock( i_args->jobs, AfContainerLock::READLOCK); AfContainerLock uLock( i_args->users, AfContainerLock::READLOCK); o_msg_response = i_args->users->generateJobsList( i_msg->int32()); if( o_msg_response == NULL ) { o_msg_response = new af::Msg( af::Msg::TUserId, 0); } break; } case af::Msg::TJobsListRequestUsersIds: { AfContainerLock jLock( i_args->jobs, AfContainerLock::READLOCK); AfContainerLock uLock( i_args->users, AfContainerLock::READLOCK); af::MCGeneral mcids( i_msg); std::string type_name; o_msg_response = i_args->users->generateJobsList( mcids.getList(), type_name); break; } case af::Msg::TTaskRequest: { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); af::MCTaskPos mctaskpos( i_msg); JobContainerIt jobsIt( i_args->jobs); JobAf* job = jobsIt.getJob( mctaskpos.getJobId()); if( job == NULL ) { o_msg_response = new af::Msg(); std::ostringstream stream; stream << "Msg::TTaskRequest: No job with id=" << mctaskpos.getJobId(); o_msg_response->setString( stream.str()); break; } af::TaskExec * task = job->generateTask( mctaskpos.getNumBlock(), mctaskpos.getNumTask()); if( task ) { o_msg_response = new af::Msg( af::Msg::TTask, task); delete task; } else { o_msg_response = new af::Msg(); std::ostringstream stream; stream << "Msg::TTaskRequest: No such task[" << mctaskpos.getJobId() << "][" << mctaskpos.getNumBlock() << "][" << mctaskpos.getNumTask() << "]"; o_msg_response->setString( stream.str()); } break; } case af::Msg::TTaskLogRequest: { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); af::MCTaskPos mctaskpos( i_msg); JobContainerIt jobsIt( i_args->jobs); JobAf* job = jobsIt.getJob( mctaskpos.getJobId()); if( job == NULL ) { o_msg_response = new af::Msg(); std::ostringstream stream; stream << "Msg::TTaskLogRequest: No job with id=" << mctaskpos.getJobId(); o_msg_response->setString( stream.str()); break; } const std::list<std::string> * list = &(job->getTaskLog( mctaskpos.getNumBlock(), mctaskpos.getNumTask())); if( list == NULL ) { // FIXME: Better to return some message in any case. break; } o_msg_response = new af::Msg(); if( list->size() == 0) { std::list<std::string> list; list.push_back("Task log is empty."); o_msg_response->setStringList( list); } else { o_msg_response->setStringList( *list); } break; } case af::Msg::TTaskErrorHostsRequest: { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); af::MCTaskPos mctaskpos( i_msg); JobContainerIt jobsIt( i_args->jobs); JobAf* job = jobsIt.getJob( mctaskpos.getJobId()); if( job == NULL ) { // FIXME: Better to return some message in any case. break; } o_msg_response = new af::Msg(); o_msg_response->setString( job->v_getErrorHostsListString( mctaskpos.getNumBlock(), mctaskpos.getNumTask())); break; } case af::Msg::TTaskOutputRequest: { af::Msg * msg_request_render = NULL; std::string filename, error; af::MCTaskPos tp( i_msg); //printf("ThreadReadMsg::msgCase: case af::Msg::TJobTaskOutputRequest: job=%d, block=%d, task=%d, number=%d\n", tp.getJobId(), tp.getNumBlock(), tp.getNumTask(), tp.getNumber()); { AfContainerLock jLock( i_args->jobs, AfContainerLock::READLOCK); AfContainerLock rLock( i_args->renders, AfContainerLock::READLOCK); JobContainerIt jobsIt( i_args->jobs); JobAf* job = jobsIt.getJob( tp.getJobId()); if( job == NULL ) { o_msg_response = af::msgString("Error: Job is NULL."); AFCommon::QueueLogError("Jobs is NULL"); break; } // Trying to set message to request output from running remote host. msg_request_render = job->v_getTaskStdOut( tp.getNumBlock(), tp.getNumTask(), tp.getNumber(), i_args->renders, filename, error); if( error.size()) { if( msg_request_render ) delete msg_request_render; o_msg_response = af::msgString( error); AFCommon::QueueLogError( error); break; } } if( filename.size()) { // // Retrieving output from file // int readsize = -1; char * data = af::fileRead( filename, readsize, af::Msg::SizeDataMax, &error); if( data ) { o_msg_response = new af::Msg(); o_msg_response->setData( readsize, data); delete [] data; } else if( error.size()) { error = std::string("Getting task output: ") + error; AFCommon::QueueLogError( error); o_msg_response = af::msgString( error); } } else if( msg_request_render) { // // Retrieving output from render // msg_request_render->setReceiving(); bool ok; o_msg_response = af::msgsend( msg_request_render, ok, af::VerboseOn); if( o_msg_response == NULL ) { error = "Retrieving output from render failed. See server logs for details."; o_msg_response = af::msgString( error); AFCommon::QueueLogError( error); } delete msg_request_render; } else { if( error.size()) { o_msg_response = af::msgString( error); AFCommon::QueueLogError("TTaskOutputRequest: Neiter message nor filename\n" + error); } else AFCommon::QueueLogError("TTaskOutputRequest: Neiter message nor filename."); } break; } case af::Msg::TJobsWeightRequest: { AfContainerLock jLock( i_args->jobs, AfContainerLock::READLOCK); af::MCJobsWeight jobsWeight; i_args->jobs->getWeight( jobsWeight); o_msg_response = new af::Msg( af::Msg::TJobsWeight, &jobsWeight); break; } // Cases for run cycle thread: case af::Msg::TTaskUpdateState: { af::MCTaskUp taskup( i_msg); af::MCTaskPos taskpos( taskup.getNumJob(), taskup.getNumBlock(), taskup.getNumTask(), taskup.getNumber()); o_msg_response = new af::Msg( af::Msg::TRenderCloseTask, &taskpos); } case af::Msg::TTaskUpdatePercent: case af::Msg::TTaskListenOutput: case af::Msg::TRenderDeregister: case af::Msg::TTalkDeregister: /* { // Check magic number mismatch mode: // All message types above are not allowed in "GetOnly" mode. if( i_msg->isMagicInvalid() && ( af::Environment::getMagicMode() <= af::MMM_GetOnly )) { std::string err = "Magic Mismatch Mode: \""; err += af::Environment::getMagicModeName(); err += "\""; err += "\nMessage type not allowed: \""; err += af::Msg::TNAMES[i_msg->type()]; err += "\""; AFCommon::QueueLogError( err); delete i_msg; return o_msg_response; } // Only Monitor message types are allowed in "GetOnly" mode. }*/ case af::Msg::TMonitorSubscribe: case af::Msg::TMonitorUnsubscribe: case af::Msg::TMonitorDeregister: case af::Msg::TMonitorUsersJobs: case af::Msg::TMonitorJobsIdsAdd: case af::Msg::TMonitorJobsIdsSet: case af::Msg::TMonitorJobsIdsDel: case af::Msg::TMonitorMessage: { // Push message for run cycle thread. i_args->msgQueue->pushMsg( i_msg); // Need to return here to not to delete input message (i_msg) later. return o_msg_response; // ( o_msg_response is NULL in all cases except Msg::TTaskUpdateState, // in that case render should recieve an answer to close task // and finish sending any updates for the task ) } // -------------------------------------------------------------------------// default: { AFCommon::QueueLogError( std::string("Unknown message recieved: ") + i_msg->v_generateInfoString( false)); break; } } // Deleting input message as it not needed any more. delete i_msg; // Returning an answer return o_msg_response; }
bool JobContainer::registerJob( JobAf *job, std::string & o_err, UserContainer *users, MonitorContainer * monitoring) { if( job == NULL ) { AF_ERR << "JobContainer::registerJob: Can't allocate memory for a new job."; return false; } if( users == NULL ) { AF_ERR << "JobContainer::registerJob: Users container is not set."; delete job; return false; } // Job from store is already checked for validness if(( job->isFromStore() == false ) && (job->isValidConstructed() == false )) { o_err = "Invalid job."; delete job; return false; } UserAf *user; { // Register new user if job has a new user name. AfContainerLock jLock( this, AfContainerLock::WRITELOCK); AfContainerLock uLock( users, AfContainerLock::WRITELOCK ); if( monitoring) AfContainerLock mLock( monitoring, AfContainerLock::WRITELOCK ); AF_DEBUG << "JobContainer::registerJob: Checking job user: "******"JobContainer::registerJob: Can't register new user."; return false; } // Add job node to container. if( add( job) == false ) { delete job; o_err = "JobContainer::registerJob: Can't add job to container."; return false; } AF_DEBUG << "JobContainer::registerJob: locking job."; job->lock(); AF_DEBUG << "JobContainer::registerJob: locking user."; user->lock(); user->addJob( job); if( monitoring ) { AF_DEBUG << "JobContainer::registerJob: monitor new job events."; monitoring->addJobEvent( af::Monitor::EVT_jobs_add, job->getId(), user->getId()); monitoring->addEvent( af::Monitor::EVT_users_change, user->getId()); } } // initialize job ( create tasks output root_dir, execute "pre"commands if any) AF_DEBUG << "JobContainer::registerJob: initiaizing new job with user."; if( job->initialize() == false) { AF_DEBUG << "JobContainer::registerJob: Job initialization failed."; if( monitoring ) { AfContainerLock mLock( monitoring, AfContainerLock::WRITELOCK ); monitoring->addJobEvent( af::Monitor::EVT_jobs_del, job->getId(), user->getId()); monitoring->addEvent( af::Monitor::EVT_users_change, user->getId()); } { // Set job to zombie: AfContainerLock jLock( this, AfContainerLock::WRITELOCK); AfContainerLock uLock( users, AfContainerLock::WRITELOCK); user->unLock(); job->deleteNode( NULL, NULL); } return false; } if( monitoring ) { AfContainerLock mLock( monitoring, AfContainerLock::WRITELOCK ); AF_DEBUG << "JobContainer::registerJob: monitor unlock job and user events."; monitoring->addJobEvent( af::Monitor::EVT_jobs_change, job->getId(), user->getId()); monitoring->addEvent( af::Monitor::EVT_users_change, user->getId()); } AF_DEBUG << "JobContainer::registerJob: unlocking user and job."; { AfContainerLock jLock( this, AfContainerLock::WRITELOCK); AfContainerLock uLock( users, AfContainerLock::WRITELOCK); user->unLock(); job->unLock(); } AFCommon::QueueLog("Job registered: " + job->v_generateInfoString()); return true; }
af::Msg * threadProcessJSON( ThreadArgs * i_args, af::Msg * i_msg) { rapidjson::Document document; std::string error; char * data = af::jsonParseMsg( document, i_msg, &error); if( data == NULL ) { AFCommon::QueueLogError( error); delete i_msg; return NULL; } af::Msg * o_msg_response = NULL; JSON & getObj = document["get"]; if( getObj.IsObject()) { std::string type, mode; bool binary = false; af::jr_string("type", type, getObj); af::jr_string("mode", mode, getObj); af::jr_bool("binary", binary, getObj); bool json = true; if( binary ) json = false; bool full = false; if( mode == "full") full = true; std::vector<int32_t> ids; af::jr_int32vec("ids", ids, getObj); std::string mask; af::jr_string("mask", mask, getObj); if( type == "jobs" ) { if( getObj.HasMember("uids")) { std::vector<int32_t> uids; af::jr_int32vec("uids", uids, getObj); if( uids.size()) { AfContainerLock jLock( i_args->jobs, AfContainerLock::READLOCK); AfContainerLock uLock( i_args->users, AfContainerLock::READLOCK); o_msg_response = i_args->users->generateJobsList( uids, type, json); } } if( getObj.HasMember("users")) { std::vector<std::string> users; af::jr_stringvec("users", users, getObj); if( users.size()) { AfContainerLock jLock( i_args->jobs, AfContainerLock::READLOCK); AfContainerLock uLock( i_args->users, AfContainerLock::READLOCK); o_msg_response = i_args->users->generateJobsList( users, type, json); } } else if( mode == "output") { std::vector<int32_t> block_ids; std::vector<int32_t> task_ids; int number = 0; af::jr_int32vec("block_ids", block_ids, getObj); af::jr_int32vec("task_ids", task_ids, getObj); af::jr_int("number", number, getObj); if(( ids.size() == 1 ) && ( block_ids.size() == 1 ) && ( task_ids.size() == 1 )) { af::Msg * msg_request_render = NULL; std::string filename, error, name; // Get output from job, it can return a request message for render or a filename { AfContainerLock jlock( i_args->jobs, AfContainerLock::READLOCK); AfContainerLock rLock( i_args->renders, AfContainerLock::READLOCK); JobContainerIt it( i_args->jobs); JobAf * job = it.getJob( ids[0]); if( job == NULL ) o_msg_response = af::jsonMsgError("Invalid ID"); else { msg_request_render = job->v_getTaskStdOut( block_ids[0], task_ids[0], number, i_args->renders, filename, error); name = job->generateTaskName( block_ids[0], task_ids[0]); if( number > 0 ) name += "["+af::itos(number)+"]"; } } if( filename.size()) // Reading output from file { int readsize = -1; char * data = af::fileRead( filename, &readsize, af::Msg::SizeDataMax, &error); if( data ) { o_msg_response = af::jsonMsg( mode, name, data, readsize); delete [] data; } } else if( msg_request_render) // Retrieving output from render { msg_request_render->setReceiving(); bool ok; af::Msg * response = af::msgsend( msg_request_render, ok, af::VerboseOn); if( response ) { o_msg_response = af::jsonMsg( mode, name, response->data(), response->dataLen()); delete response; } else error = "Retrieving output from render failed. See server logs for details."; delete msg_request_render; } if( error.size()) { if( o_msg_response == NULL ) o_msg_response = af::jsonMsgError( error); AFCommon::QueueLogError("TTaskOutputRequest: " + error); } } } else { AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK); JobAf * job = NULL; bool was_error = false; if( ids.size() == 1 ) { JobContainerIt it( i_args->jobs); job = it.getJob( ids[0]); if( job == NULL ) o_msg_response = af::jsonMsgError( "Invalid ID"); } if( job ) { std::vector<int32_t> block_ids; af::jr_int32vec("block_ids", block_ids, getObj); if( block_ids.size() && ( block_ids[0] != -1 )) { std::vector<int32_t> task_ids; af::jr_int32vec("task_ids", task_ids, getObj); if( task_ids.size() && ( task_ids[0] != -1)) o_msg_response = job->writeTask( block_ids[0], task_ids[0], mode, binary); else { std::vector<std::string> modes; af::jr_stringvec("mode", modes, getObj); o_msg_response = job->writeBlocks( block_ids, modes); } } else if( mode.size()) { if( mode == "thumbnail" ) o_msg_response = job->writeThumbnail( binary); else if( mode == "progress" ) o_msg_response = job->writeProgress( json); else if( mode == "error_hosts" ) o_msg_response = job->writeErrorHosts(); else if( mode == "log" ) o_msg_response = job->writeLog(); } } if( o_msg_response == NULL ) o_msg_response = i_args->jobs->generateList( full ? af::Msg::TJob : af::Msg::TJobsList, type, ids, mask, json); } } else if( type == "renders") { AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK); if( mode.size()) { RenderAf * render = NULL; if( ids.size() == 1 ) { RenderContainerIt it( i_args->renders); render = it.getRender( ids[0]); if( render == NULL ) o_msg_response = af::jsonMsgError( "Invalid ID"); } if( render ) { if( full ) o_msg_response = render->jsonWriteSrvFarm(); else if( mode == "log" ) o_msg_response = render->writeLog(); else if( mode == "tasks_log" ) o_msg_response = af::jsonMsg("tasks_log", render->getName(), render->getTasksLog()); } } if( o_msg_response == NULL ) { if( mode == "resources" ) o_msg_response = i_args->renders->generateList( af::Msg::TRendersResources, type, ids, mask, json); else o_msg_response = i_args->renders->generateList( af::Msg::TRendersList, type, ids, mask, json); } } else if( type == "users") { AfContainerLock lock( i_args->users, AfContainerLock::READLOCK); if( mode.size()) { UserAf * user = NULL; if( ids.size() == 1 ) { UserContainerIt it( i_args->users); user = it.getUser( ids[0]); if( user == NULL ) o_msg_response = af::jsonMsgError( "Invalid ID"); } if( user ) { if( mode == "jobs_order" ) o_msg_response = user->writeJobdsOrder(); else if( mode == "log" ) o_msg_response = user->writeLog(); } } if( o_msg_response == NULL ) o_msg_response = i_args->users->generateList( af::Msg::TUsersList, type, ids, mask, json); } else if( type == "monitors") { AfContainerLock lock( i_args->monitors, AfContainerLock::READLOCK); if( mode == "events") { MonitorContainerIt it( i_args->monitors); if( ids.size() ) { MonitorAf* node = it.getMonitor( ids[0]); if( node != NULL ) { o_msg_response = node->getEvents(); } else { o_msg_response = af::jsonMsg("{\"monitor\":{\"id\":0}}"); } } else { o_msg_response = af::jsonMsgError("id is not specified"); } } else o_msg_response = i_args->monitors->generateList( af::Msg::TMonitorsList, type, ids, mask, json); } else if( type == "files") { std::string path; std::ostringstream files; af::jr_string("path", path, getObj); std::vector<std::string> list = af::getFilesListSafe( path); files << "{\"path\":\"" << path << "\",\n"; files << "\"files\":["; for( int i = 0; i < list.size(); i++) { if( i ) files << ','; files << '"' << list[i] << '"'; } files << "]}"; o_msg_response = af::jsonMsg( files); } else if( type == "config" ) { o_msg_response = af::jsonMsg( af::Environment::getConfigData()); } } else if( document.HasMember("action")) { i_args->msgQueue->pushMsg( i_msg); // To not to detele it, set to NULL, as it pushed to another queue i_msg = NULL; } else if( document.HasMember("job")) { if( af::Environment::isDemoMode() ) { AFCommon::QueueLogError("Job registration is not allowed: Server demo mode."); } else { // No containers locks needed here. // Job registration is a complex procedure. // It locks and unlocks needed containers itself. i_args->jobs->job_register( new JobAf( document["job"]), i_args->users, i_args->monitors); } } else if( document.HasMember("monitor")) { AfContainerLock mlock( i_args->monitors, AfContainerLock::WRITELOCK); AfContainerLock ulock( i_args->users, AfContainerLock::READLOCK); MonitorAf * newMonitor = new MonitorAf( document["monitor"], i_args->users); newMonitor->setAddressIP( i_msg->getAddress()); o_msg_response = i_args->monitors->addMonitor( newMonitor, /*JSON = */ true); } else if( document.HasMember("user")) { AfContainerLock ulock( i_args->users, AfContainerLock::WRITELOCK); o_msg_response = i_args->users->addUser( new UserAf( document["user"]), i_args->monitors); } else if( document.HasMember("reload_farm")) { AfContainerLock mLock( i_args->monitors, AfContainerLock::WRITELOCK); AfContainerLock rlock( i_args->renders, AfContainerLock::WRITELOCK); printf("\n ========= RELOADING FARM =========\n\n"); if( af::loadFarm( true)) { RenderContainerIt rendersIt( i_args->renders); for( RenderAf *render = rendersIt.render(); render != NULL; rendersIt.next(), render = rendersIt.render()) { render->getFarmHost(); i_args->monitors->addEvent( af::Msg::TMonitorRendersChanged, render->getId()); } printf("\n ========= FARM RELOADED SUCCESSFULLY =========\n\n"); o_msg_response = af::jsonMsgStatus( true, "reload_farm", "Reloaded successfully."); } else { printf("\n ========= FARM RELOADING FAILED =========\n\n"); o_msg_response = af::jsonMsgStatus( false, "reload_farm", "Failed, see server logs fo details. Check farm with \"afcmd fcheck\" at first."); } } else if( document.HasMember("reload_config")) { AfContainerLock jlock( i_args->jobs, AfContainerLock::WRITELOCK); AfContainerLock rlock( i_args->renders, AfContainerLock::WRITELOCK); AfContainerLock ulock( i_args->users, AfContainerLock::WRITELOCK); printf("\n ========= RELOADING CONFIG =========\n\n"); std::string message; if( af::Environment::reload()) { printf("\n ========= CONFIG RELOADED SUCCESSFULLY =========\n\n"); o_msg_response = af::jsonMsgStatus( true, "reload_config", "Reloaded successfully."); } else { printf("\n ========= CONFIG RELOADING FAILED =========\n\n"); o_msg_response = af::jsonMsgStatus( false, "reload_config", "Failed, see server logs fo details."); } } delete [] data; if( i_msg ) delete i_msg; return o_msg_response; }
/** This is a main run cycle thread entry point **/ void threadRunCycle( void * i_args) { AFINFO("ThreadRun::run:") ThreadArgs * a = (ThreadArgs*)i_args; while( AFRunning) { #ifdef _DEBUG printf("...................................\n"); #endif /**/ { // // Lock containers: // AFINFO("ThreadRun::run: Locking containers...") AfContainerLock jLock( a->jobs, AfContainerLock::WRITELOCK); AfContainerLock lLock( a->renders, AfContainerLock::WRITELOCK); AfContainerLock mlock( a->monitors, AfContainerLock::WRITELOCK); AfContainerLock tlock( a->talks, AfContainerLock::WRITELOCK); AfContainerLock ulock( a->users, AfContainerLock::WRITELOCK); // // Messages reaction: // AFINFO("ThreadRun::run: React on incoming messages:") /* Process all messages in our message queue. We do it without waiting so that the job solving below can run just after. NOTE: I think this should be a waiting operation in a different thread. The job solving below should be put asleep using a semaphore and woke up when something changes. We need to avoid the Sleep() function below. */ af::Msg *message; while( message = a->msgQueue->popMsg( af::AfQueue::e_no_wait) ) { threadRunCycleCase( a, message ); } // // Refresh data: // AFINFO("ThreadRun::run: Refreshing data:") a->talks ->refresh( NULL, a->monitors); a->monitors ->refresh( NULL, a->monitors); a->jobs ->refresh( a->renders, a->monitors); a->renders ->refresh( a->jobs, a->monitors); a->users ->refresh( NULL, a->monitors); // // Jobs sloving: // { AFINFO("ThreadRun::run: Solving jobs:") RenderContainerIt rendersIt( a->renders); std::list<int> rIds; { // ask every ready render to produce a task for( RenderAf *render = rendersIt.render(); render != NULL; rendersIt.next(), render = rendersIt.render()) { if( render->isReady()) { // store render Id if it produced a task if( a->users->solve( render, a->monitors)) { rIds.push_back( render->getId()); continue; } } // Render not solved, needed to update render status render->notSolved(); } } // cycle on renders, which produced a task static const int renders_cycle_limit = 100000; int renders_cycle = 0; while( rIds.size()) { renders_cycle++; if( renders_cycle > renders_cycle_limit ) { AFERROR("Renders solve cycles limit reached."); break; } AFINFA("ThreadRun::run: Renders on cycle: %d", int(rIds.size())) std::list<int>::iterator rIt = rIds.begin(); while( rIt != rIds.end()) { RenderAf * render = rendersIt.getRender( *rIt); if( render->isReady()) { if( a->users->solve( render, a->monitors)) { rIt++; continue; } } // delete render id from list if it can't produce a task rIt = rIds.erase( rIt); } } } // // Wake-On-Lan: // { AFINFO("ThreadRun::run: Wake-On-Lan:") RenderContainerIt rendersIt( a->renders); { for( RenderAf *render = rendersIt.render(); render != NULL; rendersIt.next(), render = rendersIt.render()) { if( render->isWOLWakeAble()) { if( a->users->solve( render, a->monitors)) { render->wolWake( a->monitors, std::string("Automatic waking by a job.")); continue; } } } } } // // Dispatch events to monitors: // AFINFO("ThreadRun::run: dispatching monitor events:") a->monitors->dispatch(); // // Free Containers: // AFINFO("ThreadRun::run: deleting zombies:") a->talks ->freeZombies(); a->monitors ->freeZombies(); a->renders ->freeZombies(); a->jobs ->freeZombies(); a->users ->freeZombies(); } // // Sleeping // AFINFO("ThreadRun::run: sleeping...") af::sleep_sec( 1); } }