Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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;

}
Ejemplo n.º 5
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
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
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;

}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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);
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
0
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;

}
Ejemplo n.º 20
0
int __fxstat64( int i, int fd, struct stat64 *s)
{
	dc_debug(DC_TRACE, "Running preloaded fstat64 for [%d]", fd);
	return dc_fstat64(fd, s);
}
Ejemplo n.º 21
0
int stat64(const char *p, struct stat64 *s)
{
	dc_debug(DC_TRACE, "Running preloaded stat64 for %s", p);
	return dc_stat64(p, s);
}
Ejemplo n.º 22
0
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);
}
Ejemplo n.º 23
0
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);
}
Ejemplo n.º 24
0
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);
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
0
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);

}
Ejemplo n.º 27
0
off64_t ftello64 (FILE *stream )
{
	dc_debug(DC_TRACE, "Running preloaded ftello64");
	return dc_ftello64( stream );
}
Ejemplo n.º 28
0
int fseeko64( FILE *stream, off64_t offset, int whence)
{
	dc_debug(DC_TRACE, "Running preloaded fseeko64");
	return dc_fseeko64( stream, offset, whence );
}
Ejemplo n.º 29
0
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;
}
Ejemplo n.º 30
0
int creat64(const char *path, mode_t mode)
{
	dc_debug(DC_TRACE, "Running preloaded creat for %s", path);
	return dc_creat(path, mode);
}