int irodsTruncate (const char *path, off_t size) { dataObjInp_t dataObjInp; int status; pathCache_t *tmpPathCache; iFuseConn_t *iFuseConn = NULL; rodsLog (LOG_DEBUG, "irodsTruncate: %s", path); if (matchAndLockPathCache ((char *) path, &tmpPathCache) == 1) { if(tmpPathCache->fileCache != NULL) { LOCK_STRUCT(*tmpPathCache->fileCache); if(tmpPathCache->fileCache->state == HAVE_NEWLY_CREATED_CACHE) { status = truncate (tmpPathCache->fileCache->fileCachePath, size); if (status >= 0) { updatePathCacheStatFromFileCache (tmpPathCache); UNLOCK_STRUCT(*(tmpPathCache->fileCache)); UNLOCK_STRUCT(*tmpPathCache); return (0); } } UNLOCK_STRUCT(*(tmpPathCache->fileCache)); } } UNLOCK_STRUCT(*tmpPathCache); memset (&dataObjInp, 0, sizeof (dataObjInp)); status = parseRodsPathStr ((char *) (path + 1) , &MyRodsEnv, dataObjInp.objPath); if (status < 0) { rodsLogError (LOG_ERROR, status, "irodsTruncate: parseRodsPathStr of %s error", path); /* use ENOTDIR for this type of error */ return -ENOTDIR; } dataObjInp.dataSize = size; getAndUseIFuseConn (&iFuseConn, &MyRodsEnv); RECONNECT_IF_NECESSARY(status, iFuseConn, rcDataObjTruncate (iFuseConn->conn, &dataObjInp)); if (status >= 0) { pathCache_t *tmpPathCache; if (matchAndLockPathCache ((char *) path, &tmpPathCache) == 1) { tmpPathCache->stbuf.st_size = size; } UNLOCK_STRUCT(*tmpPathCache); status = 0; } else { rodsLogError (LOG_ERROR, status, "irodsTruncate: rcDataObjTruncate of %s error", path); status = -ENOENT; } unuseIFuseConn (iFuseConn); return (status); }
int renmeLocalPath( char *from, char *to, char *toIrodsPath ) { pathCache_t *fromPathCache = NULL; pathCache_t *tmpPathCache = NULL; /* do not check existing path here as path cache may be out of date */ matchAndLockPathCache( from, &fromPathCache ); if ( fromPathCache == NULL ) { return 0; } LOCK( PathCacheLock ); if ( fromPathCache->fileCache != NULL ) { LOCK_STRUCT( *( fromPathCache->fileCache ) ); free( fromPathCache->fileCache->localPath ); fromPathCache->fileCache->localPath = strdup( to ); free( fromPathCache->fileCache->objPath ); fromPathCache->fileCache->objPath = strdup( toIrodsPath ); _pathReplace( ( char * ) to, fromPathCache->fileCache, &fromPathCache->stbuf, &tmpPathCache ); UNLOCK_STRUCT( *( fromPathCache->fileCache ) ); } else { _pathReplace( ( char * ) to, NULL /* fromPathCache->fileCache */, &fromPathCache->stbuf, &tmpPathCache ); } /* need to unlock fileCache here since the following function call ness to lock fileCache */ _pathNotExist( ( char * ) from ); UNLOCK_STRUCT( *fromPathCache ); UNLOCK( PathCacheLock ); return 0; }
/* getIFuseConnByPath - try to use the same conn as opened desc of the * same path */ iFuseConn_t *getAndUseConnByPath( char *localPath, int *status ) { iFuseConn_t *iFuseConn; /* make sure iFuseConn is not released after getAndLockIFuseDescByPath finishes */ pathCache_t *tmpPathCache; matchAndLockPathCache( pctable, localPath, &tmpPathCache ); if ( tmpPathCache != NULL ) { *status = _getAndUseConnForPathCache( &iFuseConn, tmpPathCache ); UNLOCK_STRUCT( *tmpPathCache ); } else { /* no match. just assign one */ pathExist(pctable, localPath, NULL, NULL, NULL); // need to find a way to clean up *status = getAndUseIFuseConn( &iFuseConn ); } return iFuseConn; }
int irodsOpen (const char *path, struct fuse_file_info *fi) { dataObjInp_t dataObjInp; int status; int fd; iFuseConn_t *iFuseConn = NULL; iFuseDesc_t *desc = NULL; pathCache_t *tmpPathCache = NULL; struct stat stbuf; char cachePath[MAX_NAME_LEN]; char objPath[MAX_NAME_LEN]; int flags = fi->flags; rodsLog (LOG_DEBUG, "irodsOpen: %s, flags = %d", path, fi->flags); matchAndLockPathCache((char *) path, &tmpPathCache); if(tmpPathCache!= NULL) { if(tmpPathCache->fileCache != NULL) { LOCK_STRUCT(*(tmpPathCache->fileCache)); if (tmpPathCache->fileCache->state != NO_FILE_CACHE) { rodsLog (LOG_DEBUG, "irodsOpen: a match for %s", path); desc = newIFuseDesc(tmpPathCache->fileCache->objPath, (char *) path, tmpPathCache->fileCache, &status); if (status < 0) { UNLOCK_STRUCT(*(tmpPathCache->fileCache)); UNLOCK_STRUCT(*tmpPathCache); rodsLogError (LOG_ERROR, status, "irodsOpen: create descriptor of %s error", dataObjInp.objPath); return status; } fi->fh = desc->index; if(tmpPathCache->fileCache->iFd == 0) { tmpPathCache->fileCache->iFd = open(tmpPathCache->fileCache->fileCachePath, O_RDWR); } UNLOCK_STRUCT(*(tmpPathCache->fileCache)); UNLOCK_STRUCT(*tmpPathCache); return (0); } UNLOCK_STRUCT(*(tmpPathCache->fileCache)); } UNLOCK_STRUCT(*tmpPathCache); } memset (&dataObjInp, 0, sizeof (dataObjInp)); dataObjInp.openFlags = flags; status = parseRodsPathStr ((char *) (path + 1) , &MyRodsEnv, objPath); rstrcpy(dataObjInp.objPath, objPath, MAX_NAME_LEN); if (status < 0) { rodsLogError (LOG_ERROR, status, "irodsOpen: parseRodsPathStr of %s error", path); /* use ENOTDIR for this type of error */ return -ENOTDIR; } iFuseConn = getAndUseConnByPath((char *) path, &MyRodsEnv, &status); /* status = getAndUseIFuseConn(&iFuseConn, &MyRodsEnv); */ if(status < 0) { rodsLogError (LOG_ERROR, status, "irodsOpen: cannot get connection for %s error", path); /* use ENOTDIR for this type of error */ return -ENOTDIR; } /* do only O_RDONLY (0) */ status = _irodsGetattr (iFuseConn, path, &stbuf); if ((flags & (O_WRONLY | O_RDWR)) != 0 || status < 0 || stbuf.st_size > MAX_READ_CACHE_SIZE) { fd = rcDataObjOpen (iFuseConn->conn, &dataObjInp); unuseIFuseConn (iFuseConn); if (fd < 0) { rodsLogError (LOG_ERROR, status, "irodsOpen: rcDataObjOpen of %s error, status = %d", path, fd); return -ENOENT; } fileCache_t *fileCache = addFileCache(fd, objPath, (char *) path, NULL, stbuf.st_mode, stbuf.st_size, NO_FILE_CACHE); matchAndLockPathCache((char *) path, &tmpPathCache); if(tmpPathCache == NULL) { pathExist((char *) path, fileCache, &stbuf, NULL); } else { _addFileCacheForPath(tmpPathCache, fileCache); UNLOCK_STRUCT(*tmpPathCache); } desc = newIFuseDesc (objPath, (char *) path, fileCache, &status); if (desc == NULL) { rodsLogError (LOG_ERROR, status, "irodsOpen: allocIFuseDesc of %s error", path); return -ENOENT; } } else { rodsLog (LOG_DEBUG, "irodsOpenWithReadCache: caching %s", path); if ((status = getFileCachePath (path, cachePath)) < 0) { unuseIFuseConn(iFuseConn); return status; } /* get the file to local cache */ dataObjInp.dataSize = stbuf.st_size; status = rcDataObjGet (iFuseConn->conn, &dataObjInp, cachePath); unuseIFuseConn(iFuseConn); if (status < 0) { rodsLogError (LOG_ERROR, status, "irodsOpenWithReadCache: rcDataObjGet of %s error", dataObjInp.objPath); return status; } int fd = open(cachePath, O_RDWR); fileCache_t *fileCache = addFileCache(fd, objPath, (char *) path, cachePath, stbuf.st_mode, stbuf.st_size, HAVE_READ_CACHE); matchAndLockPathCache((char *) path, &tmpPathCache); if(tmpPathCache == NULL) { pathExist((char *) path, fileCache, &stbuf, NULL); } else { _addFileCacheForPath(tmpPathCache, fileCache); UNLOCK_STRUCT(*tmpPathCache); } desc = newIFuseDesc(objPath, (char *) path,fileCache, &status); if (status < 0) { rodsLogError (LOG_ERROR, status, "irodsOpen: create descriptor of %s error", dataObjInp.objPath); return status; } } fi->fh = desc->index; return (0); }
int irodsChmod (const char *path, mode_t mode) { int status; modDataObjMeta_t modDataObjMetaInp; keyValPair_t regParam; dataObjInfo_t dataObjInfo; char dataMode[SHORT_STR_LEN]; pathCache_t *tmpPathCache; iFuseConn_t *iFuseConn = NULL; rodsLog (LOG_DEBUG, "irodsChmod: %s", path); matchAndLockPathCache((char *) path, &tmpPathCache); if (tmpPathCache->fileCache != NULL) { LOCK_STRUCT(*tmpPathCache->fileCache); if(tmpPathCache->fileCache->state == HAVE_NEWLY_CREATED_CACHE) { /* has not actually been created yet */ tmpPathCache->fileCache->mode = mode; UNLOCK_STRUCT(*tmpPathCache->fileCache); UNLOCK_STRUCT(*tmpPathCache); return (0); } UNLOCK_STRUCT(*tmpPathCache->fileCache); } UNLOCK_STRUCT(*tmpPathCache); if(tmpPathCache->stbuf.st_nlink != 1) { rodsLog (LOG_NOTICE, "irodsChmod: modification of the mode of non file object is currently not supported", path); return 0; } memset (®Param, 0, sizeof (regParam)); snprintf (dataMode, SHORT_STR_LEN, "%d", mode); addKeyVal (®Param, DATA_MODE_KW, dataMode); addKeyVal (®Param, ALL_KW, ""); memset(&dataObjInfo, 0, sizeof(dataObjInfo)); status = parseRodsPathStr ((char *) (path + 1) , &MyRodsEnv, dataObjInfo.objPath); if (status < 0) { rodsLogError (LOG_ERROR, status, "irodsChmod: parseRodsPathStr of %s error", path); /* use ENOTDIR for this type of error */ return -ENOTDIR; } modDataObjMetaInp.regParam = ®Param; modDataObjMetaInp.dataObjInfo = &dataObjInfo; getAndUseIFuseConn (&iFuseConn, &MyRodsEnv); RECONNECT_IF_NECESSARY(status, iFuseConn, rcModDataObjMeta(iFuseConn->conn, &modDataObjMetaInp)); if (status >= 0) { #ifdef CACHE_FUSE_PATH pathCache_t *tmpPathCache; if (matchAndLockPathCache ((char *) path, &tmpPathCache) == 1) { tmpPathCache->stbuf.st_mode &= 0xfffffe00; tmpPathCache->stbuf.st_mode |= (mode & 0777); UNLOCK_STRUCT(*tmpPathCache); } #endif status = 0; } else { rodsLogError(LOG_ERROR, status, "irodsChmod: rcModDataObjMeta failure"); status = -ENOENT; } unuseIFuseConn (iFuseConn); clearKeyVal (®Param); return(status); }
int _irodsGetattr (iFuseConn_t *iFuseConn, const char *path, struct stat *stbuf) { int status; dataObjInp_t dataObjInp; rodsObjStat_t *rodsObjStatOut = NULL; #ifdef CACHE_FUSE_PATH pathCache_t *tmpPathCache; #endif rodsLog (LOG_DEBUG, "_irodsGetattr: %s", path); #ifdef CACHE_FUSE_PATH /*if (lookupPathNotExist( (char *) path) == 1) { rodsLog (LOG_DEBUG, "irodsGetattr: a match for non existing path %s", path); return -ENOENT; }*/ if (matchAndLockPathCache ((char *) path, &tmpPathCache) == 1) { rodsLog (LOG_DEBUG, "irodsGetattr: a match for path %s", path); if (tmpPathCache->fileCache != NULL) { LOCK_STRUCT(*(tmpPathCache->fileCache)); if(tmpPathCache->fileCache->state == HAVE_NEWLY_CREATED_CACHE) { status = _updatePathCacheStatFromFileCache (tmpPathCache); UNLOCK_STRUCT(*(tmpPathCache->fileCache)); UNLOCK_STRUCT(*tmpPathCache); if (status < 0) { clearPathFromCache ((char *) path); } else { *stbuf = tmpPathCache->stbuf; return (0); } } else { UNLOCK_STRUCT(*(tmpPathCache->fileCache)); UNLOCK_STRUCT(*tmpPathCache); } } else { UNLOCK_STRUCT(*tmpPathCache); } } #endif memset (stbuf, 0, sizeof (struct stat)); memset (&dataObjInp, 0, sizeof (dataObjInp)); status = parseRodsPathStr ((char *) (path + 1) , &MyRodsEnv, dataObjInp.objPath); if (status < 0) { rodsLogError (LOG_ERROR, status, "irodsGetattr: parseRodsPathStr of %s error", path); /* use ENOTDIR for this type of error */ return -ENOTDIR; } status = rcObjStat (iFuseConn->conn, &dataObjInp, &rodsObjStatOut); if (status < 0) { if (isReadMsgError (status)) { ifuseReconnect (iFuseConn); status = rcObjStat (iFuseConn->conn, &dataObjInp, &rodsObjStatOut); } if (status < 0) { if (status != USER_FILE_DOES_NOT_EXIST) { rodsLogError (LOG_ERROR, status, "irodsGetattr: rcObjStat of %s error", path); } #ifdef CACHE_FUSE_PATH pathNotExist ((char *) path); #endif return -ENOENT; } } if (rodsObjStatOut->objType == COLL_OBJ_T) { fillDirStat (stbuf, atoi (rodsObjStatOut->createTime), atoi (rodsObjStatOut->modifyTime), atoi (rodsObjStatOut->modifyTime)); } else if (rodsObjStatOut->objType == UNKNOWN_OBJ_T) { pathNotExist ((char *) path); if (rodsObjStatOut != NULL) freeRodsObjStat (rodsObjStatOut); return -ENOENT; } else { fillFileStat (stbuf, rodsObjStatOut->dataMode, rodsObjStatOut->objSize, atoi (rodsObjStatOut->createTime), atoi (rodsObjStatOut->modifyTime), atoi (rodsObjStatOut->modifyTime)); } if (rodsObjStatOut != NULL) freeRodsObjStat (rodsObjStatOut); /* don't set file cache */ pathExist ((char *) path, NULL, stbuf, &tmpPathCache); return 0; }
/************************************************************************** * private functions **************************************************************************/ static int _commitLocalBuffer(const char *iRODSPath, struct fuse_file_info *fi, lazyUploadFileInfo_t *lazyUploadFileInfo) { int status; int desc; char bufferPath[MAX_NAME_LEN]; int descInx; status = _getBufferPath(iRODSPath, bufferPath); if(status < 0) { rodsLog (LOG_DEBUG, "_upload: failed to get Buffered lazy upload file path - %s", iRODSPath); return status; } // close local buffer file handle if(lazyUploadFileInfo->localHandle < 0) { rodsLog (LOG_DEBUG, "_commitLocalBuffer: wrong file descriptor - %s, %d", iRODSPath, lazyUploadFileInfo->localHandle); return -EBADF; } // no write but requested flush if(lazyUploadFileInfo->curOffset == 0) { return 0; } fsync(lazyUploadFileInfo->localHandle); close(lazyUploadFileInfo->localHandle); lazyUploadFileInfo->localHandle = -1; rodsLog (LOG_DEBUG, "_commitLocalBuffer: upload - %s", iRODSPath); if(lazyUploadFileInfo->commitCount == 0) { // put and reopen iRODS file dataObjInp_t dataObjInp; int fd; pathCache_t *tmpPathCache = NULL; iFuseConn_t *iFuseConn = NULL; iFuseDesc_t *desc = NULL; struct stat stbuf; char objPath[MAX_NAME_LEN]; descInx = GET_IFUSE_DESC_INDEX(fi); rodsLog (LOG_DEBUG, "_commitLocalBuffer: closing existing iRODS file handle - %s - %d", iRODSPath, descInx); status = ifuseClose (&IFuseDesc[descInx]); if (status < 0) { int myError; if ((myError = getErrno (status)) > 0) { return (-myError); } else { return -ENOENT; } } // put rodsLog (LOG_DEBUG, "_commitLocalBuffer: uploading buffered file - %s", iRODSPath); status = _upload(iRODSPath); if(status != 0) { rodsLog (LOG_DEBUG, "_commitLocalBuffer: upload error - %s, %d", iRODSPath, status); return status; } // reopen file rodsLog (LOG_DEBUG, "_commitLocalBuffer: reopening iRODS file handle - %s", iRODSPath); memset (&dataObjInp, 0, sizeof (dataObjInp)); //dataObjInp.openFlags = lazyUploadFileInfo->accmode; dataObjInp.openFlags = O_RDWR | O_APPEND; status = parseRodsPathStr ((char *) iRODSPath, LazyUploadRodsEnv, objPath); rstrcpy(dataObjInp.objPath, objPath, MAX_NAME_LEN); if (status < 0) { rodsLogError (LOG_ERROR, status, "_commitLocalBuffer: parseRodsPathStr of %s error", iRODSPath); /* use ENOTDIR for this type of error */ return -ENOTDIR; } iFuseConn = getAndUseConnByPath((char *) iRODSPath, &status); /* status = getAndUseIFuseConn(&iFuseConn); */ if(status < 0) { rodsLogError (LOG_ERROR, status, "_commitLocalBuffer: cannot get connection for %s error", iRODSPath); /* use ENOTDIR for this type of error */ return -ENOTDIR; } status = _irodsGetattr (iFuseConn, iRODSPath, &stbuf); fd = rcDataObjOpen (iFuseConn->conn, &dataObjInp); unuseIFuseConn (iFuseConn); if (fd < 0) { rodsLogError (LOG_ERROR, status, "_commitLocalBuffer: rcDataObjOpen of %s error, status = %d", iRODSPath, fd); return -ENOENT; } fileCache_t *fileCache = addFileCache(fd, objPath, (char *) iRODSPath, NULL, stbuf.st_mode, stbuf.st_size, NO_FILE_CACHE); matchAndLockPathCache(pctable, (char *) iRODSPath, &tmpPathCache); if(tmpPathCache == NULL) { pathExist(pctable, (char *) iRODSPath, fileCache, &stbuf, NULL); } else { _addFileCacheForPath(tmpPathCache, fileCache); UNLOCK_STRUCT(*tmpPathCache); } desc = newIFuseDesc (objPath, (char *) iRODSPath, fileCache, &status); if (desc == NULL) { rodsLogError (LOG_ERROR, status, "_commitLocalBuffer: allocIFuseDesc of %s error", iRODSPath); return -ENOENT; } SET_IFUSE_DESC_INDEX(fi, desc->index); rodsLog (LOG_DEBUG, "_commitLocalBuffer: created new file handle - %s - %d", iRODSPath, desc->index); } else { // append int localDesc = open (bufferPath, O_RDONLY, 0755); char *buffer = (char*)malloc(FUSE_LAZY_UPLOAD_MEM_BUFFER_SIZE); int grandTotalReadLen = 0; if(localDesc < 0) { rodsLog (LOG_DEBUG, "_commitLocalBuffer: file descriptor error - %s, %d", iRODSPath, localDesc); return -ENOENT; } descInx = GET_IFUSE_DESC_INDEX(fi); if (checkFuseDesc (descInx) < 0) { return -EBADF; } status = 0; while(grandTotalReadLen < lazyUploadFileInfo->curOffset) { int totalReadLen = 0; int totalWriteLen = 0; while(totalReadLen < FUSE_LAZY_UPLOAD_MEM_BUFFER_SIZE) { int readLen = read(localDesc, buffer + totalReadLen, FUSE_LAZY_UPLOAD_MEM_BUFFER_SIZE - totalReadLen); if(readLen > 0) { totalReadLen += readLen; } else if(readLen == 0) { // EOF break; } else if(readLen < 0) { rodsLog (LOG_DEBUG, "_commitLocalBuffer: buffered file read error - %s, %d", iRODSPath, localDesc); status = getErrno (readLen); break; } } if(status >= 0) { while(totalWriteLen < totalReadLen) { int writeLen = _ifuseWrite (&IFuseDesc[descInx], buffer + totalWriteLen, totalReadLen - totalWriteLen, lazyUploadFileInfo->curLocalOffsetStart + totalWriteLen); if(writeLen > 0) { totalWriteLen += writeLen; } else if(writeLen == 0) { // EOF break; } else if(writeLen < 0) { rodsLog (LOG_DEBUG, "_commitLocalBuffer: iRODS file write error - %s", iRODSPath); status = getErrno (writeLen); break; } } } grandTotalReadLen += totalReadLen; } unlockDesc (descInx); free(buffer); close(localDesc); } rodsLog (LOG_DEBUG, "_commitLocalBuffer: reset local buffered file - %s", iRODSPath); // reset local buffer file desc = open (bufferPath, O_RDWR|O_CREAT|O_TRUNC, 0755); lazyUploadFileInfo->localHandle = desc; lazyUploadFileInfo->commitCount++; lazyUploadFileInfo->curLocalOffsetStart += lazyUploadFileInfo->curOffset; lazyUploadFileInfo->curOffset = 0; return (0); }