int smart_reconnect(struct vsp_node * node, int mode) { int old_fd; if(node->flags != O_RDONLY) { return 1; } /* user uses data fd as file descriptor and we have to keep it unchanged */ old_fd = node->dataFd; if(data_hello_conversation(node) < 0) { dc_debug(DC_ERROR, "[%d] Failed to make a new data connection.", node->dataFd); return 1; } /* try to get old fd in use */ node->dataFd = dup2(node->dataFd, old_fd); if( node->dataFd != old_fd) { node->dataFd = old_fd; dc_debug(DC_ERROR, "dup2 failed. Reconnection impossible."); return 1; } if(mode && !dc_set_pos(node, mode, -1)) { dc_debug(DC_ERROR, "[%d] Failed to set correct position.", node->dataFd); return 1; } dc_debug(DC_INFO, "[%d] Broken connection recovered.", node->dataFd); return 0; }
int dc_fstat64(int fd, struct stat64 *buf) #endif { struct vsp_node *node; int rc; char *path; off64_t size; #ifdef DC_CALL_TRACE showTraceBack(); #endif node = get_vsp_node( fd ); if( node == NULL ) { dc_debug(DC_INFO, "Using system native fstat64 for %d.", fd); return system_fstat64(fd, buf); } /* pnfs can not show file size if file opened for write and not closed */ if( node->flags & O_WRONLY ) { size = dc_real_lseek( node, 0, SEEK_CUR ); } path = getNodePath(node); m_unlock(&node->mux); rc = dc_stat64( (const char *) path , buf); free(path); if( node->flags & O_WRONLY ) { buf->st_size = size; } return rc; }
void alarm_handler( int sig) { dc_debug(DC_ERROR, "dcap: Last IO operation timeout."); isIOFailed = 1; isAlarm = 0; /* set back old alarm handler */ sigaction(SIGALRM, &old_sa_alarm, NULL); }
int ping_pong(struct vsp_node * node) { char ping[64]; int len; asciiMessage *aM; struct pollfd pfd; int rc; ping[0] = '\0'; len = sprintf(ping, "%d 2 client ping\n", node->queueID); setNonBlocking(node->fd); rc = sendControlMessage(node->fd, ping, len, node->tunnel); clearNonBlocking(node->fd); if( rc < 0 ) { dc_debug(DC_ERROR, "Ping failed (control line down)."); return 0; } pfd.fd = node->fd; pfd.events = POLLIN; rc = poll(&pfd, 1, 1000*10); /* 10 seconds */ if((rc == 1) && (pfd.revents & POLLIN )) { dcap_set_alarm(10); aM = getControlMessage(HAVETO, node); dcap_set_alarm(0); if( (aM != NULL ) && (aM->type == ASCII_PING) ) { free(aM->msg); free(aM); return 1; } } dc_debug(DC_ERROR, "Ping failed."); return 0; }
struct dirent64 *readdir64( DIR *dir) #endif { dc_debug(DC_TRACE, "Running preloaded readdir64"); #ifdef sgi return ( dirent64_t *)dc_readdir64(dir); #else return dc_readdir64(dir); #endif }
void dc_noBuffering(int fd) { struct vsp_node *node; node = get_vsp_node(fd); if(node == NULL) return; if(node->ahead != NULL) { /* check for DCACHE_RAHEAD */ if(getenv("DCACHE_RAHEAD") != NULL ) { dc_debug(DC_INFO, "Read ahead disabling skipped for fd = %d.", fd); }else{ free(node->ahead); node->ahead=NULL; dc_debug(DC_INFO, "No Read ahead for fd = %d.", fd); } } m_unlock(&node->mux); }
int dcap_set_alarm(unsigned int t) { struct sigaction sa_alarm; struct sigaction *optr; struct sigaction *ptr; if(t) { dc_debug(DC_TRACE, "Setting IO timeout to %d seconds.", t); sa_alarm.sa_handler = alarm_handler; sigemptyset(&sa_alarm.sa_mask); sa_alarm.sa_flags = 0; ptr = &sa_alarm; optr = &old_sa_alarm; /* reset the error flag */ isIOFailed = 0; /* make a note, that alarm is set */ isAlarm = 1; }else{ dc_debug(DC_TRACE, "Removing IO timeout handler."); /* set the old interrupt handler */ /* do nothing if alarm not seted */ if( !isAlarm ) return 0; ptr = &old_sa_alarm; optr = NULL; isAlarm = 0; } if (sigaction(SIGALRM, ptr, optr) < 0) { dc_debug(DC_ERROR,"Sigaction failed!"); return 1; } alarm(t); return 0; }
int validate_env_variable(char* timeout_var, long* timeout_val) { char *timeout_str, *end; timeout_str = getenv(timeout_var); if( timeout_str == NULL || *timeout_str == '\0') { return 0; } *timeout_val = strtol( timeout_str, &end, ENVAR_TIMEOUT_VALUE_BASE); if( end == timeout_str) { dc_debug( DC_INFO, "Invalid value for %s environment variable",timeout_var); return 0; } if( *end != '\0') { dc_debug( DC_INFO, "Ignoring trailing garbage at end of %s value.", timeout_var); } if( *timeout_val < 0) { dc_debug( DC_INFO, "Negative numbers are not allowed for %s environment variable.", timeout_var); return 0; } return 1; }
int open64(const char *path, int flags,...) { mode_t mode = 0; va_list args; if (flags & O_CREAT) { va_start(args, flags); mode = va_arg(args, mode_t); va_end(args); } dc_debug(DC_TRACE, "Running preloaded open64 for %s", path); return dc_open(path, flags, mode); }
int dc_facl(int fd, int cmd, int nentries, void *aclbufp) { struct vsp_node *node; int rc; char *path; off64_t size; #ifdef DC_CALL_TRACE showTraceBack(); #endif node = get_vsp_node( fd ); if( node == NULL ) { dc_debug(DC_INFO, "Using system native fstat64 for %d.", fd); return system_facl(fd, cmd, nentries, aclbufp); } return dc_acl_dummy(cmd); }
int dc_close2(int fd) { int res = 0; struct vsp_node *node; int32_t size; #ifdef DC_CALL_TRACE showTraceBack(); #endif /* nothing wrong ... yet */ dc_errno = DEOK; node = delete_vsp_node(fd); if (node == NULL) { /* we have not such file descriptor, so lets give a try to system */ return system_close(fd); } dc_real_fsync( node ); if(node->unsafeWrite) { size = htonl(-1); /* send end of data */ writen(node->dataFd, (char *) &size, sizeof(size), NULL); /* FIXME: error detection missing */ if (get_fin(node) < 0) { dc_debug(DC_ERROR, "dc_close: mover did not FIN the data blocks."); res = -1; } } close_data_socket(node->dataFd); deleteQueue(node->queueID); m_unlock(&node->mux); node_destroy(node); return res; }
int dc_chown( const char *path, uid_t uid, gid_t gid) { dcap_url *url; struct vsp_node *node; int rc; url = (dcap_url *)dc_getURL(path); if( url == NULL ) { dc_debug(DC_INFO, "Using system native chown for %s.", path); return system_chown(path, uid, gid); } node = new_vsp_node( path ); if( node == NULL ) { free(url->file); free(url->host); if( url->prefix != NULL ) free(url->prefix); free(url); return 1; } node->url = url; if (url->type == URL_PNFS) { node->pnfsId = (char *)strdup(url->file); }else{ node->pnfsId = (char *)strdup(path); } node->asciiCommand = DCAP_CMD_CHOWN; node->uid = uid; node->gid = gid; rc = cache_open(node); /* node cleanup procedure */ node_unplug( node ); deleteQueue(node->queueID); node_destroy(node); return rc; }
int dc_real_fsync( struct vsp_node *node) { int rc = 0; if( (node->ahead != NULL) && ( node->ahead->buffer != NULL ) && node->ahead->isDirty ) { dc_debug(DC_IO, "[%d] Syncing %ld bytes.", node->dataFd, node->ahead->used); if( dc_real_write( node, NULL, 0) < 0 ) { rc = -1; } } return rc; }
int dc_acl(const char *path, int cmd, int nentries, void *aclbufp) { dcap_url *url; struct vsp_node *node; int rc; url = (dcap_url *)dc_getURL(path); if( url == NULL ) { dc_debug(DC_INFO, "Using system native chown for %s.", path); return system_acl(path, cmd, nentries, aclbufp); } else { free(url->file); free(url->host); if( url->prefix != NULL ) { free(url->prefix); } free(url); } return dc_acl_dummy(cmd); }
int dc_lstat64(const char *path, struct stat64 *buf) #endif { dcap_url *url; struct vsp_node *node; #ifdef WIN32 struct _stati64 *s; #else struct stat64 *s; #endif int rc; int old_errno; #ifdef DC_CALL_TRACE showTraceBack(); #endif /* nothing wrong ... yet */ dc_errno = DEOK; url = (dcap_url *)dc_getURL(path); /* let system to do the work where it's possible */ if(url == NULL) { dc_debug(DC_INFO, "Using system native lstat64 for %s.", path); rc = system_lstat64(path, buf); /* isPnfs overwrite errno */ old_errno = errno; if( (buf->st_size != 1) || !isPnfs(path) ) { errno = old_errno; return rc; } } node = new_vsp_node(path); if (node == NULL) { dc_debug(DC_ERROR, "dc_stat: Failed to create new node."); free(url->file); free(url->host); free(url); return -1; } node->url = url; if (url == NULL ) { getPnfsID(node); }else{ if (url->type == URL_PNFS) { node->pnfsId = (char *)strdup(url->file); }else{ node->pnfsId = (char *)strdup(path); } } node->asciiCommand = DCAP_CMD_LSTAT; rc = cache_open(node); if(node->ipc != NULL) { #ifdef WIN32 s = (struct _stati64*)node->ipc; memcpy(buf, s, sizeof(struct _stati64) ); #else s = (struct stat64*)node->ipc; memcpy(buf, s, sizeof(struct stat64) ); #endif free(node->ipc); node->ipc = NULL; } /* node cleanup procedure */ node_unplug( node ); deleteQueue(node->queueID); node_destroy(node); if( rc != 0 ) { errno = ENOENT; } return rc; }
int dc_feof(FILE *fp) { int rc ; struct vsp_node *node; node = get_vsp_node(FILE_NO(fp)); if( node == NULL ) { return system_feof(fp); } #if defined(__linux__) || defined(__GNU__) || defined(__FreeBSD_kernel__) || defined(__CYGWIN__) if ( ((FILE *)fp)->_flags & _IO_EOF_SEEN ) { #else if ( ((FILE *)fp)->_flag & _IOEOF ) { #endif rc = 1 ; }else { rc = 0 ; } m_unlock(&node->mux); return rc ; } FILE *dc_fopen64(const char *file, const char *mode); FILE *dc_fopen(const char *file, const char *mode) { return dc_fopen64(file, mode); } FILE *dc_fopen64(const char *file, const char *mode) { int fd, rw, oflags ; FILE *fp; if( isPnfs( file ) || isUrl(file) ) { rw= ( mode[1] == '+' ) ; switch(*mode) { case 'a': oflags= O_APPEND | O_CREAT | ( rw ? O_RDWR : O_WRONLY ) ; break ; case 'r': oflags= rw ? O_RDWR : O_RDONLY ; break ; case 'w': oflags= O_TRUNC | O_CREAT | ( rw ? O_RDWR : O_WRONLY ) ; break ; default: return NULL ; } fp = (FILE *)malloc( sizeof(FILE) ); if( fp == NULL ) { return NULL; } /* break FILE chain */ #if defined(__linux__) || defined(__GNU__) || defined(__FreeBSD_kernel__) fp->_chain = NULL; fp->_IO_write_ptr = NULL; fp->_IO_write_base = NULL; fp->_lock = NULL; fp->_flags = 0; #else fp->_flag = 0; #endif fd = dc_open(file,oflags, 0644) ; if ( fd < 0 ) { free(fp); return NULL ; } FILE_NO(fp) = fd; } else { dc_debug(DC_TRACE, "Running system native fopen [%s, %s]", file, mode); fp = system_fopen64( file, mode ); } return fp; }
int dc_close(int fd) { int res = 0; int tmp; int32_t size; int32_t closemsg[6]; int msglen; struct vsp_node *node; #ifdef DC_CALL_TRACE showTraceBack(); #endif /* nothing wrong ... yet */ dc_errno = DEOK; node = delete_vsp_node(fd); if (node == NULL) { /* we have not such file descriptor, so lets give a try to system */ dc_debug(DC_INFO, "Using system native close for [%d].", fd); return system_close(fd); } if ( node->lcb != NULL ) { dc_lcb_clean( node ); } dc_real_fsync( node ); if(node->unsafeWrite > 1) { size = htonl(-1); /* send end of data */ writen(node->dataFd, (char *) &size, sizeof(size), NULL); /* FIXME: error detection missing */ if (get_fin(node) < 0) { dc_debug(DC_ERROR, "dc_close: mover did not FIN the data blocks."); res = -1; } } if(node->reference == 0 ) { if( (node->sum != NULL) && ( node->sum->isOk == 1 ) ) { closemsg[0] = htonl(20); closemsg[2] = htonl(12); closemsg[3] = htonl(DCAP_DATA_SUM); closemsg[4] = htonl(node->sum->type); closemsg[5] = htonl(node->sum->sum); msglen = 6; dc_debug(DC_INFO, "File checksum is: %u", node->sum->sum); }else{ closemsg[0] = htonl(4); msglen = 2; } closemsg[1] = htonl(IOCMD_CLOSE); /* actual command */ dc_debug(DC_IO, "Sending CLOSE for fd:%d ID:%d.", node->dataFd, node->queueID); check_timeout_envar(); dcap_set_alarm(closeTimeOut > 0 ? closeTimeOut : DCAP_IO_TIMEOUT/4); tmp = sendDataMessage(node, (char *) closemsg, msglen*sizeof(int32_t), ASCII_OK, NULL); /* FIXME: error detection missing */ if( tmp < 0 ) { dc_debug(DC_ERROR, "sendDataMessage failed."); /* ignore close errors if file was open for read */ if(node->flags & O_WRONLY) { res = -1; } if(isIOFailed) { isIOFailed = 0; /* command line dwon */ if(!ping_pong(node)) { /* remove file descriptor from the list of control lines in use */ lockMember(); deleteMemberByValue(node->fd); unlockMember(); pollDelete(node->fd); close_control_socket(node->fd, node->tunnel); } } } dcap_set_alarm(0); deleteQueue(node->queueID); } /* * Even if there is still a reference to the dcap session, * we have to close local socket descriptor. */ close_data_socket(node->dataFd); node_destroy(node); return res; }
dcap_url* dc_getURL( const char *path ) { dcap_url *url; char *s; char *w; char *port_str; int host_len; int type = URL_NONE; int def_door_len; char *domain; struct servent *se; char *t; if(path == NULL) { dc_errno = DEURL; return NULL; } s = strstr(path, DCAP_PREFIX); if( s != NULL ) { type = URL_DCAP; }else{ s = strstr(path, PNFS_PREFIX); if( s != NULL ) { type = URL_PNFS; } } if( (type != URL_DCAP) && (type != URL_PNFS) ) { dc_errno = DEURL; return NULL; } url = (dcap_url *)malloc(sizeof(dcap_url)); if(url == NULL) { dc_debug(DC_ERROR, "Failed to allocate dcap_url for %s", path); return NULL; } url->host = NULL; url->file = NULL; url->prefix = NULL; url->type= type; url->need_brackets = 0; url->port = -1; if( s != path ) { url->prefix = (char *)xstrndup(path, s - path ); }else{ s = (char *)path; } /* now s is a pointer to url without prefix */ s = (char *)(s + strlen(DCAP_PREFIX)); /* w points to a first / in the path */ w = strchr(s, '/'); if(w == NULL) { free(url); return NULL; } url->file = strdup(w + 1); host_len = w-s; if( host_len != 0 ) { if (s[0] == '[') { /* ipv6 address */ s++; t = strchr(s, ']'); if (t == NULL || t > w) { /* bad formated url */ dc_errno = DEURL; dc_debug(DC_ERROR, "badly formed url for %s", path); free(url); return NULL; } url->need_brackets = 1; url->host = xstrndup(s, t - s); s = t+1; } else { t = strchr(s, ':'); if (t == NULL || t > w) { url->host = xstrndup(s, w - s); s = w; } else { url->host = xstrndup(s, t - s); s = t; } } /* s points to ':' or '/' */ if( s[0] == '/' ) { w = strchr(path, ':'); w = xstrndup(path, w - path); se = getservbyname(w, "tcp"); free(w); url->port = se ? ntohs(se->s_port) : DEFAULT_DOOR_PORT; }else{ s++; port_str = xstrndup(s, w-s); url->port = atoi(port_str); free(port_str); } }else{ if( url->type == URL_PNFS ) { free(url); return NULL; } domain = strchr(w + 1, '/'); if( domain == NULL ) { free(url); return NULL; } domain++; w = strchr(domain , '/'); if( w == NULL ) { w = (char *) domain + strlen(domain); } host_len = w - domain ; def_door_len = strlen(DEFAULT_DOOR); url->host = (char *)malloc( def_door_len + host_len + host_len > 0 ? 2 : 1); if(url->host == NULL) { dc_debug(DC_ERROR, "Failed to allocate hostname for %s", path); free(url); return NULL; } memcpy(url->host, DEFAULT_DOOR , def_door_len); if(host_len) { memcpy(url->host + def_door_len, ".", 1); } memcpy(url->host + def_door_len +1, domain, host_len); url->host[host_len + def_door_len +1] = '\0'; } return url; }
void dc_setNodeBufferSize(struct vsp_node *node, size_t newSize) { char *tmpBuffer; if(node == NULL) return; if( node->ahead == NULL ) { node->ahead = (ioBuffer *)malloc( sizeof(ioBuffer) ); if(node->ahead == NULL) { dc_debug(DC_ERROR, "Failed allocate memory for read-ahead, so skipping"); }else{ node->ahead->buffer = NULL; node->ahead->cur = 0; node->ahead->base = 0; node->ahead->used = 0; node->ahead->size = 0; node->ahead->isDirty = 0; } } if(node->ahead != NULL) { if( node->ahead->buffer == NULL ) { /* allocating the buffer first time */ dc_debug(DC_INFO, "[%d] Allocating %d bytes as Read-ahead buffer.", node->dataFd, newSize); node->ahead->buffer = (char *)malloc(newSize); if( node->ahead->buffer == NULL ) { dc_debug(DC_ERROR, "[%d] Failed to allocate %ld bytes for Read-ahead buffer.", node->dataFd, newSize); }else{ node->ahead->size = newSize; node->ahead->used = 0; node->ahead->cur = 0; node->ahead->isDirty = 0; } }else{ /* changing the buffer size */ if( newSize == node->ahead->size) { /* no changes are needed */ return; } dc_debug(DC_INFO, "[%d] Changing Read-ahead buffer size from %ld to %ld.", node->dataFd, node->ahead->size, newSize); tmpBuffer = (char *)realloc(node->ahead->buffer, newSize); if( tmpBuffer == NULL ) { dc_debug(DC_INFO, "[%d] Failed to change read-ahead buffer size.", node->queueID); return; } node->ahead->buffer = tmpBuffer; if( newSize < node->ahead->size ) { /* if newSize < oldSize, make a corrections of current position and buffer used size. NOTE, that if used < newSize, no changes needed for current position as it can not be bigger than used. */ if(node->ahead->used > newSize) { node->seek = node->ahead->base + newSize; node->whence = SEEK_SET; dc_set_pos(node, DCFT_POSITION, -1); node->ahead->used = newSize; if(node->ahead->cur > newSize) { node->ahead->cur = newSize; } } } node->ahead->size = newSize; } } return; }
int __fxstat64( int i, int fd, struct stat64 *s) { dc_debug(DC_TRACE, "Running preloaded fstat64 for [%d]", fd); return dc_fstat64(fd, s); }
int stat64(const char *p, struct stat64 *s) { dc_debug(DC_TRACE, "Running preloaded stat64 for %s", p); return dc_stat64(p, s); }
off64_t lseek64(int fd, off64_t offset, int mode) { dc_debug(DC_TRACE, "Running preloaded lseek64 for [%d][%lld][%d]", fd, (off64_t)offset, mode); return dc_lseek64(fd, offset, mode); }
int __lxstat64(int i, const char *p, struct stat64 *s) { dc_debug(DC_TRACE, "Running preloaded __lxstat64 for %s", p); return dc_lstat64(p, s); }
ssize_t pwrite64(int fd, const void *buff, size_t n, off64_t off) { dc_debug(DC_TRACE, "Running preloaded pwrite64 for [%d]", fd); return dc_pwrite64(fd, buff, n, off); }
ssize_t dc_real_write( struct vsp_node *node, const void *buff, size_t buflen) { int32_t writemsg[5]; int tmp; int32_t datamsg[2]; int32_t size; int64_t offt; int msglen; size_t len; size_t dataLen; int use_io_buf = 0; size_t wr_buffer = 0; if( (node->ahead == NULL) && ( getenv("DCACHE_WRBUFFER") != NULL ) ) { dc_debug(DC_INFO, "Switching on write buffer."); if(getenv("DCACHE_WA_BUFFER") != NULL) { wr_buffer = atoi( getenv("DCACHE_WA_BUFFER") ); } dc_setNodeBufferSize(node, wr_buffer == 0 ? IO_BUFFER_SIZE : wr_buffer); } if( (node->ahead != NULL) && ( node->ahead->buffer != NULL) ) { use_io_buf = 1; } if( use_io_buf ) { if( ! node->ahead->isDirty ) { if( node->ahead->used ) { switch( node->whence ){ case SEEK_SET: break; case SEEK_CUR: break; default: node->whence = SEEK_CUR; node->seek = -(node->ahead->used - node->ahead->cur); break; } } /* keep current position, including seeks */ node->ahead->base = dc_real_lseek(node, (off64_t)0, SEEK_CUR); node->ahead->isDirty = 1; node->ahead->cur = 0; node->ahead->used = 0; } len = node->ahead->size - node->ahead->cur; if( buflen && ( len > buflen ) ) { memcpy( node->ahead->buffer +node->ahead->cur , buff, buflen ); dc_debug( DC_IO, "[%d] Filling %ld bytes into IO buffer. Available %ld", node->dataFd, buflen, len - buflen); node->ahead->cur += buflen; if( node->ahead->cur > node->ahead->used ) { node->ahead->used = node->ahead->cur; } return buflen; } if( !buflen ) { dc_debug(DC_IO, "[%d] Flushing %d bytes of IO buffer.", node->dataFd, node->ahead->cur); } } /* node->unsafeWrite == 0 : regular write operation node->unsafeWrite == 1 : unsafeWrite, IO request not sended yet node->unsafeWrite >1 : unsafeWrite, IO request sended */ /* do following part allways for regular write and once of unsafe write */ if(!node->unsafeWrite || (node->unsafeWrite == 1 ) ){ if(node->whence == -1) { writemsg[0] = htonl(4); writemsg[1] = htonl(IOCMD_WRITE); msglen = 2; dc_debug(DC_IO,"[%d] Sending IOCMD_WRITE.", node->dataFd); }else{ /* in case of seeks and write, there is no way to keep track of check summ */ if( node->sum != NULL ) { node->sum->isOk = 0 ; } writemsg[0] = htonl(16); writemsg[1] = htonl(IOCMD_SEEK_WRITE); offt = htonll(node->seek); memcpy( (char *) &writemsg[2],(char *) &offt, sizeof(offt)); if(node->whence == SEEK_SET) { writemsg[4] = htonl(IOCMD_SEEK_SET); }else{ writemsg[4] = htonl(IOCMD_SEEK_CURRENT); } dc_debug(DC_IO,"[%d] Sending IOCMD_SEEK_WRITE.", node->dataFd); msglen = 5; } tmp = sendDataMessage(node, (char *) writemsg, msglen*sizeof(int32_t), ASCII_NULL, NULL); if (tmp != COMM_SENT) { m_unlock(&node->mux); dc_debug(DC_ERROR, "sendDataMessage failed."); return -1; } datamsg[0] = htonl(4); datamsg[1] = htonl(IOCMD_DATA); tmp = writen(node->dataFd, (char *) datamsg, sizeof(datamsg), NULL); /* do this part only once if unsafeWrite requaried */ if(node->unsafeWrite) { node->unsafeWrite = 2; } } dataLen = buflen; if( use_io_buf ) dataLen += node->ahead->cur; size = htonl(dataLen); writen(node->dataFd, (char *) &size, sizeof(size), NULL); /* send data size */ if( use_io_buf ) { writen(node->dataFd, (const char *)node->ahead->buffer, node->ahead->cur, NULL); /* send data */ } writen(node->dataFd, (const char *)buff, buflen, NULL); /* send data */ /* update the ckecksum */ if( (node->sum != NULL ) && (node->sum->isOk == 1) ) { if( use_io_buf ) { update_checkSum(node->sum, (unsigned char *)node->ahead->buffer, node->ahead->cur); } /* * we do not need to calculate checksum if buff == NULL ( flush operation ) * if we do so, then check sum well be reseted to default value; */ if( buff != NULL ) { update_checkSum(node->sum, (unsigned char *)buff, buflen); } } if(!node->unsafeWrite) { size = htonl(-1); /* send end of data */ writen(node->dataFd, (char *) &size, sizeof(size), NULL); /* FIXME: error detection missing */ if (get_fin(node) < 0) { dc_debug(DC_ERROR, "dc_write: mover did not FIN the data block."); return -1; } } if( node->whence == SEEK_SET ) { node->pos = dataLen + node->seek; } else { /* SEEK_CUR */ node->pos += (node->seek + dataLen); } node->seek = 0; node->whence = -1; if( use_io_buf ) { node->ahead->cur = 0; node->ahead->used = 0; node->ahead->base = 0; node->ahead->isDirty = 0; } #ifndef WIN32 dc_debug(DC_IO, "[%d] Expected position: %lld @ %ld bytes written.", node->dataFd, (long long int)node->pos, dataLen); #else dc_debug(DC_IO, "[%d] Expected position: %lld @ %ld bytes written.", node->dataFd, (long int)node->pos, dataLen); #endif return buflen; }
FILE *fopen64(const char *path, const char *mode) { dc_debug(DC_TRACE, "Running preloaded fopen for [%s, %s]", path, mode); return dc_fopen(path, mode); }
off64_t ftello64 (FILE *stream ) { dc_debug(DC_TRACE, "Running preloaded ftello64"); return dc_ftello64( stream ); }
int fseeko64( FILE *stream, off64_t offset, int whence) { dc_debug(DC_TRACE, "Running preloaded fseeko64"); return dc_fseeko64( stream, offset, whence ); }
off64_t dc_real_lseek(struct vsp_node *node, off64_t offset, int whence) { int64_t off; int32_t lseekmsg[5]; int32_t size; int tmp; int use_ahead = 0; ConfirmationBlock result; if( (node->ahead != NULL) && ( node->ahead->buffer != NULL) && node->ahead->used) { use_ahead = 1; } if( whence == SEEK_SET ) { /* if already at requested position, do nothing */ result.lseek = dc_real_lseek( node, 0, SEEK_CUR ); if ( result.lseek == offset ) { dc_debug(DC_IO, "[%d] SEEK_SET to the current position, skipping", node->dataFd); return offset; } } if( (whence == SEEK_CUR) && (offset == 0) ) { /* position request, do nothing.... */ if( use_ahead && node->ahead->used) { switch( node->whence ) { /* node->ahead->base already contains seek information */ case SEEK_SET: off = node->seek + node->ahead->cur; break; case SEEK_CUR: off = node->ahead->base + node->ahead->cur; break; default: off = node->ahead->base + node->ahead->cur; } }else{ switch( node->whence ) { case SEEK_SET: off = node->seek; break; case SEEK_CUR: off = node->pos + node->seek; break; default: off = node->pos; } } return off; } if( use_ahead ) { dc_real_fsync(node); } /* funish unsafe write operation if node->unsafeWrite flag > 1 : transaction in progress */ if(node->unsafeWrite > 1) { size = htonl(-1); /* send end of data */ writen(node->dataFd, (char *) &size, sizeof(size), NULL); /* FIXME: error detection missing */ if (get_fin(node) < 0) { dc_debug(DC_ERROR, "dc_lseek: mover did not FIN the data block."); dc_errno = DEUOF; return -1; } node->unsafeWrite = 1; } /* to be fast in seek+read, do not realy seeks now. Do it only read calls as SEEK_AND_READ command */ switch (whence) { case SEEK_SET: /* TODO: what happens, if user will requests offset out of file size ?*/ if( use_ahead && ( (off64_t)(node->ahead->base + node->ahead->used) > offset) && (offset >= (off64_t)node->ahead->base) ) { node->ahead->cur = offset - node->ahead->base; dc_debug(DC_IO, "[%d] SEEK_SET inside Read-ahead buffer. Expected position %ld", node->dataFd, node->ahead->base + node->ahead->cur); node->whence = -1; return offset; } if( use_ahead ) { node->ahead->used = 0; node->ahead->cur = 0; node->ahead->base = 0; } node->seek = offset; node->whence = SEEK_SET; dc_debug(DC_IO, "[%d] Expected seek offset: %ld.", node->dataFd, node->seek); return offset; case SEEK_CUR: if(node->whence == -1) { if( use_ahead && (node->ahead->cur + offset >= 0) && (node->ahead->cur + offset <= node->ahead->used ) ) { node->ahead->cur += offset; dc_debug(DC_IO, "[%d] SEEK_CUR inside Read-ahead buffer. Expected position %ld", node->dataFd, node->ahead->base + node->ahead->cur); result.lseek = node->ahead->base + node->ahead->cur; return (off64_t)result.lseek; } } if(use_ahead) { node->seek = offset + node->ahead->cur - node->ahead->used; node->ahead->used = 0; }else{ node->seek += offset; } if(node->whence != SEEK_SET ) { node->whence = SEEK_CUR; result.lseek = node->pos + node->seek; }else{ /* SEEK_SET */ result.lseek = node->seek; } dc_debug(DC_IO, "[%d] SEEK_CUR offset: %ld expected position %ld.", node->dataFd, node->seek, node->pos + node->seek); return (off64_t)result.lseek; case SEEK_END: /* we have to replay sone thing on SEEK_END, so lets make real seek*/ lseekmsg[0] = htonl(16); lseekmsg[1] = htonl(IOCMD_SEEK); lseekmsg[4] = htonl(IOCMD_SEEK_END); break; default: dc_debug(DC_ERROR, "dc_lseek: illegal value of whence parameter [%d].", whence); dc_debug(DC_ERROR, " Valid values are %d ( SEEK_SET), %d (SEEK_CUR), %d (SEEK_END)", SEEK_SET, SEEK_CUR, SEEK_END); errno = EINVAL; return -1; } off = htonll(offset); memcpy( (char *) &lseekmsg[2],(char *) &off, sizeof(off)); tmp = sendDataMessage(node, (char *) lseekmsg, sizeof(lseekmsg), ASCII_NULL, &result); if (tmp != COMM_SENT) { dc_debug(DC_ERROR, "sendDataMessage failed."); return -1; } node->pos = (off64_t)result.lseek; if( node->ahead != NULL ) { node->ahead->cur = 0; node->ahead->used = 0; node->ahead->isDirty = 0; node->ahead->base = 0; } node->whence = -1; return (off64_t)result.lseek; }
int creat64(const char *path, mode_t mode) { dc_debug(DC_TRACE, "Running preloaded creat for %s", path); return dc_creat(path, mode); }