Ejemplo n.º 1
0
int
irodsWrite( const char *path, const char *buf, size_t size, off_t offset,
            struct fuse_file_info *fi ) {
    int descInx;
    int status;

    rodsLog( LOG_DEBUG, "irodsWrite: %s", path );

    descInx = fi->fh;

    if ( checkFuseDesc( descInx ) < 0 ) {
        return -EBADF;
    }

    status = _ifuseWrite( &IFuseDesc[descInx], ( char * )buf, size, offset );
    unlockDesc( descInx );

    return status;
}
/**************************************************************************
 * 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);
}
int
writeLazyUploadBufferedFile (const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
    int status;
    lazyUploadFileInfo_t *lazyUploadFileInfo = NULL;
    char iRODSPath[MAX_NAME_LEN];
    char bufferPath[MAX_NAME_LEN];
    off_t seek_status;
    int descInx;

    // convert input path to iRODSPath
    status = _getiRODSPath(path, iRODSPath);
    if(status < 0) {
        rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: failed to get iRODS path - %s", path);
        return status;
    }

    status = _getBufferPath(iRODSPath, bufferPath);
    if(status < 0) {
        rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: failed to get buffer path - %s", iRODSPath);
        return status;
    }

    LOCK(LazyUploadLock);

    // check the given file is Buffered
    lazyUploadFileInfo = (lazyUploadFileInfo_t *)lookupFromHashTable(LazyUploadBufferedFileTable_Opened, iRODSPath);
    if(lazyUploadFileInfo != NULL) {
        // has lazy upload file handle opened
        if(lazyUploadFileInfo->localHandle < 0) {
            rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: wrong file descriptor - %s, %d", iRODSPath, lazyUploadFileInfo->localHandle);
            UNLOCK(LazyUploadLock);
            return -EBADF;
        }
    } else {
        rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: file is not opened - %s", iRODSPath);
        UNLOCK(LazyUploadLock);
        return -EBADF;
    }

    if(offset - lazyUploadFileInfo->curLocalOffsetStart < 0) {
        // backward?
        // commit local buffered data
        status = _commitLocalBuffer(iRODSPath, fi, lazyUploadFileInfo);
        if(status < 0) {
            rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: failed to commit local buffered data - %s", iRODSPath);
            UNLOCK(LazyUploadLock);
            return status; 
        }

        // rewrite directly to iRODS
        descInx = GET_IFUSE_DESC_INDEX(fi);

        if (checkFuseDesc (descInx) < 0) {
            UNLOCK(LazyUploadLock);
            return -EBADF;
        }

        status = _ifuseWrite (&IFuseDesc[descInx], (char *)buf, size, offset);
        unlockDesc (descInx);
        UNLOCK(LazyUploadLock);
        return status;
    }

    // try to write to local buffer
    seek_status = lseek (lazyUploadFileInfo->localHandle, offset - lazyUploadFileInfo->curLocalOffsetStart, SEEK_SET);
    if (seek_status != (offset - lazyUploadFileInfo->curLocalOffsetStart)) {
        status = (int)seek_status;
        rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: failed to seek file desc - %d, %ld -> %ld", lazyUploadFileInfo->localHandle, offset - lazyUploadFileInfo->curLocalOffsetStart, seek_status);
        UNLOCK(LazyUploadLock);
        return status;
    }

    // TEST
    //if (lazyUploadFileInfo->curOffset > 10*1024*1024) {
    //    status = -1;
    //   errno = ENOSPC;
    //} else {
    //    status = write (lazyUploadFileInfo->localHandle, buf, size);
    //}
    // TEST END

    status = write (lazyUploadFileInfo->localHandle, buf, size);
    rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: write to opened lazy-upload Buffered file - %d", lazyUploadFileInfo->localHandle);

    if (status < 0) {
        // no space?
        if (errno == ENOSPC) {
            // handle no space
            // mode switch
            status = _commitLocalBuffer(iRODSPath, fi, lazyUploadFileInfo);
            if(status < 0) {
                rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: failed to change to appending mode - %s", iRODSPath);
                UNLOCK(LazyUploadLock);
                return status; 
            }

            // write to local buffer again
            seek_status = lseek (lazyUploadFileInfo->localHandle, offset - lazyUploadFileInfo->curLocalOffsetStart, SEEK_SET);
            if (seek_status != (offset - lazyUploadFileInfo->curLocalOffsetStart)) {
                status = (int)seek_status;
                rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: failed to seek file desc - %d, %ld -> %ld", lazyUploadFileInfo->localHandle, offset - lazyUploadFileInfo->curLocalOffsetStart, seek_status);
                UNLOCK(LazyUploadLock);
                return status;
            }

            status = write (lazyUploadFileInfo->localHandle, buf, size);
            rodsLog (LOG_DEBUG, "writeLazyUploadBufferedFile: write to opened lazy-upload Buffered file - %d", lazyUploadFileInfo->localHandle);

            if(status >= 0) {
                lazyUploadFileInfo->curOffset += status;
            }
        }
    } else {
        lazyUploadFileInfo->curOffset += status;
    }

    UNLOCK(LazyUploadLock);

    return status;
}