void JobAf::v_action( Action & i_action) { // If action has blocks ids array - action to for blocks if( i_action.data->HasMember("block_ids") || i_action.data->HasMember("block_mask")) { std::vector<int32_t> block_ids; // Try to get block ids from array: const JSON & j_block_ids = (*i_action.data)["block_ids"]; if( j_block_ids.IsArray()) af::jr_int32vec("block_ids", block_ids, *i_action.data); // -1 id is specified = all blocks if(( block_ids.size() == 1 ) && ( block_ids[0] == -1 )) { block_ids.clear(); for( int b = 0; b < m_blocks_num; b++) block_ids.push_back( m_blocks[b]->m_data->getBlockNum()); } // Try to fill ids from mask: const JSON & j_block_mask = (*i_action.data)["block_mask"]; if( j_block_mask.IsString()) { std::string mask; af::jr_string("block_mask", mask, *i_action.data); af::RegExp re; std::string re_err; if( false == re.setPattern( mask, &re_err)) { appendLog("Invalid block mask = " + mask + " from " + i_action.author); return; } for( int b = 0; b < m_blocks_num; b++) if( re.match( m_blocks[b]->m_data->getName())) block_ids.push_back( m_blocks[b]->m_data->getBlockNum()); } if( block_ids.empty()) { appendLog("\"block_ids\" array does not contain any integers or invalid \"block_mask\" from " + i_action.author); return; } bool job_progress_changed = false; for( int b = 0; b < block_ids.size(); b++) { if(( block_ids[b] >= getBlocksNum()) || ( block_ids[b] < 0 )) { appendLog("Invalid block number = " + af::itos(block_ids[b]) + " " + i_action.author); continue; } if( m_blocks[block_ids[b]]->action( i_action)) job_progress_changed = true; } if( job_progress_changed ) i_action.monitors->addJobEvent( af::Monitor::EVT_jobs_change, getId(), getUid()); if( i_action.log.size() ) store(); return; } const JSON & operation = (*i_action.data)["operation"]; if( operation.IsObject()) { std::string type; af::jr_string("type", type, operation); if( type == "delete") { if( m_id == AFJOB::SYSJOB_ID ) { appendLog("System job can't be deleted by " + i_action.author); return; } appendLog("Deleted by " + i_action.author); m_user->appendLog( "Job \"" + m_name + "\" deleted by " + i_action.author); deleteNode( i_action.renders, i_action.monitors); i_action.monitors->addJobEvent( af::Monitor::EVT_jobs_del, getId(), getUid()); return; } else if( type == "start") { m_state = m_state & (~AFJOB::STATE_OFFLINE_MASK); } else if( type == "pause") { m_state = m_state | AFJOB::STATE_OFFLINE_MASK; } else if( type == "stop") { restartAllTasks("Job stopped by " + i_action.author, i_action.renders, i_action.monitors, AFJOB::STATE_RUNNING_MASK); m_state = m_state | AFJOB::STATE_OFFLINE_MASK; } else if( type == "restart_running") { restartAllTasks("Job restarted running by " + i_action.author, i_action.renders, i_action.monitors, AFJOB::STATE_RUNNING_MASK); } else if( type == "restart_skipped") { restartAllTasks("Job restarted skipped by " + i_action.author, i_action.renders, i_action.monitors, AFJOB::STATE_SKIPPED_MASK); } else if( type == "restart_done") { restartAllTasks("Job restarted done by " + i_action.author, i_action.renders, i_action.monitors, AFJOB::STATE_DONE_MASK); } else if( type == "reset_error_hosts") { for( int b = 0; b < m_blocks_num; b++) m_blocks[b]->action( i_action); } else if( type == "restart") { //printf("Msg::TJobRestart:\n"); restartAllTasks("Job restarted by " + i_action.author, i_action.renders, i_action.monitors); //printf("Msg::TJobRestart: tasks restarted.\n"); checkDepends(); m_time_started = 0; } else if( type == "restart_errors") { restartAllTasks("Job errors restarted by " + i_action.author, i_action.renders, i_action.monitors, AFJOB::STATE_ERROR_MASK); } else if( type == "restart_pause") { restartAllTasks("Job restarted ( and paused ) by " + i_action.author, i_action.renders, i_action.monitors); checkDepends(); m_state = m_state | AFJOB::STATE_OFFLINE_MASK; m_time_started = 0; } else { appendLog("Unknown operation \"" + type + "\" by " + i_action.author); return; } appendLog("Operation \"" + type + "\" by " + i_action.author); i_action.monitors->addJobEvent( af::Monitor::EVT_jobs_change, getId(), getUid()); store(); return; } // Store user name before parameters read, to check whether it changed const std::string user_name = m_user_name; const JSON & params = (*i_action.data)["params"]; if( params.IsObject()) jsonRead( params, &i_action.log); if( m_user_name != user_name ) { // User name was changed UserAf * user = i_action.users->getUser( m_user_name); if( user == NULL ) { return; } i_action.monitors->addEvent( af::Monitor::EVT_users_change, m_user->getId()); i_action.monitors->addJobEvent( af::Monitor::EVT_jobs_del, getId(), m_user->getId()); m_user->removeJob( this); user->addJob( this); i_action.monitors->addEvent( af::Monitor::EVT_users_change, m_user->getId()); i_action.monitors->addJobEvent( af::Monitor::EVT_jobs_add, getId(), m_user->getId()); store(); return; } if( i_action.log.size() ) { store(); i_action.monitors->addJobEvent( af::Monitor::EVT_jobs_change, getId(), getUid()); } }
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; }