QuillErrCode FILESQL::file_updateEvent(const char *eventType, AttrList *info, AttrList *condition) { int retval = 0; struct stat file_status; if (is_dummy) return QUILL_SUCCESS; if(!is_open) { dprintf(D_ALWAYS,"Error in logging event to Quill SQL Log : File not open\n"); return QUILL_FAILURE; } if(file_lock() == QUILL_FAILURE) { return QUILL_FAILURE; } fstat(outfiledes, &file_status); // only write to the log if it's not exceeding the log size limit if (file_status.st_size < FILESIZELIMT) { retval = write(outfiledes,"UPDATE ", strlen("UPDATE ")); retval = write(outfiledes,eventType, strlen(eventType)); retval = write(outfiledes,"\n", strlen("\n")); MyString temp, temp1; const char *tempv; retval = sPrintAd(temp, *info); tempv = temp.Value(); retval = write(outfiledes,tempv, strlen(tempv)); retval = write(outfiledes,"***",3); /* Now the delimitor*/ retval = write(outfiledes,"\n",1); /* Now the newline*/ retval = sPrintAd(temp1, *condition); tempv = temp1.Value(); retval = write(outfiledes,tempv, strlen(tempv)); retval = write(outfiledes,"***",3); /* Now the delimitor*/ retval = write(outfiledes,"\n",1); /* Now the newline*/ } if(file_unlock() == QUILL_FAILURE) { return QUILL_FAILURE; } if (retval < 0) { return QUILL_FAILURE; } else { return QUILL_SUCCESS; } }
//function:getQpidPort- reads port # from the classAd char* getQpidPort(char *hName){ config(); char* port; MyString daemonHost = "pigeon@"; daemonHost += hName; DaemonAllowLocateFull dObj(DT_GENERIC, daemonHost.Value(), NULL); dObj.setSubsystem("PIGEON"); bool flag = dObj.locate(Daemon::LOCATE_FULL); if(!flag){ fprintf(stderr, "Problem locating daemon object: %s \n", dObj.error()); return NULL; } ClassAd *qpidAd = dObj.daemonAd(); if(qpidAd){ MyString inBuf=""; sPrintAd(inBuf, *qpidAd); char* start =strstr(inBuf.Value(),"PORT ="); char* end =strstr(start,"\n"); int len = end - start -9; port = (char*)malloc(sizeof(len+1)); char *ports = strncpy(port,start+8,len); port[len]='\0'; ports = NULL; } else { fprintf(stderr, "Problem retrieving pigeon Ad \n"); } return (port); }
bool CCBListener::HandleCCBRequest( ClassAd &msg ) { MyString address; MyString connect_id; MyString request_id; MyString name; if( !msg.LookupString( ATTR_MY_ADDRESS, address) || !msg.LookupString( ATTR_CLAIM_ID, connect_id) || !msg.LookupString( ATTR_REQUEST_ID, request_id) ) { MyString msg_str; sPrintAd(msg_str, msg); EXCEPT("CCBListener: invalid CCB request from %s: %s\n", m_ccb_address.Value(), msg_str.Value() ); } msg.LookupString( ATTR_NAME, name ); if( name.find(address.Value())<0 ) { name.formatstr_cat(" with reverse connect address %s",address.Value()); } dprintf(D_FULLDEBUG|D_NETWORK, "CCBListener: received request to connect to %s, request id %s.\n", name.Value(), request_id.Value()); return DoReversedCCBConnect( address.Value(), connect_id.Value(), request_id.Value(), name.Value() ); }
int TransferQueueManager::HandleRequest(int cmd,Stream *stream) { ReliSock *sock = (ReliSock *)stream; ASSERT( cmd == TRANSFER_QUEUE_REQUEST ); ClassAd msg; sock->decode(); if( !getClassAd( sock, msg ) || !sock->end_of_message() ) { dprintf(D_ALWAYS, "TransferQueueManager: failed to receive transfer request " "from %s.\n", sock->peer_description() ); return FALSE; } bool downloading = false; MyString fname; MyString jobid; MyString queue_user; filesize_t sandbox_size; if( !msg.LookupBool(ATTR_DOWNLOADING,downloading) || !msg.LookupString(ATTR_FILE_NAME,fname) || !msg.LookupString(ATTR_JOB_ID,jobid) || !msg.LookupString(ATTR_USER,queue_user) || !msg.LookupInteger(ATTR_SANDBOX_SIZE,sandbox_size)) { MyString msg_str; sPrintAd(msg_str, msg); dprintf(D_ALWAYS,"TransferQueueManager: invalid request from %s: %s\n", sock->peer_description(), msg_str.Value()); return FALSE; } // Currently, we just create the client with the default max queue // age. If it becomes necessary to customize the maximum age // on a case-by-case basis, it should be easy to adjust. TransferQueueRequest *client = new TransferQueueRequest( sock, sandbox_size, fname.Value(), jobid.Value(), queue_user.Value(), downloading, m_default_max_queue_age); if( !AddRequest( client ) ) { delete client; return KEEP_STREAM; // we have already closed this socket } return KEEP_STREAM; }
bool BaseResource::SendUpdate () { ClassAd ad; /* Set the correct types */ SetMyTypeName ( ad, GRID_ADTYPE ); /* populate class ad with the relevant resource information */ PublishResourceAd ( &ad ); daemonCore->publish( &ad ); std::string tmp; sPrintAd ( tmp, ad ); dprintf ( D_FULLDEBUG, "BaseResource::UpdateResource: \n%s\n", tmp.c_str() ); return daemonCore->sendUpdates( UPDATE_GRID_AD, &ad, NULL, true ) > 0; }
bool CCBListener::ReadMsgFromCCB() { if( !m_sock ) { return false; } m_sock->timeout(CCB_TIMEOUT); ClassAd msg; if( !getClassAd( m_sock, msg ) || !m_sock->end_of_message() ) { dprintf(D_ALWAYS, "CCBListener: failed to receive message from CCB server %s\n", m_ccb_address.Value()); Disconnected(); return false; } m_last_contact_from_peer = time(NULL); RescheduleHeartbeat(); int cmd = -1; msg.LookupInteger( ATTR_COMMAND, cmd ); switch( cmd ) { case CCB_REGISTER: return HandleCCBRegistrationReply( msg ); case CCB_REQUEST: return HandleCCBRequest( msg ); case ALIVE: dprintf(D_FULLDEBUG,"CCBListener: received heartbeat from server.\n"); return true; } MyString msg_str; sPrintAd(msg_str, msg); dprintf( D_ALWAYS, "CCBListener: Unexpected message received from CCB " "server: %s\n", msg_str.Value() ); return false; }
bool CCBListener::HandleCCBRegistrationReply( ClassAd &msg ) { if( !msg.LookupString(ATTR_CCBID,m_ccbid) ) { MyString msg_str; sPrintAd(msg_str, msg); EXCEPT("CCBListener: no ccbid in registration reply: %s", msg_str.Value() ); } msg.LookupString(ATTR_CLAIM_ID,m_reconnect_cookie); dprintf(D_ALWAYS, "CCBListener: registered with CCB server %s as ccbid %s", m_ccb_address.Value(), m_ccbid.Value() ); m_waiting_for_registration = false; m_registered = true; daemonCore->daemonContactInfoChanged(); return true; }
bool DCSchedd::getJobConnectInfo( PROC_ID jobid, int subproc, char const *session_info, int timeout, CondorError *errstack, MyString &starter_addr, MyString &starter_claim_id, MyString &starter_version, MyString &slot_name, MyString &error_msg, bool &retry_is_sensible, int &job_status, MyString &hold_reason) { ClassAd input; ClassAd output; input.Assign(ATTR_CLUSTER_ID,jobid.cluster); input.Assign(ATTR_PROC_ID,jobid.proc); if( subproc != -1 ) { input.Assign(ATTR_SUB_PROC_ID,subproc); } input.Assign(ATTR_SESSION_INFO,session_info); ReliSock sock; if( !connectSock(&sock,timeout,errstack) ) { error_msg = "Failed to connect to schedd"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } if( !startCommand(GET_JOB_CONNECT_INFO, &sock, timeout, errstack) ) { error_msg = "Failed to send GET_JOB_CONNECT_INFO to schedd"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } if( !forceAuthentication(&sock, errstack) ) { error_msg = "Failed to authenticate"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } sock.encode(); if( !putClassAd(&sock, input) || !sock.end_of_message() ) { error_msg = "Failed to send GET_JOB_CONNECT_INFO to schedd"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } sock.decode(); if( !getClassAd(&sock, output) || !sock.end_of_message() ) { error_msg = "Failed to get response from schedd"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } if( IsFulldebug(D_FULLDEBUG) ) { std::string adstr; sPrintAd(adstr, output, true); dprintf(D_FULLDEBUG,"Response for GET_JOB_CONNECT_INFO:\n%s\n", adstr.c_str()); } bool result=false; output.LookupBool(ATTR_RESULT,result); if( !result ) { output.LookupString(ATTR_HOLD_REASON,hold_reason); output.LookupString(ATTR_ERROR_STRING,error_msg); retry_is_sensible = false; output.LookupBool(ATTR_RETRY,retry_is_sensible); output.LookupInteger(ATTR_JOB_STATUS,job_status); } else { output.LookupString(ATTR_STARTER_IP_ADDR,starter_addr); output.LookupString(ATTR_CLAIM_ID,starter_claim_id); output.LookupString(ATTR_VERSION,starter_version); output.LookupString(ATTR_REMOTE_HOST,slot_name); } return result; }
void CCBServer::HandleRequestResultsMsg( CCBTarget *target ) { // Reply from target daemon about whether it succeeded in // connecting to the requested client. Sock *sock = target->getSock(); ClassAd msg; sock->decode(); if( !getClassAd( sock, msg ) || !sock->end_of_message() ) { // disconnect dprintf(D_FULLDEBUG, "CCB: received disconnect from target daemon %s " "with ccbid %lu.\n", sock->peer_description(), target->getCCBID() ); RemoveTarget( target ); return; } int command = 0; if( msg.LookupInteger( ATTR_COMMAND, command ) && command == ALIVE ) { SendHeartbeatResponse( target ); return; } target->decPendingRequestResults(); bool success = false; MyString error_msg; MyString reqid_str; CCBID reqid; MyString connect_id; msg.LookupBool( ATTR_RESULT, success ); msg.LookupString( ATTR_ERROR_STRING, error_msg ); msg.LookupString( ATTR_REQUEST_ID, reqid_str ); msg.LookupString( ATTR_CLAIM_ID, connect_id ); if( !CCBIDFromString( reqid, reqid_str.Value() ) ) { MyString msg_str; sPrintAd(msg_str, msg); dprintf(D_ALWAYS, "CCB: received reply from target daemon %s with ccbid %lu " "without a valid request id: %s\n", sock->peer_description(), target->getCCBID(), msg_str.Value()); RemoveTarget( target ); return; } CCBServerRequest *request = GetRequest( reqid ); if( request && request->getSock()->readReady() ) { // Request socket must have just closed. To avoid noise in // logs when we fail to write to it, delete the request now. RemoveRequest( request ); request = NULL; } char const *request_desc = "(client which has gone away)"; if( request ) { request_desc = request->getSock()->peer_description(); } if( success ) { dprintf(D_FULLDEBUG,"CCB: received 'success' from target daemon %s " "with ccbid %lu for " "request %s from %s.\n", sock->peer_description(), target->getCCBID(), reqid_str.Value(), request_desc); } else { dprintf(D_FULLDEBUG,"CCB: received error from target daemon %s " "with ccbid %lu for " "request %s from %s: %s\n", sock->peer_description(), target->getCCBID(), reqid_str.Value(), request_desc, error_msg.Value()); } if( !request ) { if( success ) { // expected: the client has gone away; it got what it wanted return; } dprintf( D_FULLDEBUG, "CCB: client for request %s to target daemon %s with ccbid " "%lu disappeared before receiving error details.\n", reqid_str.Value(), sock->peer_description(), target->getCCBID()); return; } if( connect_id != request->getConnectID() ) { MyString msg_str; sPrintAd(msg_str, msg); dprintf( D_FULLDEBUG, "CCB: received wrong connect id (%s) from target daemon %s " "with ccbid %lu for " "request %s\n", connect_id.Value(), sock->peer_description(), target->getCCBID(), reqid_str.Value()); RemoveTarget( target ); return; } RequestFinished( request, success, error_msg.Value() ); }
int CCBServer::HandleRequest(int cmd,Stream *stream) { ReliSock *sock = (ReliSock *)stream; ASSERT( cmd == CCB_REQUEST ); // Avoid lengthy blocking on communication with our peer. // This command-handler should not get called until data // is ready to read. sock->timeout(1); ClassAd msg; sock->decode(); if( !getClassAd( sock, msg ) || !sock->end_of_message() ) { dprintf(D_ALWAYS, "CCB: failed to receive request " "from %s.\n", sock->peer_description() ); return FALSE; } MyString name; if( msg.LookupString(ATTR_NAME,name) ) { // client name is purely for debugging purposes name.formatstr_cat(" on %s",sock->peer_description()); sock->set_peer_description(name.Value()); } MyString target_ccbid_str; MyString return_addr; MyString connect_id; // id target daemon should present to requester CCBID target_ccbid; // NOTE: using ATTR_CLAIM_ID for connect id so that it is // automatically treated as a secret over the network. // It must be presented by the target daemon when connecting // to the requesting client, so the client can confirm that // the connection is in response to its request. if( !msg.LookupString(ATTR_CCBID,target_ccbid_str) || !msg.LookupString(ATTR_MY_ADDRESS,return_addr) || !msg.LookupString(ATTR_CLAIM_ID,connect_id) ) { MyString ad_str; sPrintAd(ad_str, msg); dprintf(D_ALWAYS, "CCB: invalid request from %s: %s\n", sock->peer_description(), ad_str.Value() ); return FALSE; } if( !CCBIDFromString(target_ccbid,target_ccbid_str.Value()) ) { dprintf(D_ALWAYS, "CCB: request from %s contains invalid CCBID %s\n", sock->peer_description(), target_ccbid_str.Value() ); return FALSE; } CCBTarget *target = GetTarget( target_ccbid ); if( !target ) { dprintf(D_ALWAYS, "CCB: rejecting request from %s for ccbid %s because no daemon is " "currently registered with that id " "(perhaps it recently disconnected).\n", sock->peer_description(), target_ccbid_str.Value()); MyString error_msg; error_msg.formatstr( "CCB server rejecting request for ccbid %s because no daemon is " "currently registered with that id " "(perhaps it recently disconnected).", target_ccbid_str.Value()); RequestReply( sock, false, error_msg.Value(), 0, target_ccbid ); return FALSE; } SetSmallBuffers(sock); CCBServerRequest *request = new CCBServerRequest( sock, target_ccbid, return_addr.Value(), connect_id.Value() ); AddRequest( request, target ); dprintf(D_FULLDEBUG, "CCB: received request id %lu from %s for target ccbid %s " "(registered as %s)\n", request->getRequestID(), request->getSock()->peer_description(), target_ccbid_str.Value(), target->getSock()->peer_description()); ForwardRequestToTarget( request, target ); return KEEP_STREAM; }
int main( int argc, char **argv ) { CURL* handle = NULL; ClassAd stats_ad; FileTransferStats stats; int retry_count = 0; int rval = -1; int diagnostic = 0; MyString stats_string; // Point the global curl_stats pointer to our local object ft_stats = &stats; if(argc == 2 && strcmp(argv[1], "-classad") == 0) { printf("%s", "PluginVersion = \"0.1\"\n" "PluginType = \"FileTransfer\"\n" "SupportedMethods = \"http,https,ftp,file\"\n" ); return 0; } if ((argc > 3) && ! strcmp(argv[3],"-diagnostic")) { diagnostic = 1; } else if(argc != 3) { return -1; } // Initialize win32 + SSL socket libraries. // Do not initialize these separately! Doing so causes https:// transfers // to segfault. int init = curl_global_init( CURL_GLOBAL_DEFAULT ); if( init != 0 ) { fprintf( stderr, "Error: curl_plugin initialization failed with error" " code %d\n", init ); return -1; } if ( ( handle = curl_easy_init() ) == NULL ) { return -1; } // Initialize the stats structure init_stats( argv ); stats.TransferStartTime = condor_gettimestamp_double(); // Enter the loop that will attempt/retry the curl request for(;;) { // The sleep function is defined differently in Windows and Linux #ifdef WIN32 Sleep( ( retry_count++ ) * 1000 ); #else sleep( retry_count++ ); #endif rval = send_curl_request( argv, diagnostic, handle, ft_stats ); // If curl request is successful, break out of the loop if( rval == CURLE_OK ) { break; } // If we have not exceeded the maximum number of retries, and we encounter // a non-fatal error, stay in the loop and try again else if( retry_count <= MAX_RETRY_ATTEMPTS && ( rval == CURLE_COULDNT_CONNECT || rval == CURLE_PARTIAL_FILE || rval == CURLE_READ_ERROR || rval == CURLE_OPERATION_TIMEDOUT || rval == CURLE_SEND_ERROR || rval == CURLE_RECV_ERROR ) ) { continue; } // On fatal errors, break out of the loop else { break; } } stats.TransferEndTime = condor_gettimestamp_double(); // If the transfer was successful, output the statistics to stdout if( rval != -1 ) { stats.Publish( stats_ad ); sPrintAd( stats_string, stats_ad ); fprintf( stdout, "%s", stats_string.c_str() ); } // Cleanup curl_easy_cleanup(handle); curl_global_cleanup(); return rval; // 0 on success }
int pseudo_ulog( ClassAd *ad ) { ULogEvent *event = instantiateEvent(ad); int result = 0; char const *critical_error = NULL; MyString CriticalErrorBuf; bool event_already_logged = false; bool put_job_on_hold = false; char const *hold_reason = NULL; char *hold_reason_buf = NULL; int hold_reason_code = 0; int hold_reason_sub_code = 0; if(!event) { MyString add_str; sPrintAd(add_str, *ad); dprintf( D_ALWAYS, "invalid event ClassAd in pseudo_ulog: %s\n", add_str.Value()); return -1; } if(ad->LookupInteger(ATTR_HOLD_REASON_CODE,hold_reason_code)) { put_job_on_hold = true; ad->LookupInteger(ATTR_HOLD_REASON_SUBCODE,hold_reason_sub_code); ad->LookupString(ATTR_HOLD_REASON,&hold_reason_buf); if(hold_reason_buf) { hold_reason = hold_reason_buf; } } if( event->eventNumber == ULOG_REMOTE_ERROR ) { RemoteErrorEvent *err = (RemoteErrorEvent *)event; if(!err->getExecuteHost() || !*err->getExecuteHost()) { //Insert remote host information. char *execute_host = NULL; thisRemoteResource->getMachineName(execute_host); err->setExecuteHost(execute_host); delete[] execute_host; } if(err->isCriticalError()) { CriticalErrorBuf.formatstr( "Error from %s: %s", err->getExecuteHost(), err->getErrorText()); critical_error = CriticalErrorBuf.Value(); if(!hold_reason) { hold_reason = critical_error; } //Temporary: the following causes critical remote errors //to be logged as ShadowExceptionEvents, rather than //RemoteErrorEvents. The result is ugly, but guaranteed to //be compatible with other user-log reading tools. BaseShadow::log_except(critical_error); event_already_logged = true; } } if( !event_already_logged && !Shadow->uLog.writeEvent( event, ad ) ) { MyString add_str; sPrintAd(add_str, *ad); dprintf( D_ALWAYS, "unable to log event in pseudo_ulog: %s\n", add_str.Value()); result = -1; } if(put_job_on_hold) { hold_reason = critical_error; if(!hold_reason) { hold_reason = "Job put on hold by remote host."; } Shadow->holdJobAndExit(hold_reason,hold_reason_code,hold_reason_sub_code); //should never get here, because holdJobAndExit() exits. } if( critical_error ) { //Suppress ugly "Shadow exception!" Shadow->exception_already_logged = true; //lame: at the time of this writing, EXCEPT does not want const: EXCEPT("%s", critical_error); } delete event; return result; }
int JobRouterHookMgr::hookJobCleanup(RoutedJob* r_job) { ClassAd temp_ad; char* hook_cleanup = getHookPath(HOOK_JOB_CLEANUP, r_job->src_ad); if (NULL == hook_cleanup) { // hook not defined dprintf(D_FULLDEBUG, "HOOK_JOB_CLEANUP not configured.\n"); return 0; } if (0 >= r_job->dest_ad.size()) { return 0; } // Verify the cleanup hook hasn't already been spawned and that // we're not waiting for it to return. std::string key = r_job->dest_key; if (true == JobRouterHookMgr::checkHookKnown(key.c_str(), HOOK_JOB_CLEANUP)) { dprintf(D_FULLDEBUG, "JobRouterHookMgr::hookJobCleanup " "retried while still waiting for cleanup hook to " "return for job with key %s - ignoring\n", key.c_str()); return 1; } temp_ad = r_job->dest_ad; MyString hook_stdin; sPrintAd(hook_stdin, temp_ad); CleanupClient* cleanup_client = new CleanupClient(hook_cleanup, r_job); if (NULL == cleanup_client) { dprintf(D_ALWAYS|D_FAILURE, "ERROR in JobRouterHookMgr::hookJobCleanup: " "failed to create status update client\n"); return -1; } set_user_priv_from_ad(r_job->src_ad); if (0 == spawn(cleanup_client, NULL, &hook_stdin, PRIV_USER_FINAL)) { dprintf(D_ALWAYS|D_FAILURE, "ERROR in JobRouterHookMgr::JobCleanup: " "failed to spawn HOOK_JOB_CLEANUP (%s)\n", hook_cleanup); delete cleanup_client; return -1; } uninit_user_ids(); // Add our info to the list of hooks currently running for this job. if (false == JobRouterHookMgr::addKnownHook(key.c_str(), HOOK_JOB_CLEANUP)) { dprintf(D_ALWAYS, "ERROR in JobRouterHookMgr::hookJobCleanup: " "failed to add HOOK_JOB_CLEANUP to list of " "hooks running for job key %s\n", key.c_str()); } dprintf(D_FULLDEBUG, "HOOK_JOB_CLEANUP (%s) invoked.\n", hook_cleanup); return 1; }
int JobRouterHookMgr::hookJobExit(RoutedJob* r_job) { ClassAd temp_ad; char* hook_job_exit = getHookPath(HOOK_JOB_EXIT, r_job->src_ad); if (NULL == hook_job_exit) { // hook not defined dprintf(D_FULLDEBUG, "HOOK_JOB_EXIT not configured.\n"); return 0; } // Verify the exit hook hasn't already been spawned and that // we're not waiting for it to return. std::string key = r_job->dest_key; if (true == JobRouterHookMgr::checkHookKnown(key.c_str(),HOOK_JOB_EXIT)) { dprintf(D_FULLDEBUG, "JobRouterHookMgr::hookJobExit " "retried while still waiting for exit hook to return " "for job with key %s - ignoring\n", key.c_str()); return 1; } temp_ad = r_job->src_ad; MyString hook_stdin; sPrintAd(hook_stdin, temp_ad); hook_stdin += "\n------\n"; temp_ad = r_job->dest_ad; sPrintAd(hook_stdin, temp_ad); ExitClient *exit_client = new ExitClient(hook_job_exit, r_job); if (NULL == exit_client) { dprintf(D_ALWAYS|D_FAILURE, "ERROR in JobRouterHookMgr::hookJobExit: " "failed to create exit client\n"); return -1; } set_user_priv_from_ad(r_job->src_ad); if (0 == spawn(exit_client, NULL, &hook_stdin, PRIV_USER_FINAL)) { dprintf(D_ALWAYS|D_FAILURE, "ERROR in JobRouterHookMgr::hookJobExit: " "failed to spawn HOOK_JOB_EXIT (%s)\n", hook_job_exit); delete exit_client; return -1; } uninit_user_ids(); // Add our info to the list of hooks currently running for this job. if (false == JobRouterHookMgr::addKnownHook(key.c_str(), HOOK_JOB_EXIT)) { dprintf(D_ALWAYS, "ERROR in JobRouterHookMgr::hookJobExit: " "failed to add HOOK_JOB_EXIT to list of " "hooks running for job key %s\n", key.c_str()); } dprintf(D_FULLDEBUG, "HOOK_JOB_EXIT (%s) invoked.\n", hook_job_exit); return 1; }
int JobRouterHookMgr::hookTranslateJob(RoutedJob* r_job, std::string &route_info) { ClassAd temp_ad; char* hook_translate = getHookPath(HOOK_TRANSLATE_JOB, r_job->src_ad); if (NULL == hook_translate) { // hook not defined, which is ok dprintf(D_FULLDEBUG, "HOOK_TRANSLATE_JOB not configured.\n"); return 0; } // Verify the translate hook hasn't already been spawned and that // we're not waiting for it to return. std::string key = r_job->src_key; if (true == JobRouterHookMgr::checkHookKnown(key.c_str(), HOOK_TRANSLATE_JOB)) { dprintf(D_FULLDEBUG, "JobRouterHookMgr::hookTranslateJob " "retried while still waiting for translate hook to " "return for job with key %s - ignoring\n", key.c_str()); return 1; } temp_ad = r_job->src_ad; MyString hook_stdin; hook_stdin = route_info.c_str(); hook_stdin += "\n------\n"; sPrintAd(hook_stdin, temp_ad); TranslateClient* translate_client = new TranslateClient(hook_translate, r_job); if (NULL == translate_client) { dprintf(D_ALWAYS|D_FAILURE, "ERROR in JobRouterHookMgr::hookTranslateJob: " "failed to create translation client\n"); return -1; } set_user_priv_from_ad(r_job->src_ad); if (0 == spawn(translate_client, NULL, &hook_stdin, PRIV_USER_FINAL)) { dprintf(D_ALWAYS|D_FAILURE, "ERROR in JobRouterHookMgr::hookTranslateJob: " "failed to spawn HOOK_TRANSLATE_JOB (%s)\n", hook_translate); delete translate_client; return -1; } uninit_user_ids(); // Add our info to the list of hooks currently running for this job. if (false == JobRouterHookMgr::addKnownHook(key.c_str(), HOOK_TRANSLATE_JOB)) { dprintf(D_ALWAYS, "ERROR in JobRouterHookMgr::hookTranslateJob: " "failed to add HOOK_TRANSLATE_JOB to list of " "hooks running for job key %s\n", key.c_str()); } dprintf(D_FULLDEBUG, "HOOK_TRANSLATE_JOB (%s) invoked.\n", hook_translate); return 1; }
int vanilla2grid(int argc, char **argv) { if(argc != 3) { fprintf(stderr, "Usage:\n" " %s filename 'gridurl'\n" " filename - filename of classad to process\n" " girdurl - Unified grid URL\n", argv[0]); return 1; } // Load old classad string. MyString s_jobad = slurp_file(argv[1]); // Read in as old ClassAds format ClassAd jobad((char *)s_jobad.Value(),'\n'); int orig_cluster; if( ! jobad.EvaluateAttrInt(ATTR_CLUSTER_ID, orig_cluster) ) { dprintf(D_ALWAYS, "Vanilla job lacks a cluster\n"); return 1; } int orig_proc; if( ! jobad.EvaluateAttrInt(ATTR_PROC_ID, orig_proc) ) { dprintf(D_ALWAYS, "Vanilla job lacks a proc\n"); return 1; } //==================================================================== // Do something interesting: VanillaToGrid::vanillaToGrid(&jobad, argv[2]); printf("Claiming job %d.%d\n", orig_cluster, orig_proc); MyString errors; switch(claim_job(jobad, NULL, NULL, orig_cluster, orig_proc, &errors, MYID)) { case CJR_OK: break; case CJR_BUSY: fprintf(stderr, "Unable to claim original job %d.%d because it's busy (%s)\n. Continuing anyway.\n", orig_cluster, orig_proc, errors.Value()); break; case CJR_ERROR: fprintf(stderr, "Unable to claim original job %d.%d because of an error: %s\n. Continuing anyway.\n", orig_cluster, orig_proc, errors.Value()); break; } int cluster,proc; if( ! submit_job( jobad, 0, 0, &cluster, &proc ) ) { fprintf(stderr, "Failed to submit job\n"); } printf("Successfully submitted %d.%d\n",cluster,proc); if(0) // Print the transformed add. { // Convert to old classad string MyString out; sPrintAd(out, jobad); printf("%s\n", out.Value()); } return 0; }
bool DCTransferQueue::PollForTransferQueueSlot(int timeout,bool &pending,MyString &error_desc) { if( GoAheadAlways( m_xfer_downloading ) ) { return true; } CheckTransferQueueSlot(); if( !m_xfer_queue_pending ) { // status of request is known pending = false; if( !m_xfer_queue_go_ahead ) { error_desc = m_xfer_rejected_reason; } return m_xfer_queue_go_ahead; } Selector selector; selector.add_fd( m_xfer_queue_sock->get_file_desc(), Selector::IO_READ ); time_t start = time(NULL); do { int t = timeout - (time(NULL) - start); selector.set_timeout( t >= 0 ? t : 0 ); selector.execute(); } while( selector.signalled() ); if( selector.timed_out() ) { // It is expected that we may time out while waiting for a // response. The caller should keep calling this function // periodically until we get a result. pending = true; return false; } m_xfer_queue_sock->decode(); ClassAd msg; if( !getClassAd(m_xfer_queue_sock, msg) || !m_xfer_queue_sock->end_of_message() ) { formatstr(m_xfer_rejected_reason, "Failed to receive transfer queue response from %s for job %s " "(initial file %s).", m_xfer_queue_sock->peer_description(), m_xfer_jobid.c_str(), m_xfer_fname.c_str()); goto request_failed; } int result; // this should be one of the values in XFER_QUEUE_ENUM if( !msg.LookupInteger(ATTR_RESULT,result) ) { std::string msg_str; sPrintAd(msg_str, msg); formatstr(m_xfer_rejected_reason, "Invalid transfer queue response from %s for job %s (%s): %s", m_xfer_queue_sock->peer_description(), m_xfer_jobid.c_str(), m_xfer_fname.c_str(), msg_str.c_str()); goto request_failed; } if( result == XFER_QUEUE_GO_AHEAD ) { m_xfer_queue_go_ahead = true; } else { m_xfer_queue_go_ahead = false; std::string reason; msg.LookupString(ATTR_ERROR_STRING,reason); formatstr(m_xfer_rejected_reason, "Request to transfer files for %s (%s) was rejected by %s: %s", m_xfer_jobid.c_str(), m_xfer_fname.c_str(), m_xfer_queue_sock->peer_description(), reason.c_str()); goto request_failed; } { int report_interval = 0; if( msg.LookupInteger(ATTR_REPORT_INTERVAL,report_interval) ) { m_report_interval = (unsigned)report_interval; m_last_report.getTime(); m_next_report = m_last_report.seconds() + m_report_interval; } } m_xfer_queue_pending = false; pending = m_xfer_queue_pending; return true; request_failed: error_desc = m_xfer_rejected_reason; dprintf(D_ALWAYS, "%s\n", m_xfer_rejected_reason.c_str()); m_xfer_queue_pending = false; m_xfer_queue_go_ahead = false; pending = m_xfer_queue_pending; return false; }
bool Rooster::wakeUp(ClassAd *startd_ad) { ASSERT( startd_ad ); MyString name; startd_ad->LookupString(ATTR_NAME,name); dprintf(D_ALWAYS,"Sending wakeup call to %s.\n",name.Value()); int stdin_pipe_fds[2]; stdin_pipe_fds[0] = -1; // child's side stdin_pipe_fds[1] = -1; // my side if( !daemonCore->Create_Pipe(stdin_pipe_fds) ) { dprintf(D_ALWAYS,"Rooster::wakeUp: failed to create stdin pipe."); return false; } int stdout_pipe_fds[2]; stdout_pipe_fds[0] = -1; // my side stdout_pipe_fds[1] = -1; // child's side if( !daemonCore->Create_Pipe(stdout_pipe_fds) ) { dprintf(D_ALWAYS,"Rooster::wakeUp: failed to create stdout pipe."); daemonCore->Close_Pipe(stdin_pipe_fds[0]); daemonCore->Close_Pipe(stdin_pipe_fds[1]); return false; } int std_fds[3]; std_fds[0] = stdin_pipe_fds[0]; std_fds[1] = stdout_pipe_fds[1]; std_fds[2] = stdout_pipe_fds[1]; int pid = daemonCore->Create_Process( m_wakeup_args.GetArg(0), m_wakeup_args, PRIV_CONDOR_FINAL, 0, FALSE, NULL, NULL, NULL, NULL, std_fds); daemonCore->Close_Pipe(stdin_pipe_fds[0]); daemonCore->Close_Pipe(stdout_pipe_fds[1]); if( pid == -1 ) { dprintf(D_ALWAYS,"Failed to run %s: %s\n", m_wakeup_cmd.Value(), strerror(errno)); daemonCore->Close_Pipe(stdin_pipe_fds[1]); daemonCore->Close_Pipe(stdout_pipe_fds[0]); return false; } MyString stdin_str; sPrintAd(stdin_str, *startd_ad); // Beware: the following code assumes that we will not // deadlock by filling up the stdin pipe while the tool blocks // filling up the stdout pipe. The tool must consume all // input before generating more than a pipe buffer full of output. int n = daemonCore->Write_Pipe(stdin_pipe_fds[1],stdin_str.Value(),stdin_str.Length()); if( n != stdin_str.Length() ) { dprintf(D_ALWAYS,"Rooster::wakeUp: failed to write to %s: %s\n", m_wakeup_cmd.Value(), strerror(errno)); daemonCore->Close_Pipe(stdin_pipe_fds[1]); daemonCore->Close_Pipe(stdout_pipe_fds[0]); return false; } // done writing to tool daemonCore->Close_Pipe(stdin_pipe_fds[1]); MyString stdout_str; while( true ) { char pipe_buf[1024]; n = daemonCore->Read_Pipe(stdout_pipe_fds[0],pipe_buf,1023); if( n <= 0 ) { break; } ASSERT( n < 1024 ); pipe_buf[n] = '\0'; stdout_str += pipe_buf; } // done reading from tool daemonCore->Close_Pipe(stdout_pipe_fds[0]); if( stdout_str.Length() ) { // log debugging output from the tool dprintf(D_ALWAYS|D_NOHEADER,"%s",stdout_str.Value()); } // Would be nice to get final exit status of tool, but // daemonCore() doesn't provide a waitpid() equivalent. // Why didn't I just use my_popen()? Because it doesn't // allow us to write to the tool _and_ log debugging output. return true; }