Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
/** 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);
}
}