Skip to content

Commit

Permalink
Move filelock to file_handle
Browse files Browse the repository at this point in the history
  • Loading branch information
iychoi committed Aug 22, 2023
1 parent c28304f commit 13d5dcf
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 411 deletions.
144 changes: 106 additions & 38 deletions fs/file_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import (

// FileHandle is a handle for a file opened
type FileHandle struct {
id string
filesystem *FileSystem
connection *connection.IRODSConnection
irodsfilehandle *types.IRODSFileHandle
entry *Entry
offset int64
openmode types.FileOpenMode
mutex sync.Mutex
id string
filesystem *FileSystem
connection *connection.IRODSConnection
irodsFileHandle *types.IRODSFileHandle
irodsFileLockHandle *types.IRODSFileLockHandle
entry *Entry
offset int64
openMode types.FileOpenMode
mutex sync.Mutex
}

// GetID returns ID
Expand Down Expand Up @@ -47,32 +48,32 @@ func (handle *FileHandle) GetOffset() int64 {

// GetOpenMode returns file open mode
func (handle *FileHandle) GetOpenMode() types.FileOpenMode {
return handle.openmode
return handle.openMode
}

// IsReadMode returns true if file is opened with read mode
func (handle *FileHandle) IsReadMode() bool {
return handle.openmode.IsRead()
return handle.openMode.IsRead()
}

// IsReadOnlyMode returns true if file is opened with read only mode
func (handle *FileHandle) IsReadOnlyMode() bool {
return handle.openmode.IsReadOnly()
return handle.openMode.IsReadOnly()
}

// IsWriteMode returns true if file is opened with write mode
func (handle *FileHandle) IsWriteMode() bool {
return handle.openmode.IsWrite()
return handle.openMode.IsWrite()
}

// IsWriteOnlyMode returns true if file is opened with write only mode
func (handle *FileHandle) IsWriteOnlyMode() bool {
return handle.openmode.IsWriteOnly()
return handle.openMode.IsWriteOnly()
}

// GetIRODSFileHandle returns iRODS File Handle
func (handle *FileHandle) GetIRODSFileHandle() *types.IRODSFileHandle {
return handle.irodsfilehandle
return handle.irodsFileHandle
}

// GetEntry returns Entry info
Expand All @@ -85,9 +86,19 @@ func (handle *FileHandle) Close() error {
handle.mutex.Lock()
defer handle.mutex.Unlock()

if handle.irodsFileLockHandle != nil {
// unlock if locked
err := irods_fs.UnlockDataObject(handle.connection, handle.irodsFileLockHandle)
if err != nil {
return err
}

handle.irodsFileLockHandle = nil
}

defer handle.filesystem.ioSession.ReturnConnection(handle.connection)

err := irods_fs.CloseDataObject(handle.connection, handle.irodsfilehandle)
err := irods_fs.CloseDataObject(handle.connection, handle.irodsFileHandle)
handle.filesystem.fileHandleMap.Remove(handle.id)

if handle.IsWriteMode() {
Expand All @@ -103,7 +114,7 @@ func (handle *FileHandle) Seek(offset int64, whence int) (int64, error) {
handle.mutex.Lock()
defer handle.mutex.Unlock()

newOffset, err := irods_fs.SeekDataObject(handle.connection, handle.irodsfilehandle, offset, types.Whence(whence))
newOffset, err := irods_fs.SeekDataObject(handle.connection, handle.irodsFileHandle, offset, types.Whence(whence))
if err != nil {
return newOffset, err
}
Expand All @@ -117,7 +128,7 @@ func (handle *FileHandle) Truncate(size int64) error {
handle.mutex.Lock()
defer handle.mutex.Unlock()

err := irods_fs.TruncateDataObjectHandle(handle.connection, handle.irodsfilehandle, size)
err := irods_fs.TruncateDataObjectHandle(handle.connection, handle.irodsFileHandle, size)
if err != nil {
return err
}
Expand All @@ -131,10 +142,10 @@ func (handle *FileHandle) Read(buffer []byte) (int, error) {
defer handle.mutex.Unlock()

if !handle.IsReadMode() {
return 0, xerrors.Errorf("file is opened with %s mode", handle.openmode)
return 0, xerrors.Errorf("file is opened with %s mode", handle.openMode)
}

readLen, err := irods_fs.ReadDataObject(handle.connection, handle.irodsfilehandle, buffer)
readLen, err := irods_fs.ReadDataObject(handle.connection, handle.irodsFileHandle, buffer)
if readLen > 0 {
handle.offset += int64(readLen)
}
Expand All @@ -149,11 +160,11 @@ func (handle *FileHandle) ReadAt(buffer []byte, offset int64) (int, error) {
defer handle.mutex.Unlock()

if !handle.IsReadMode() {
return 0, xerrors.Errorf("file is opened with %s mode", handle.openmode)
return 0, xerrors.Errorf("file is opened with %s mode", handle.openMode)
}

if handle.offset != offset {
newOffset, err := irods_fs.SeekDataObject(handle.connection, handle.irodsfilehandle, offset, types.SeekSet)
newOffset, err := irods_fs.SeekDataObject(handle.connection, handle.irodsFileHandle, offset, types.SeekSet)
if err != nil {
return 0, err
}
Expand All @@ -165,7 +176,7 @@ func (handle *FileHandle) ReadAt(buffer []byte, offset int64) (int, error) {
}
}

readLen, err := irods_fs.ReadDataObject(handle.connection, handle.irodsfilehandle, buffer)
readLen, err := irods_fs.ReadDataObject(handle.connection, handle.irodsFileHandle, buffer)
if readLen > 0 {
handle.offset += int64(readLen)
}
Expand All @@ -180,10 +191,10 @@ func (handle *FileHandle) Write(data []byte) (int, error) {
defer handle.mutex.Unlock()

if !handle.IsWriteMode() {
return 0, xerrors.Errorf("file is opened with %s mode", handle.openmode)
return 0, xerrors.Errorf("file is opened with %s mode", handle.openMode)
}

err := irods_fs.WriteDataObject(handle.connection, handle.irodsfilehandle, data)
err := irods_fs.WriteDataObject(handle.connection, handle.irodsFileHandle, data)
if err != nil {
return 0, err
}
Expand All @@ -204,11 +215,11 @@ func (handle *FileHandle) WriteAt(data []byte, offset int64) (int, error) {
defer handle.mutex.Unlock()

if !handle.IsWriteMode() {
return 0, xerrors.Errorf("file is opened with %s mode", handle.openmode)
return 0, xerrors.Errorf("file is opened with %s mode", handle.openMode)
}

if handle.offset != offset {
newOffset, err := irods_fs.SeekDataObject(handle.connection, handle.irodsfilehandle, offset, types.SeekSet)
newOffset, err := irods_fs.SeekDataObject(handle.connection, handle.irodsFileHandle, offset, types.SeekSet)
if err != nil {
return 0, err
}
Expand All @@ -220,7 +231,7 @@ func (handle *FileHandle) WriteAt(data []byte, offset int64) (int, error) {
}
}

err := irods_fs.WriteDataObject(handle.connection, handle.irodsfilehandle, data)
err := irods_fs.WriteDataObject(handle.connection, handle.irodsFileHandle, data)
if err != nil {
return 0, err
}
Expand All @@ -235,10 +246,67 @@ func (handle *FileHandle) WriteAt(data []byte, offset int64) (int, error) {
return len(data), nil
}

// LockDataObject locks data object with write lock (exclusive)
func (handle *FileHandle) LockDataObject(wait bool) error {
handle.mutex.Lock()
defer handle.mutex.Unlock()

lockType := types.DataObjectLockTypeWrite
lockCommand := types.DataObjectLockCommandSetLock
if wait {
lockCommand = types.DataObjectLockCommandSetLockWait
}

fileLockHandle, err := irods_fs.LockDataObject(handle.connection, handle.irodsFileHandle.Path, lockType, lockCommand)
if err != nil {
return err
}

handle.irodsFileLockHandle = fileLockHandle

return nil
}

// RLockDataObject locks data object with read lock
func (handle *FileHandle) RLockDataObject(wait bool) error {
handle.mutex.Lock()
defer handle.mutex.Unlock()

lockType := types.DataObjectLockTypeRead
lockCommand := types.DataObjectLockCommandSetLock
if wait {
lockCommand = types.DataObjectLockCommandSetLockWait
}

fileLockHandle, err := irods_fs.LockDataObject(handle.connection, handle.irodsFileHandle.Path, lockType, lockCommand)
if err != nil {
return err
}

handle.irodsFileLockHandle = fileLockHandle

return nil
}

// UnlockDataObject unlocks data object
func (handle *FileHandle) UnlockDataObject() error {
handle.mutex.Lock()
defer handle.mutex.Unlock()

err := irods_fs.UnlockDataObject(handle.connection, handle.irodsFileLockHandle)
if err != nil {
return err
}

handle.irodsFileLockHandle = nil

return nil
}

// preprocessRename should be called before the file is renamed
func (handle *FileHandle) preprocessRename() error {
// first, we need to close the file
err := irods_fs.CloseDataObject(handle.connection, handle.irodsfilehandle)
err := irods_fs.CloseDataObject(handle.connection, handle.irodsFileHandle)

if handle.IsWriteMode() {
handle.filesystem.invalidateCacheForFileUpdate(handle.entry.Path)
Expand All @@ -252,23 +320,23 @@ func (handle *FileHandle) preprocessRename() error {
func (handle *FileHandle) postprocessRename(newPath string, newEntry *Entry) error {
// apply path change
newOpenMode := types.FileOpenModeReadWrite
switch handle.openmode {
switch handle.openMode {
case types.FileOpenModeReadOnly:
newOpenMode = handle.openmode
newOpenMode = handle.openMode
case types.FileOpenModeReadWrite:
newOpenMode = handle.openmode
newOpenMode = handle.openMode
case types.FileOpenModeWriteOnly:
newOpenMode = handle.openmode
newOpenMode = handle.openMode
case types.FileOpenModeWriteTruncate:
newOpenMode = types.FileOpenModeWriteOnly
case types.FileOpenModeAppend:
newOpenMode = handle.openmode
newOpenMode = handle.openMode
case types.FileOpenModeReadAppend:
newOpenMode = handle.openmode
newOpenMode = handle.openMode
}

// reopen
newHandle, offset, err := irods_fs.OpenDataObject(handle.connection, newPath, handle.irodsfilehandle.Resource, string(newOpenMode))
newHandle, offset, err := irods_fs.OpenDataObject(handle.connection, newPath, handle.irodsFileHandle.Resource, string(newOpenMode))
if err != nil {
return err
}
Expand All @@ -285,13 +353,13 @@ func (handle *FileHandle) postprocessRename(newPath string, newEntry *Entry) err
}
}

handle.irodsfilehandle = newHandle
handle.irodsFileHandle = newHandle
handle.entry = newEntry
handle.openmode = newOpenMode
handle.openMode = newOpenMode
return nil
}

// ToString stringifies the object
func (handle *FileHandle) ToString() string {
return fmt.Sprintf("<FileHandle %d %s %s %s>", handle.entry.ID, handle.entry.Type, handle.entry.Name, handle.openmode)
return fmt.Sprintf("<FileHandle %d %s %s %s>", handle.entry.ID, handle.entry.Type, handle.entry.Name, handle.openMode)
}
75 changes: 0 additions & 75 deletions fs/file_lock_handle.go

This file was deleted.

Loading

0 comments on commit 13d5dcf

Please sign in to comment.