af::Msg * JobContainer::registerJob( JSON & i_object, UserContainer * i_users, MonitorContainer * i_monitoring) { JobAf * job = new JobAf( i_object); int32_t id = 0; int64_t serial = 0; std::string err; if( registerJob( job, err, i_users, i_monitoring)) { id = job->getId(); serial = job->getSerial(); } else job = NULL; std::ostringstream oss; oss << "{"; oss << "\n\"id\":" << id; oss << ",\n\"serial\":" << serial; if( err.size()) { oss << ",\n\"error\":\"" << err << "\""; } else if( job == NULL ) { oss << ",\n\"error\":\"Job registration failed. See server log for details.\""; } oss << "\n}"; return af::jsonMsg( oss); }
void BranchSrv::v_postSolve(time_t i_curtime, MonitorContainer * i_monitoring) { // Generate a new active jobs list: m_active_jobs_list.clear(); AfListIt jIt(&m_jobs_list); for (AfNodeSrv * node = jIt.node(); node != NULL; jIt.next(), node = jIt.node()) { JobAf * job = (JobAf*)node; if(job->isDone()) continue; m_active_jobs_list.push_back(job); } // Clear active users (and delete users data) for (std::list<BranchUserData*>::iterator it = m_active_users_list.begin(); it != m_active_users_list.end(); it++) delete (*it); m_active_users_list.clear(); // Generate a new active users list: std::map<UserAf*, BranchSrvUserData*>::iterator uIt = m_users.begin(); for (; uIt != m_users.end(); uIt++) { if ((*uIt).second->running_tasks_num == 0) continue; m_active_users_list.push_back( new BranchUserData((*uIt).first, (*uIt).second->running_tasks_num, (*uIt).second->running_capacity_total)); } }
void JobContainer::reconnectTask( af::TaskExec * i_taskexec, RenderAf & i_render, MonitorContainer * i_monitoring) { #ifdef AFOUTPUT AF_DEBUG << "Reconnecting task " << i_taskexec << " with " << i_render; #endif JobContainerIt jobsIt( this); JobAf* job = jobsIt.getJob( i_taskexec->getJobId()); if( NULL == job ) { AF_ERR << "Job with id=" << i_taskexec->getJobId() << " does not exists."; delete i_taskexec; return; } return job->reconnectTask( i_taskexec, i_render, i_monitoring); }
const std::vector<int32_t> JobContainer::getIdsBySerials( const std::vector<int64_t> & i_serials) { std::vector<int32_t> ids; JobContainerIt jobsIt( this); for( JobAf *job = jobsIt.job(); job != NULL; jobsIt.next(), job = jobsIt.job()) { for( int i = 0; i < i_serials.size(); i++) { if( i_serials[i] == job->getSerial()) { ids.push_back( job->getId()); break; } } } if( ids.size() == 0 ) ids.push_back(-1); return ids; }
void RenderAf::ejectTasks( JobContainer * jobs, MonitorContainer * monitoring, uint32_t upstatus, const std::string * i_keeptasks_username ) { if( m_tasks.size() < 1) return; std::list<int>id_jobs; std::list<int>id_blocks; std::list<int>id_tasks; std::list<int>numbers; for( std::list<af::TaskExec*>::const_iterator it = m_tasks.begin(); it != m_tasks.end(); it++) { // Skip if username to keep tasks provided: if( i_keeptasks_username != NULL ) if( *i_keeptasks_username == (*it)->getUserName()) continue; id_jobs.push_back( (*it)->getJobId()); id_blocks.push_back( (*it)->getBlockNum()); id_tasks.push_back( (*it)->getTaskNum()); numbers.push_back( (*it)->getNumber()); appendLog( std::string("Ejecting task: ") + (*it)->v_generateInfoString( false)); } JobContainerIt jobsIt( jobs); std::list<int>::const_iterator jIt = id_jobs.begin(); std::list<int>::const_iterator bIt = id_blocks.begin(); std::list<int>::const_iterator tIt = id_tasks.begin(); std::list<int>::const_iterator nIt = numbers.begin(); std::list<int>::const_iterator end = numbers.end(); for( ; nIt != end; jIt++, bIt++, tIt++, nIt++) { JobAf* job = jobsIt.getJob( *jIt); if( job != NULL ) { af::MCTaskUp taskup( m_id, *jIt, *bIt, *tIt, *nIt, upstatus); job->v_updateTaskState( taskup, ms_renders, monitoring); } } }
void JobContainer::updateTaskState( af::MCTaskUp &taskup, RenderContainer * renders, MonitorContainer * monitoring) { switch( taskup.getStatus()) { case af::TaskExec::UPNULL: case af::TaskExec::UPNoTaskRunning: case af::TaskExec::UPNoJob: case af::TaskExec::UPLAST: AFERRAR("JobContainer::updateTaskState: Bad task update status (jobID=%d).\n", taskup.getNumJob()); return; } JobContainerIt jobsIt( this); JobAf* job = jobsIt.getJob( taskup.getNumJob()); if( job != NULL ) { job->v_updateTaskState( taskup, renders, monitoring); return; } // Job does not exist! AFERRAR("JobContainer::updateTaskState: Job with id=%d does not exists.", taskup.getNumJob()) if( taskup.getStatus() == af::TaskExec::UPPercent) RenderAf::closeLostTask( taskup); }
void JobContainer::getWeight( af::MCJobsWeight & jobsWeight ) { JobContainerIt jobsIt( this); for( JobAf *job = jobsIt.job(); job != NULL; jobsIt.next(), job = jobsIt.job()) { int weight = job->v_calcWeight(); jobsWeight.add( job->getName(), job->getId(), job->getLogsWeight(), job->getBlackListsWeight(), job->getProgressWeight(), weight ); } }
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; }
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; }
//######################################## main ######################################### int main(int argc, char *argv[]) { // Initialize environment: af::Environment ENV( af::Environment::Server, argc, argv); ENV.addUsage("-demo", "Disable tasks changing and new jobs."); // Initialize general library: if( af::init( af::InitFarm) == false) return 1; // Initialize store: afsql::init(); // Environment aready printed usage and we can exit. if( ENV.isHelpMode()) return 0; // create directories if it is not exists if( af::pathMakePath( ENV.getTempDir(), af::VerboseOn ) == false) return 1; if( af::pathMakeDir( ENV.getJobsDir(), af::VerboseOn ) == false) return 1; if( af::pathMakeDir( ENV.getUsersDir(), af::VerboseOn ) == false) return 1; if( af::pathMakeDir( ENV.getRendersDir(), af::VerboseOn ) == false) return 1; // Server for windows can be me more simple and not use signals at all. // Windows is not a server platform, so it designed for individual tests or very small companies with easy load. #ifndef _WIN32 // Interrupt signals catch. // We need to catch interrupt signals to let threads to finish running function themselves. // This needed mostly fot queues to let them to finish to process last item. struct sigaction actint; bzero( &actint, sizeof(actint)); actint.sa_handler = sig_int; sigaction( SIGINT, &actint, NULL); sigaction( SIGTERM, &actint, NULL); // SIGPIPE signal catch. // This is not an error for our application. struct sigaction actpipe; bzero( &actpipe, sizeof(actpipe)); actpipe.sa_handler = sig_pipe; sigaction( SIGPIPE, &actpipe, NULL); // SIGALRM signal catch and block. // Special threads use alarm signal to unblock connect function. // Other threads should ignore this signal. struct sigaction actalrm; bzero( &actalrm, sizeof(actalrm)); actalrm.sa_handler = sig_alrm; sigaction( SIGALRM, &actalrm, NULL); sigset_t sigmask; sigemptyset( &sigmask); sigaddset( &sigmask, SIGALRM); if( sigprocmask( SIG_BLOCK, &sigmask, NULL) != 0) perror("sigprocmask:"); if( pthread_sigmask( SIG_BLOCK, &sigmask, NULL) != 0) perror("pthread_sigmask:"); #endif // containers initialization JobContainer jobs; if( false == jobs.isInitialized()) return 1; UserContainer users; if( false == users.isInitialized()) return 1; RenderContainer renders; if( false == renders.isInitialized()) return 1; MonitorContainer monitors; if( false == monitors.isInitialized()) return 1; // Message Queue initialization, but without thread start. // Run cycle queue will read this messages itself. af::MsgQueue msgQueue("RunMsgQueue"); if( false == msgQueue.isInitialized()) return 1; // Thread aruguments. ThreadArgs threadArgs; threadArgs.jobs = &jobs; threadArgs.renders = &renders; threadArgs.users = &users; threadArgs.monitors = &monitors; threadArgs.msgQueue = &msgQueue; /* Creating the afcommon object will actually create many message queues that will spawn threads. Have a look in the implementation of AfCommon. */ AFCommon afcommon( &threadArgs ); // Update SQL tables: afsql::DBConnection afdb_upTables("AFDB_upTables"); afdb_upTables.DBOpen(); if( afdb_upTables.isOpen()) { afsql::UpdateTables( &afdb_upTables); afdb_upTables.DBClose(); } // // Get Renders from store: // { printf("Getting renders from store...\n"); std::vector<std::string> folders = AFCommon::getStoredFolders( ENV.getRendersDir()); printf("%d renders found.\n", (int)folders.size()); for( int i = 0; i < folders.size(); i++) { RenderAf * render = new RenderAf( folders[i]); if( render->isStoredOk() != true ) { af::removeDir( render->getStoreDir()); delete render; continue; } renders.addRender( render); } printf("%d renders registered.\n", renders.getCount()); } // // Get Users from store: // { printf("Getting users from store...\n"); std::vector<std::string> folders = AFCommon::getStoredFolders( ENV.getUsersDir()); printf("%d users found.\n", (int)folders.size()); for( int i = 0; i < folders.size(); i++) { UserAf * user = new UserAf( folders[i]); if( user->isStoredOk() != true ) { af::removeDir( user->getStoreDir()); delete user; continue; } if( users.addUser( user) == 0 ) delete user; } printf("%d users registered from store.\n", users.getCount()); } // // Get Jobs from store: // bool hasSystemJob = false; { printf("Getting jobs from store...\n"); std::vector<std::string> folders = AFCommon::getStoredFolders( ENV.getJobsDir()); std::string sysjob_folder = AFCommon::getStoreDir( ENV.getJobsDir(), AFJOB::SYSJOB_ID, AFJOB::SYSJOB_NAME); printf("%d jobs found.\n", (int)folders.size()); for( int i = 0; i < folders.size(); i++) { JobAf * job = NULL; if( folders[i] == sysjob_folder) job = new SysJob( folders[i]); else job = new JobAf( folders[i]); if( job->isValidConstructed()) { if( job->getId() == AFJOB::SYSJOB_ID ) { SysJob * sysjob = (SysJob*)job; if( sysjob->initSystem() ) { hasSystemJob = true; } else { printf("System job retrieved from store is obsolete. Deleting it...\n"); delete job; continue; } } jobs.job_register( job, &users, NULL); } else { af::removeDir( job->getStoreDir()); delete job; } } printf("%d jobs registered from store.\n", jobs.getCount()); } // Disable new commands and editing: if( af::Environment::hasArgument("-demo")) { printf("Demo mode, no new commands.\n"); af::Environment::setDemoMode(); } // // Create system maintenance job if it was not in store: if( hasSystemJob == false ) { SysJob* job = new SysJob(); jobs.job_register( job, &users, NULL); } /* Start the thread that is responsible of listening to the port for incoming connections. */ DlThread ServerAccept; ServerAccept.Start( &threadAcceptClient, &threadArgs); // Run cycle thread. // All 'brains' are there. DlThread RunCycleThread; RunCycleThread.Start( &threadRunCycle, &threadArgs); /* Do nothing since everything is done in our threads. */ while( AFRunning ) { DlThread::Self()->Sleep( 1 ); } AFINFO("afanasy::main: Waiting child threads.") //alarm(1); /*FIXME: Why we don`t need to join accent thread? */ //ServerAccept.Cancel(); //ServerAccept.Join(); AFINFO("afanasy::main: Waiting Run.") // No need to chanel run cycle thread as // every new cycle it checks running external valiable RunCycleThread.Join(); af::destroy(); return 0; }