bool DCStarter::peek(bool transfer_stdout, ssize_t &stdout_offset, bool transfer_stderr, ssize_t &stderr_offset, const std::vector<std::string> &filenames, std::vector<ssize_t> &offsets, size_t max_bytes, bool &retry_sensible, PeekGetFD &next, std::string &error_msg, unsigned timeout, const std::string &sec_session_id, DCTransferQueue *xfer_q) { compat_classad::ClassAd ad; ad.InsertAttr(ATTR_JOB_OUTPUT, transfer_stdout); ad.InsertAttr("OutOffset", stdout_offset); ad.InsertAttr(ATTR_JOB_ERROR, transfer_stderr); ad.InsertAttr("ErrOffset", stderr_offset); ad.InsertAttr(ATTR_VERSION, CondorVersion()); size_t total_files = 0; total_files += transfer_stdout ? 1 : 0; total_files += transfer_stderr ? 1 : 0; if (filenames.size()) { total_files += filenames.size(); std::vector<classad::ExprTree *> filelist; filelist.reserve(filenames.size()); std::vector<classad::ExprTree *> offsetlist; offsetlist.reserve(filenames.size()); std::vector<ssize_t>::const_iterator it2 = offsets.begin(); for (std::vector<std::string>::const_iterator it = filenames.begin(); it != filenames.end() && it2 != offsets.end(); it++, it2++) { classad::Value value; value.SetStringValue(*it); filelist.push_back(classad::Literal::MakeLiteral(value)); value.SetIntegerValue(*it2); offsetlist.push_back(classad::Literal::MakeLiteral(value)); } classad::ExprTree *list(classad::ExprList::MakeExprList(filelist)); ad.Insert("TransferFiles", list); list = classad::ExprList::MakeExprList(offsetlist); ad.Insert("TransferOffsets", list); } ad.InsertAttr(ATTR_MAX_TRANSFER_BYTES, static_cast<long long>(max_bytes)); ReliSock sock; if( !connectSock(&sock, timeout, NULL) ) { error_msg = "Failed to connect to starter"; return false; } if( !startCommand(STARTER_PEEK, &sock, timeout, NULL, NULL, false, sec_session_id.c_str()) ) { error_msg = "Failed to send START_PEEK to starter"; return false; } sock.encode(); if (!putClassAd(&sock, ad) || !sock.end_of_message()) { error_msg = "Failed to send request to starter"; return false; } compat_classad::ClassAd response; sock.decode(); if (!getClassAd(&sock, response) || !sock.end_of_message()) { error_msg = "Failed to read response for peeking at logs."; return false; } dPrintAd(D_FULLDEBUG, response); bool success = false; if (!response.EvaluateAttrBool(ATTR_RESULT, success) || !success) { response.EvaluateAttrBool(ATTR_RETRY, retry_sensible); error_msg = "Remote operation failed."; response.EvaluateAttrString(ATTR_ERROR_STRING, error_msg); return false; } classad::Value valueX; classad_shared_ptr<classad::ExprList> list; if (!response.EvaluateAttr("TransferFiles", valueX) || !valueX.IsSListValue(list)) { error_msg = "Unable to evaluate starter response"; return false; } classad_shared_ptr<classad::ExprList> offlist; if (!response.EvaluateAttr("TransferOffsets", valueX) || !valueX.IsSListValue(offlist)) { error_msg = "Unable to evaluate starter response (missing offsets)"; return false; } size_t remaining = max_bytes; size_t file_count = 0; classad::ExprList::const_iterator it2 = offlist->begin(); for (classad::ExprList::const_iterator it = list->begin(); it != list->end() && it2 != offlist->end(); it++, it2++) { classad::Value value; (*it2)->Evaluate(value); off_t off = -1; value.IsIntegerValue(off); (*it)->Evaluate(value); std::string filename; int64_t xfer_fd = -1; if (!value.IsStringValue(filename) && value.IsIntegerValue(xfer_fd)) { if (xfer_fd == 0) filename = "_condor_stdout"; if (xfer_fd == 1) filename = "_condor_stderr"; } int fd = next.getNextFD(filename); filesize_t size = -1; int retval; if ((retval = sock.get_file(&size, fd, false, false, remaining, xfer_q)) && (retval != GET_FILE_MAX_BYTES_EXCEEDED)) { error_msg = "Internal error when transferring file " + filename; } else if (size >= 0) { remaining -= max_bytes; file_count++; off += size; } else { error_msg = "Failed to transfer file " + filename; } if (xfer_fd == 0) { stdout_offset = off; //dprintf(D_FULLDEBUG, "New stdout offset: %ld\n", stdout_offset); } else if (xfer_fd == 1) { stderr_offset = off; } else { std::vector<ssize_t>::iterator it4 = offsets.begin(); for (std::vector<std::string>::const_iterator it3 = filenames.begin(); it3 != filenames.end() && it4 != offsets.end(); it3++, it4++) { if (*it3 == filename) *it4 = off; } } } size_t remote_file_count; if (!sock.get(remote_file_count) || !sock.end_of_message()) { error_msg = "Unable to get remote file count."; return false; } if (file_count != remote_file_count) { std::stringstream ss; ss << "Recieved " << file_count << " files, but remote side thought it sent " << remote_file_count << " files"; error_msg = ss.str(); return false; } if ((total_files != file_count) && !error_msg.size()) { error_msg = "At least one file transfer failed."; return false; } return true; }
int main( int argc, char *argv[] ) { char *machine_name = 0; char *log_name = 0; char *pool=0; int i; daemon_t type = DT_MASTER; myDistro->Init( argc, argv ); config(); for( i=1; i<argc; i++ ) { if(!strcmp(argv[i],"-help")) { usage(argv[0]); exit(0); } else if(!strcmp(argv[i],"-pool")) { i++; if(!argv[i]) { fprintf(stderr,"-pool requires an argument.\n\n"); usage(argv[0]); exit(1); } pool = argv[i]; } else if(!strcmp(argv[i],"-version")) { version(); exit(0); } else if(!strcmp(argv[i],"-debug")) { dprintf_set_tool_debug("TOOL", 0); } else if(argv[i][0]=='-') { type = stringToDaemonType(&argv[i][1]); if( type == DT_NONE || type == DT_DAGMAN) { usage(argv[0]); exit(1); } } else if(argv[i][0]!='-') { if(!machine_name) { machine_name = argv[i]; } else if(!log_name) { log_name = argv[i]; } else { fprintf(stderr,"Extra argument: %s\n\n",argv[i]); usage(argv[0]); exit(1); } } else { usage(argv[0]); exit(1); } } if( !machine_name || !log_name ) { usage(argv[0]); exit(1); } Daemon *daemon; ReliSock *sock; if (pool) { DCCollector col( pool ); if( ! col.addr() ) { fprintf( stderr, "Error: %s\n", col.error() ); exit(1); } daemon = new Daemon( type, machine_name, col.addr() ); } else { daemon = new Daemon( type, machine_name ); } dprintf(D_FULLDEBUG,"Locating daemon process on %s...\n",machine_name); if(!daemon->locate()) { fprintf(stderr,"Couldn't locate daemon on %s: %s\n",machine_name,daemon->error()); exit(1); } dprintf(D_FULLDEBUG,"Daemon %s is %s\n",daemon->hostname(),daemon->addr()); sock = (ReliSock*)daemon->startCommand( DC_FETCH_LOG, Sock::reli_sock); if(!sock) { fprintf(stderr,"couldn't connect to daemon %s at %s\n",daemon->hostname(),daemon->addr()); return 1; } int commandType = DC_FETCH_LOG_TYPE_PLAIN; if ((strcmp(log_name, "HISTORY") == 0) || (strcmp(log_name, "STARTD_HISTORY") == 0)) { commandType = DC_FETCH_LOG_TYPE_HISTORY; } if ((strcmp(log_name, "STARTD.PER_JOB_HISTORY_DIR") == 0) || (strcmp(log_name, "STARTD.PER_JOB_HISTORY_DIR") == 0)) { commandType = DC_FETCH_LOG_TYPE_HISTORY_DIR; } sock->put( commandType ); sock->put( log_name ); sock->end_of_message(); if (commandType == DC_FETCH_LOG_TYPE_HISTORY_DIR) { return handleHistoryDir(sock); } int result = -1; int exitcode = 1; const char *reason=NULL; filesize_t filesize; sock->decode(); sock->code(result); switch(result) { case -1: reason = "permission denied"; break; case DC_FETCH_LOG_RESULT_SUCCESS: result = sock->get_file(&filesize,1,0); if(result>=0) { exitcode = 0; } else { reason = "connection lost"; } break; case DC_FETCH_LOG_RESULT_NO_NAME: reason = "no log file by that name"; break; case DC_FETCH_LOG_RESULT_CANT_OPEN: reason = "server was unable to access it"; break; case DC_FETCH_LOG_RESULT_BAD_TYPE: reason = "server can't provide that type of log"; break; default: reason = "unknown error"; break; } if(exitcode!=0) { fprintf(stderr,"Couldn't fetch log: %s.\n",reason); } return exitcode; }