bool StreamHandler::Init( const char *fn, const char *sn, bool io ) { int flags; int result; HandlerType handler_mode; filename = fn; streamname = sn; is_output = io; if(is_output) { flags = O_CREAT|O_TRUNC|O_WRONLY; } else { flags = O_RDONLY; } remote_fd = REMOTE_CONDOR_open(filename.Value(),(open_flags_t)flags,0777); if(remote_fd<0) { dprintf(D_ALWAYS,"Couldn't open %s to stream %s: %s\n",filename.Value(),streamname.Value(),strerror(errno)); return false; } // create a DaemonCore pipe result = daemonCore->Create_Pipe(pipe_fds, is_output, // registerable for read if it's streamed output !is_output, // registerable for write if it's streamed input false, // blocking read false, // blocking write STREAM_BUFFER_SIZE); if(result==0) { dprintf(D_ALWAYS,"Couldn't create pipe to stream %s: %s\n",streamname.Value(),strerror(errno)); REMOTE_CONDOR_close(remote_fd); return false; } if(is_output) { job_pipe = pipe_fds[1]; handler_pipe = pipe_fds[0]; handler_mode = HANDLE_READ; } else { job_pipe = pipe_fds[0]; handler_pipe = pipe_fds[1]; handler_mode = HANDLE_WRITE; } offset = 0; daemonCore->Register_Pipe(handler_pipe,"Job I/O Pipe",static_cast<PipeHandlercpp>(&StreamHandler::Handler),"Stream I/O Handler",this,handler_mode); done = false; connected = true; handlers[num_handlers++] = this; return true; }
void IOProxyHandler::handle_standard_request( ReliSock *r, char *line ) { char *url = NULL; char path[CHIRP_LINE_MAX]; char newpath[CHIRP_LINE_MAX]; char flags_string[CHIRP_LINE_MAX]; char name[CHIRP_LINE_MAX]; char expr[CHIRP_LINE_MAX]; int result, offset, whence, length, flags, mode, fd, stride_length; int stride_skip, uid, gid, actime, modtime; dprintf(D_SYSCALLS,"IOProxyHandler: request: %s\n",line); flags_string[0] = 0; if(m_enable_files && sscanf_chirp(line,"open %s %s %d",path,flags_string,&mode)==3) { /* Open is a rather special case. First, we attempt to look up the file name and convert it into a physical url. Then, we make sure that we know how to open the url. Finally, we actually open it. */ dprintf(D_SYSCALLS,"Getting mapping for file %s\n",path); result = REMOTE_CONDOR_get_file_info_new(path,url); if(result==0) { dprintf(D_SYSCALLS,"Directed to use url %s\n",url); ASSERT( strlen(url) < CHIRP_LINE_MAX ); if(!strncmp(url,"remote:",7)) { strncpy(path,url+7,CHIRP_LINE_MAX); } else if(!strncmp(url,"buffer:remote:",14)) { strncpy(path,url+14,CHIRP_LINE_MAX); } else { // Condor 7.9.6 dropped the remote: and buffer:remote prefix for the vanilla shadow // so it's not longer correct to assert then these prefixes are missing. // TJ: for some reason get_peer_version() is not set here, so I have to assume that the other side // *might* be 7.9.6 and tolerate the missing url prefix. const CondorVersionInfo *vi = r->get_peer_version(); dprintf(D_SYSCALLS | D_VERBOSE,"File %s maps to url %s, peer version is %d.%d.%d\n", path, url, vi ? vi->getMajorVer() : 0, vi ? vi->getMinorVer() : 0, vi ? vi->getSubMinorVer() : 0); if (vi && ! vi->built_since_version(7,9,6)) { EXCEPT("File %s maps to url %s, which I don't know how to open.\n",path,url); } strncpy(path,url,CHIRP_LINE_MAX); } } else { EXCEPT("Unable to map file %s to a url: %s\n",path,strerror(errno)); } dprintf(D_SYSCALLS,"Which simplifies to file %s\n",path); flags = 0; if( strchr(flags_string,'w') ) { if( strchr(flags_string,'r') ) { flags |= O_RDWR; } else { flags |= O_WRONLY; } } else { flags |= O_RDONLY; } if(strchr(flags_string,'c')) flags |= O_CREAT; if(strchr(flags_string,'t')) flags |= O_TRUNC; if(strchr(flags_string,'x')) flags |= O_EXCL; if(strchr(flags_string,'a')) flags |= O_APPEND; result = REMOTE_CONDOR_open(path,(open_flags_t)flags,mode); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); // Stat stuff if(result>=0) { char *buffer = (char*) malloc(1024); ASSERT( buffer != NULL ); REMOTE_CONDOR_stat(path, buffer); r->put_bytes_raw(buffer,strlen(buffer)); free( buffer ); } free( url ); url = NULL; } else if(m_enable_files && sscanf_chirp(line,"close %d",&fd)==1) { result = REMOTE_CONDOR_close(fd); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"lseek %d %d %d",&fd,&offset,&whence)) { int whence_valid = 1; switch(whence) { case 0: whence = SEEK_SET; break; case 1: whence = SEEK_CUR; break; case 2: whence = SEEK_END; break; default: whence_valid = 0; break; } if(whence_valid) { result = REMOTE_CONDOR_lseek(fd,offset,whence); result = convert(result,errno); } else { result = CHIRP_ERROR_INVALID_REQUEST; } sprintf(line,"%d",result); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"unlink %s",path)==1) { result = REMOTE_CONDOR_unlink(path); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"rename %s %s",path,newpath)==2) { result = REMOTE_CONDOR_rename(path,newpath); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"mkdir %s %d",path,&mode)==2) { result = REMOTE_CONDOR_mkdir(path,mode); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"rmdir %s",path)==1) { result = REMOTE_CONDOR_rmdir(path); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"fsync %d",&fd)==1) { result = REMOTE_CONDOR_fsync(fd); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"lookup %s",path)==1) { result = REMOTE_CONDOR_get_file_info_new(path,url); if(result==0) { dprintf(D_SYSCALLS,"Filename %s maps to url %s\n",path,url); sprintf(line,"%u",(unsigned int)strlen(url)); r->put_line_raw(line); r->put_bytes_raw(url,strlen(url)); } else { sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } free( url ); url = NULL; } else if(m_enable_delayed && sscanf_chirp(line,"set_job_attr_delayed %s %s",name,expr)==2) { classad::ClassAdParser parser; classad::ExprTree *expr_tree; if (strlen(expr) > 993) { dprintf(D_FULLDEBUG, "Chirp update too long! (%lu)\n", strlen(expr)); result = -1; errno = ENAMETOOLONG; } else { result = parser.ParseExpression(expr, expr_tree); if (result) { result = !m_shadow->recordDelayedUpdate(name, *expr_tree); } else { dprintf(D_ALWAYS, "Failed to parse line to a ClassAd expression: %s\n", expr); } } sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } else if(m_enable_updates && sscanf_chirp(line,"set_job_attr %s %s",name,expr)==2) { result = REMOTE_CONDOR_set_job_attr(name,expr); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } else if((m_enable_updates) && sscanf_chirp(line,"get_job_attr %s",name)==1) { char *recv_expr = NULL; result = REMOTE_CONDOR_get_job_attr(name,recv_expr); if(result==0) { sprintf(line,"%u",(unsigned int)strlen(recv_expr)); r->put_line_raw(line); r->put_bytes_raw(recv_expr,strlen(recv_expr)); } else { sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } free( recv_expr ); } else if(m_enable_delayed && sscanf_chirp(line,"get_job_attr_delayed %s",name)==1) { std::string value; classad::ClassAdUnParser unparser; std::auto_ptr<classad::ExprTree> expr = m_shadow->getDelayedUpdate(name); if (expr.get()) { unparser.Unparse(value, expr.get()); sprintf(line,"%u",(unsigned int)value.size()); r->put_line_raw(line); r->put_bytes_raw(value.c_str(),value.size()); } else { sprintf(line,"%d",convert(-1,ENOENT)); r->put_line_raw(line); } } else if(m_enable_updates && sscanf_chirp(line,"constrain %s",expr)==1) { result = REMOTE_CONDOR_constrain(expr); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"read %d %d",&fd,&length)==2) { char *buffer = (char*) malloc(length); if(buffer) { result = REMOTE_CONDOR_read(fd,buffer,length); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); if(result>0) { r->put_bytes_raw(buffer,result); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); } } else if(m_enable_files && sscanf_chirp(line,"write %d %d",&fd,&length)==2) { char *buffer = (char*) malloc(length); if(buffer) { result = r->get_bytes_raw(buffer,length); if(result==length) { result = REMOTE_CONDOR_write(fd,buffer,length); sprintf(line,"%d",convert(result,errno)); } else { sprintf(line,"%d",CHIRP_ERROR_INVALID_REQUEST); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); } r->put_line_raw(line); } else if(m_enable_updates && sscanf_chirp(line,"phase %s", name)==1) { result = REMOTE_CONDOR_phase( name ); sprintf(line, "%d", convert(result,errno)); r->put_line_raw(line); } else if(m_enable_updates && sscanf_chirp(line,"ulog %s", name)==1) { GenericEvent event; ClassAd *ad; // setInfoText truncates name to 128 bytes event.setInfoText( name ); ad = event.toClassAd(); ASSERT(ad); result = REMOTE_CONDOR_ulog( ad ); sprintf(line, "%d", convert(result,errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line, "pread %d %d %d", &fd, &length, &offset) == 3){ char *buffer = (char*) malloc(length); if(buffer) { result = REMOTE_CONDOR_pread(fd,buffer,length,offset); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); if(result > 0) { r->put_bytes_raw(buffer,result); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } else if(m_enable_files && sscanf_chirp(line,"pwrite %d %d %d", &fd, &length, &offset) == 3){ char *buffer = (char*) malloc(length); if(buffer) { result = r->get_bytes_raw(buffer,length); if(result == length) { result = REMOTE_CONDOR_pwrite(fd,buffer,length,offset); sprintf(line,"%d",convert(result,errno)); } else { sprintf(line,"%d",CHIRP_ERROR_INVALID_REQUEST); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); } r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line, "sread %d %d %d %d %d", &fd, &length, &offset, &stride_length, &stride_skip) == 5) { char *buffer = (char*) malloc(length); if(buffer) { result = REMOTE_CONDOR_sread(fd,buffer,length,offset, stride_length,stride_skip); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); if(result > 0) { r->put_bytes_raw(buffer,result); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } else if(m_enable_files && sscanf_chirp(line,"swrite %d %d %d %d %d", &fd, &length, &offset, &stride_length, &stride_skip) == 5) { char *buffer = (char*) malloc(length); if(buffer) { result = r->get_bytes_raw(buffer,length); if(result==length) { result = REMOTE_CONDOR_swrite(fd,buffer,length,offset, stride_length,stride_skip); sprintf(line,"%d",convert(result,errno)); } else { sprintf(line,"%d",CHIRP_ERROR_INVALID_REQUEST); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); } r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"rmall %s", &path) == 1) { result = REMOTE_CONDOR_rmall(path); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"fstat %d", &fd) == 1) { char *buffer = (char*) malloc(1024); if(buffer) { result = REMOTE_CONDOR_fstat(fd, buffer); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); if(result>=0) { r->put_bytes_raw(buffer,strlen(buffer)); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } else if(m_enable_files && sscanf_chirp(line,"fstatfs %d", &fd) == 1) { char *buffer = (char*) malloc(1024); if(buffer) { result = REMOTE_CONDOR_fstatfs(fd, buffer); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if(result>=0) { r->put_bytes_raw(buffer,strlen(buffer)); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } else if(m_enable_files && sscanf_chirp(line,"fchown %d %d %d", &fd, &uid, &gid) == 3) { result = REMOTE_CONDOR_fchown(fd, uid, gid); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"fchmod %d %d", &fd, &mode) == 2) { result = REMOTE_CONDOR_fchmod(fd, mode); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"ftruncate %d %d", &fd, &length) == 2) { result = REMOTE_CONDOR_ftruncate(fd, length); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"getfile %s", &path) == 1) { char *buffer = NULL; result = REMOTE_CONDOR_getfile(path, &buffer); sprintf(line,"%d",convert(result,errno)); r->put_line_raw(line); if(result > 0) { r->put_bytes_raw(buffer,result); free(buffer); } } else if(m_enable_files && sscanf_chirp(line,"putfile %s %d %d", &path, &mode, &length) == 3) { // First check if putfile is possible result = REMOTE_CONDOR_putfile(path, mode, length); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if ((length > 0) && (result >= 0)) { char *buffer = (char*) malloc(length); if(buffer) { result = r->get_bytes_raw(buffer,length); // Now actually putfile result = REMOTE_CONDOR_putfile_buffer(buffer, length); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } } else if(m_enable_files && sscanf_chirp(line,"getlongdir %s", &path) == 1) { char *buffer = NULL; result = REMOTE_CONDOR_getlongdir(path, buffer); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if(result>0) { r->put_bytes_raw(buffer,strlen(buffer)); } } else if(m_enable_files && sscanf_chirp(line,"getdir %s", &path) == 1) { char *buffer = NULL; result = REMOTE_CONDOR_getdir(path, buffer); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if(result>0) { r->put_bytes_raw(buffer,strlen(buffer)); } } else if(m_enable_files && sscanf_chirp(line,"whoami %d", &length) == 1) { char *buffer = (char*)malloc(length); if(buffer) { result = REMOTE_CONDOR_whoami(length, buffer); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if(result>0) { r->put_bytes_raw(buffer,result); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } else if(m_enable_files && sscanf_chirp(line,"whoareyou %s %d", &path, &length) == 2) { char *buffer = (char*)malloc(length); if(buffer) { result = REMOTE_CONDOR_whoareyou(path, length, buffer); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if(result>0) { r->put_bytes_raw(buffer,result); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } else if(m_enable_files && sscanf_chirp(line,"link %s %s", &path, &newpath) == 2) { result = REMOTE_CONDOR_link(path, newpath); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"symlink %s %s", &path, &newpath) == 2) { result = REMOTE_CONDOR_symlink(path, newpath); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"readlink %s %d", &path, &length) == 2) { char *buffer = NULL; result = REMOTE_CONDOR_readlink(path, length, &buffer); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if(result>0) { r->put_bytes_raw(buffer,result); free(buffer); } } else if(m_enable_files && sscanf_chirp(line,"statfs %s", &path) == 1) { char *buffer = (char*) malloc(1024); if(buffer) { result = REMOTE_CONDOR_statfs(path, buffer); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if(result>=0) { r->put_bytes_raw(buffer,strlen(buffer)); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } else if(m_enable_files && sscanf_chirp(line,"stat %s", &path) == 1) { char *buffer = (char*) malloc(1024); if(buffer) { result = REMOTE_CONDOR_stat(path, buffer); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if(result==0) { r->put_bytes_raw(buffer,strlen(buffer)); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } else if(m_enable_files && sscanf_chirp(line,"lstat %s", &path) == 1) { char *buffer = (char*) malloc(1024); if(buffer) { result = REMOTE_CONDOR_lstat(path, buffer); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); if(result>=0) { r->put_bytes_raw(buffer,strlen(buffer)); } free(buffer); } else { sprintf(line,"%d",CHIRP_ERROR_NO_MEMORY); r->put_line_raw(line); } } else if(m_enable_files && sscanf_chirp(line,"access %s %d", &path, &mode) == 2) { result = REMOTE_CONDOR_access(path, mode); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"chmod %s %d", &path, &mode) == 2) { result = REMOTE_CONDOR_chmod(path, mode); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"chown %s %d %d", &path, &uid, &gid) == 3) { result = REMOTE_CONDOR_chown(path, uid, gid); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"lchown %s %d %d", &path, &uid, &gid) == 3) { result = REMOTE_CONDOR_lchown(path, uid, gid); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"truncate %s %d", &path, &length) == 2) { result = REMOTE_CONDOR_truncate(path, length); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_files && sscanf_chirp(line,"utime %s %d %d", &path, &actime, &modtime) == 3){ result = REMOTE_CONDOR_utime(path, actime, modtime); sprintf(line, "%d", convert(result, errno)); r->put_line_raw(line); } else if(m_enable_updates && strncmp(line,"version",7)==0) { sprintf(line,"%d",CHIRP_VERSION); r->put_line_raw(line); } else { sprintf(line,"%d",CHIRP_ERROR_INVALID_REQUEST); r->put_line_raw(line); } dprintf(D_SYSCALLS,"IOProxyHandler: response: %s\n",line); }
bool StreamHandler::Init( const char *fn, const char *sn, bool io, int f ) { int result; HandlerType handler_mode; filename = fn; streamname = sn; is_output = io; flags = f; if( flags == -1 ) { if( is_output ) { flags = O_CREAT | O_TRUNC | O_WRONLY; } else { flags = O_RDONLY; } } bool shouldAppend = false; if( flags & O_APPEND ) { // If we actually pass O_APPEND, then when we reconnect, flushing the // buffer will result in duplicate data if the far side suffered a // partial write. (If it failed to write the buffer at all, that's // OK, because we /wanted/ to append it to the file.) // // Instead, unset O_APPEND and simulate the effect: seek to the end of // the file on open and set offset to that. shouldAppend = true; flags = flags & (~O_APPEND); } remote_fd = REMOTE_CONDOR_open(filename.Value(),(open_flags_t)flags,0777); if(remote_fd<0) { dprintf(D_ALWAYS,"Couldn't open %s to stream %s: %s\n",filename.Value(),streamname.Value(),strerror(errno)); return false; } offset = 0; if( shouldAppend ) { offset = REMOTE_CONDOR_lseek( remote_fd, 0, SEEK_END ); if( offset < 0 ) { dprintf( D_ALWAYS, "Couldn't seek to end of %s for stream %s when append mode was requested: %s\n", filename.Value(), streamname.Value(), strerror( errno ) ); return false; } dprintf( D_SYSCALLS, "StreamHandler: Sought to %ld as a result of append request.\n", (long)offset ); } // create a DaemonCore pipe result = daemonCore->Create_Pipe(pipe_fds, is_output, // registerable for read if it's streamed output !is_output, // registerable for write if it's streamed input false, // blocking read false, // blocking write STREAM_BUFFER_SIZE); if(result==0) { dprintf(D_ALWAYS,"Couldn't create pipe to stream %s: %s\n",streamname.Value(),strerror(errno)); REMOTE_CONDOR_close(remote_fd); return false; } if(is_output) { job_pipe = pipe_fds[1]; handler_pipe = pipe_fds[0]; handler_mode = HANDLE_READ; } else { job_pipe = pipe_fds[0]; handler_pipe = pipe_fds[1]; handler_mode = HANDLE_WRITE; } daemonCore->Register_Pipe(handler_pipe,"Job I/O Pipe",static_cast<PipeHandlercpp>(&StreamHandler::Handler),"Stream I/O Handler",this,handler_mode); done = false; connected = true; handlers.push_back( this ); return true; }
int StreamHandler::Handler( int /* fd */) { int result; int actual; // // If we're disconnected from the shadow, the REMOTE_CONDOR_* calls in // this function will ASSERT() because of the bogus syscall_sock. This // is a problem if we're waiting for the shadow to reconnect. // if( syscall_sock && syscall_sock->get_file_desc() == INVALID_SOCKET ) { Disconnect(); // If we're writing, empty the pipe and check the write on reconnect. // The Disconnect() above unregisters this handler, so the application // should block until then, and we don't have to worry about losing // any more data. result = daemonCore->Read_Pipe( handler_pipe, buffer, STREAM_BUFFER_SIZE ); if( result > 0 ) { pending = result; } else if( result == 0 ) { // We know the remote fsync will fail, but it might make sense // to try it again after the reconnect, so we do nothing. // (The handler has already been unregistered; when we reregister, // it should show up as ready to read again, and return EOF again.) } else { // See question below. } return KEEP_STREAM; } if(is_output) { // Output from the job to the shadow dprintf(D_SYSCALLS,"StreamHandler: %s: stream ready\n",streamname.Value()); // As STREAM_BUFFER_SIZE should be <= PIPE_BUF, following should // never block result = daemonCore->Read_Pipe(handler_pipe,buffer,STREAM_BUFFER_SIZE); if(result>0) { dprintf(D_SYSCALLS,"StreamHandler: %s: %d bytes available, seeking to offset %ld\n",streamname.Value(),result,(long)offset); errno = 0; pending = result; REMOTE_CONDOR_lseek(remote_fd,offset,SEEK_SET); if (errno == ETIMEDOUT) { Disconnect(); return KEEP_STREAM; } // This means something's really wrong with the file -- FS full // i/o error, so punt. if (errno != 0) { EXCEPT("StreamHandler: %s: couldn't lseek on %s to %d: %s",streamname.Value(),filename.Value(),(int)offset, strerror(errno)); } errno = 0; actual = REMOTE_CONDOR_write(remote_fd,buffer,result); if (errno == ETIMEDOUT) { Disconnect(); return KEEP_STREAM; } if(actual!=result) { EXCEPT("StreamHandler: %s: couldn't write to %s: %s (%d!=%d)",streamname.Value(),filename.Value(),strerror(errno),actual,result); } dprintf(D_SYSCALLS,"StreamHandler: %s: %d bytes written to %s\n",streamname.Value(),result,filename.Value()); offset+=actual; } else if(result==0) { dprintf(D_SYSCALLS,"StreamHandler: %s: end of stream\n",streamname.Value()); daemonCore->Cancel_Pipe(handler_pipe); daemonCore->Close_Pipe(handler_pipe); done=true; result = REMOTE_CONDOR_fsync(remote_fd); if (result != 0) { // This is bad. All of our writes have succeeded, but // the final fsync has not. We don't have a good way // to recover, as we haven't saved the data. // just punt EXCEPT("StreamHandler:: %s: couldn't fsync %s: %s", streamname.Value(), filename.Value(), strerror(errno)); } // If close fails, that's OK, we know the bytes are on disk REMOTE_CONDOR_close(remote_fd); handlers.remove( this ); } else if(result<0) { dprintf(D_SYSCALLS,"StreamHandler: %s: unable to read: %s\n",streamname.Value(),strerror(errno)); // Why don't we EXCEPT here? } } else { dprintf(D_SYSCALLS,"StreamHandler: %s: stream ready\n",streamname.Value()); errno = 0; REMOTE_CONDOR_lseek(remote_fd,offset,SEEK_SET); if (errno == ETIMEDOUT) { Disconnect(); return KEEP_STREAM; } errno = 0; result = REMOTE_CONDOR_read(remote_fd,buffer,STREAM_BUFFER_SIZE); if (errno == ETIMEDOUT) { Disconnect(); return KEEP_STREAM; } if(result>0) { dprintf(D_SYSCALLS,"StreamHandler: %s: %d bytes read from %s\n",streamname.Value(),result,filename.Value()); actual = daemonCore->Write_Pipe(handler_pipe,buffer,result); if(actual>=0) { dprintf(D_SYSCALLS,"StreamHandler: %s: %d bytes consumed by job\n",streamname.Value(),actual); offset+=actual; } else { dprintf(D_SYSCALLS,"StreamHandler: %s: nothing consumed by job\n",streamname.Value()); } } else if(result==0) { dprintf(D_SYSCALLS,"StreamHandler: %s: end of file\n",streamname.Value()); done=true; daemonCore->Cancel_Pipe(handler_pipe); daemonCore->Close_Pipe(handler_pipe); REMOTE_CONDOR_close(remote_fd); handlers.remove( this ); } else if(result<0) { EXCEPT("StreamHandler: %s: unable to read from %s: %s",streamname.Value(),filename.Value(),strerror(errno)); } } return KEEP_STREAM; }
int StreamHandler::Handler( int /* fd */) { int result; int actual; if(is_output) { // Output from the job to the shadow dprintf(D_SYSCALLS,"StreamHandler: %s: stream ready\n",streamname.Value()); // As STREAM_BUFFER_SIZE should be <= PIPE_BUF, following should // never block result = daemonCore->Read_Pipe(handler_pipe,buffer,STREAM_BUFFER_SIZE); if(result>0) { dprintf(D_SYSCALLS,"StreamHandler: %s: %d bytes available\n",streamname.Value(),result); errno = 0; pending = result; REMOTE_CONDOR_lseek(remote_fd,offset,SEEK_SET); if (errno == ETIMEDOUT) { Disconnect(); return KEEP_STREAM; } // This means something's really wrong with the file -- FS full // i/o error, so punt. if (errno != 0) { EXCEPT("StreamHandler: %s: couldn't lseek on %s to %d: %s",streamname.Value(),filename.Value(),(int)offset, strerror(errno)); } errno = 0; actual = REMOTE_CONDOR_write(remote_fd,buffer,result); if (errno == ETIMEDOUT) { Disconnect(); return KEEP_STREAM; } if(actual!=result) { EXCEPT("StreamHandler: %s: couldn't write to %s: %s (%d!=%d)",streamname.Value(),filename.Value(),strerror(errno),actual,result); } dprintf(D_SYSCALLS,"StreamHandler: %s: %d bytes written to %s\n",streamname.Value(),result,filename.Value()); offset+=actual; } else if(result==0) { dprintf(D_SYSCALLS,"StreamHandler: %s: end of stream\n",streamname.Value()); daemonCore->Cancel_Pipe(handler_pipe); daemonCore->Close_Pipe(handler_pipe); done=true; result = REMOTE_CONDOR_fsync(remote_fd); if (result != 0) { // This is bad. All of our writes have succeeded, but // the final fsync has not. We don't have a good way // to recover, as we haven't saved the data. // just punt EXCEPT("StreamHandler:: %s: couldn't fsync %s: %s", streamname.Value(), filename.Value(), strerror(errno)); } // If close fails, that's OK, we know the bytes are on disk REMOTE_CONDOR_close(remote_fd); } else if(result<0) { dprintf(D_SYSCALLS,"StreamHandler: %s: unable to read: %s\n",streamname.Value(),strerror(errno)); // Why don't we EXCEPT here? } } else { dprintf(D_SYSCALLS,"StreamHandler: %s: stream ready\n",streamname.Value()); errno = 0; REMOTE_CONDOR_lseek(remote_fd,offset,SEEK_SET); if (errno == ETIMEDOUT) { Disconnect(); return KEEP_STREAM; } errno = 0; result = REMOTE_CONDOR_read(remote_fd,buffer,STREAM_BUFFER_SIZE); if (errno == ETIMEDOUT) { Disconnect(); return KEEP_STREAM; } if(result>0) { dprintf(D_SYSCALLS,"StreamHandler: %s: %d bytes read from %s\n",streamname.Value(),result,filename.Value()); actual = daemonCore->Write_Pipe(handler_pipe,buffer,result); if(actual>=0) { dprintf(D_SYSCALLS,"StreamHandler: %s: %d bytes consumed by job\n",streamname.Value(),actual); offset+=actual; } else { dprintf(D_SYSCALLS,"StreamHandler: %s: nothing consumed by job\n",streamname.Value()); } } else if(result==0) { dprintf(D_SYSCALLS,"StreamHandler: %s: end of file\n",streamname.Value()); done=true; daemonCore->Cancel_Pipe(handler_pipe); daemonCore->Close_Pipe(handler_pipe); REMOTE_CONDOR_close(remote_fd); } else if(result<0) { EXCEPT("StreamHandler: %s: unable to read from %s: %s",streamname.Value(),filename.Value(),strerror(errno)); } } return KEEP_STREAM; }