github.com/cyverse/go-irodsclient@v0.13.2/fs/fs_bulk.go (about)

     1  package fs
     2  
     3  import (
     4  	"bytes"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	"github.com/cyverse/go-irodsclient/irods/common"
     9  	irods_fs "github.com/cyverse/go-irodsclient/irods/fs"
    10  	"github.com/cyverse/go-irodsclient/irods/types"
    11  	"github.com/cyverse/go-irodsclient/irods/util"
    12  	"golang.org/x/xerrors"
    13  )
    14  
    15  // DownloadFile downloads a file to local
    16  func (fs *FileSystem) DownloadFile(irodsPath string, resource string, localPath string, callback common.TrackerCallBack) error {
    17  	irodsSrcPath := util.GetCorrectIRODSPath(irodsPath)
    18  	localDestPath := util.GetCorrectLocalPath(localPath)
    19  
    20  	localFilePath := localDestPath
    21  
    22  	srcStat, err := fs.Stat(irodsSrcPath)
    23  	if err != nil {
    24  		return xerrors.Errorf("failed to stat for path %s: %w", irodsSrcPath, types.NewFileNotFoundError(irodsSrcPath))
    25  	}
    26  
    27  	if srcStat.Type == DirectoryEntry {
    28  		return xerrors.Errorf("cannot download a collection %s", irodsSrcPath)
    29  	}
    30  
    31  	destStat, err := os.Stat(localDestPath)
    32  	if err != nil {
    33  		if os.IsNotExist(err) {
    34  			// file not exists, it's a file
    35  			// pass
    36  		} else {
    37  			return err
    38  		}
    39  	} else {
    40  		if destStat.IsDir() {
    41  			irodsFileName := util.GetIRODSPathFileName(irodsSrcPath)
    42  			localFilePath = filepath.Join(localDestPath, irodsFileName)
    43  		}
    44  	}
    45  
    46  	return irods_fs.DownloadDataObject(fs.ioSession, irodsSrcPath, resource, localFilePath, srcStat.Size, callback)
    47  }
    48  
    49  // DownloadFileResumable downloads a file to local with support of transfer resume
    50  func (fs *FileSystem) DownloadFileResumable(irodsPath string, resource string, localPath string, callback common.TrackerCallBack) error {
    51  	irodsSrcPath := util.GetCorrectIRODSPath(irodsPath)
    52  	localDestPath := util.GetCorrectLocalPath(localPath)
    53  
    54  	localFilePath := localDestPath
    55  
    56  	srcStat, err := fs.Stat(irodsSrcPath)
    57  	if err != nil {
    58  		return xerrors.Errorf("failed to stat for path %s: %w", irodsSrcPath, types.NewFileNotFoundError(irodsSrcPath))
    59  	}
    60  
    61  	if srcStat.Type == DirectoryEntry {
    62  		return xerrors.Errorf("cannot download a collection %s", irodsSrcPath)
    63  	}
    64  
    65  	destStat, err := os.Stat(localDestPath)
    66  	if err != nil {
    67  		if os.IsNotExist(err) {
    68  			// file not exists, it's a file
    69  			// pass
    70  		} else {
    71  			return err
    72  		}
    73  	} else {
    74  		if destStat.IsDir() {
    75  			irodsFileName := util.GetIRODSPathFileName(irodsSrcPath)
    76  			localFilePath = filepath.Join(localDestPath, irodsFileName)
    77  		}
    78  	}
    79  
    80  	return irods_fs.DownloadDataObjectResumable(fs.ioSession, irodsSrcPath, resource, localFilePath, srcStat.Size, callback)
    81  }
    82  
    83  // DownloadFileToBuffer downloads a file to buffer
    84  func (fs *FileSystem) DownloadFileToBuffer(irodsPath string, resource string, buffer bytes.Buffer, callback common.TrackerCallBack) error {
    85  	irodsSrcPath := util.GetCorrectIRODSPath(irodsPath)
    86  
    87  	srcStat, err := fs.Stat(irodsSrcPath)
    88  	if err != nil {
    89  		return xerrors.Errorf("failed to stat for path %s: %w", irodsSrcPath, types.NewFileNotFoundError(irodsSrcPath))
    90  	}
    91  
    92  	if srcStat.Type == DirectoryEntry {
    93  		return xerrors.Errorf("cannot download a collection %s", irodsSrcPath)
    94  	}
    95  
    96  	return irods_fs.DownloadDataObjectToBuffer(fs.ioSession, irodsSrcPath, resource, buffer, srcStat.Size, callback)
    97  }
    98  
    99  // DownloadFileParallel downloads a file to local in parallel
   100  func (fs *FileSystem) DownloadFileParallel(irodsPath string, resource string, localPath string, taskNum int, callback common.TrackerCallBack) error {
   101  	irodsSrcPath := util.GetCorrectIRODSPath(irodsPath)
   102  	localDestPath := util.GetCorrectLocalPath(localPath)
   103  
   104  	localFilePath := localDestPath
   105  
   106  	srcStat, err := fs.Stat(irodsSrcPath)
   107  	if err != nil {
   108  		return xerrors.Errorf("failed to stat for path %s: %w", irodsSrcPath, types.NewFileNotFoundError(irodsSrcPath))
   109  	}
   110  
   111  	if srcStat.Type == DirectoryEntry {
   112  		return xerrors.Errorf("cannot download a collection %s", irodsSrcPath)
   113  	}
   114  
   115  	destStat, err := os.Stat(localDestPath)
   116  	if err != nil {
   117  		if os.IsNotExist(err) {
   118  			// file not exists, it's a file
   119  			// pass
   120  		} else {
   121  			return err
   122  		}
   123  	} else {
   124  		if destStat.IsDir() {
   125  			irodsFileName := util.GetIRODSPathFileName(irodsSrcPath)
   126  			localFilePath = filepath.Join(localDestPath, irodsFileName)
   127  		}
   128  	}
   129  
   130  	return irods_fs.DownloadDataObjectParallel(fs.ioSession, irodsSrcPath, resource, localFilePath, srcStat.Size, taskNum, callback)
   131  }
   132  
   133  // DownloadFileParallelResumable downloads a file to local in parallel with support of transfer resume
   134  func (fs *FileSystem) DownloadFileParallelResumable(irodsPath string, resource string, localPath string, taskNum int, callback common.TrackerCallBack) error {
   135  	irodsSrcPath := util.GetCorrectIRODSPath(irodsPath)
   136  	localDestPath := util.GetCorrectLocalPath(localPath)
   137  
   138  	localFilePath := localDestPath
   139  
   140  	srcStat, err := fs.Stat(irodsSrcPath)
   141  	if err != nil {
   142  		return xerrors.Errorf("failed to stat for path %s: %w", irodsSrcPath, types.NewFileNotFoundError(irodsSrcPath))
   143  	}
   144  
   145  	if srcStat.Type == DirectoryEntry {
   146  		return xerrors.Errorf("cannot download a collection %s", irodsSrcPath)
   147  	}
   148  
   149  	destStat, err := os.Stat(localDestPath)
   150  	if err != nil {
   151  		if os.IsNotExist(err) {
   152  			// file not exists, it's a file
   153  			// pass
   154  		} else {
   155  			return err
   156  		}
   157  	} else {
   158  		if destStat.IsDir() {
   159  			irodsFileName := util.GetIRODSPathFileName(irodsSrcPath)
   160  			localFilePath = filepath.Join(localDestPath, irodsFileName)
   161  		}
   162  	}
   163  
   164  	return irods_fs.DownloadDataObjectParallelResumable(fs.ioSession, irodsSrcPath, resource, localFilePath, srcStat.Size, taskNum, callback)
   165  }
   166  
   167  // UploadFile uploads a local file to irods
   168  func (fs *FileSystem) UploadFile(localPath string, irodsPath string, resource string, replicate bool, callback common.TrackerCallBack) error {
   169  	localSrcPath := util.GetCorrectLocalPath(localPath)
   170  	irodsDestPath := util.GetCorrectIRODSPath(irodsPath)
   171  
   172  	irodsFilePath := irodsDestPath
   173  
   174  	stat, err := os.Stat(localSrcPath)
   175  	if err != nil {
   176  		if os.IsNotExist(err) {
   177  			// file not exists
   178  			return xerrors.Errorf("failed to stat for local path %s: %w", localSrcPath, types.NewFileNotFoundError(localSrcPath))
   179  		}
   180  		return err
   181  	}
   182  
   183  	if stat.IsDir() {
   184  		return xerrors.Errorf("failed to find a file for local path %s, the path is for a directory: %w", localSrcPath, types.NewFileNotFoundError(localSrcPath))
   185  	}
   186  
   187  	entry, err := fs.Stat(irodsDestPath)
   188  	if err != nil {
   189  		if !types.IsFileNotFoundError(err) {
   190  			return err
   191  		}
   192  	} else {
   193  		switch entry.Type {
   194  		case FileEntry:
   195  			// do nothing
   196  		case DirectoryEntry:
   197  			localFileName := filepath.Base(localSrcPath)
   198  			irodsFilePath = util.MakeIRODSPath(irodsDestPath, localFileName)
   199  		default:
   200  			return xerrors.Errorf("unknown entry type %s", entry.Type)
   201  		}
   202  	}
   203  
   204  	err = irods_fs.UploadDataObject(fs.ioSession, localSrcPath, irodsFilePath, resource, replicate, callback)
   205  	if err != nil {
   206  		return err
   207  	}
   208  
   209  	fs.invalidateCacheForFileCreate(irodsFilePath)
   210  	fs.cachePropagation.PropagateFileCreate(irodsFilePath)
   211  	return nil
   212  }
   213  
   214  // UploadFileFromBuffer uploads buffer data to irods
   215  func (fs *FileSystem) UploadFileFromBuffer(buffer bytes.Buffer, irodsPath string, resource string, replicate bool, callback common.TrackerCallBack) error {
   216  	irodsDestPath := util.GetCorrectIRODSPath(irodsPath)
   217  
   218  	irodsFilePath := irodsDestPath
   219  
   220  	entry, err := fs.Stat(irodsDestPath)
   221  	if err != nil {
   222  		if !types.IsFileNotFoundError(err) {
   223  			return err
   224  		}
   225  	} else {
   226  		switch entry.Type {
   227  		case FileEntry:
   228  			// do nothing
   229  		case DirectoryEntry:
   230  			return xerrors.Errorf("invalid entry type %s. Destination must be a file", entry.Type)
   231  		default:
   232  			return xerrors.Errorf("unknown entry type %s", entry.Type)
   233  		}
   234  	}
   235  
   236  	err = irods_fs.UploadDataObjectFromBuffer(fs.ioSession, buffer, irodsFilePath, resource, replicate, callback)
   237  	if err != nil {
   238  		return err
   239  	}
   240  
   241  	fs.invalidateCacheForFileCreate(irodsFilePath)
   242  	fs.cachePropagation.PropagateFileCreate(irodsFilePath)
   243  	return nil
   244  }
   245  
   246  // UploadFileParallel uploads a local file to irods in parallel
   247  func (fs *FileSystem) UploadFileParallel(localPath string, irodsPath string, resource string, taskNum int, replicate bool, callback common.TrackerCallBack) error {
   248  	localSrcPath := util.GetCorrectLocalPath(localPath)
   249  	irodsDestPath := util.GetCorrectIRODSPath(irodsPath)
   250  
   251  	irodsFilePath := irodsDestPath
   252  
   253  	srcStat, err := os.Stat(localSrcPath)
   254  	if err != nil {
   255  		if os.IsNotExist(err) {
   256  			// file not exists
   257  			return xerrors.Errorf("failed to stat for local path %s: %w", localSrcPath, types.NewFileNotFoundError(localSrcPath))
   258  		}
   259  		return err
   260  	}
   261  
   262  	if srcStat.IsDir() {
   263  		return xerrors.Errorf("failed to find a file for local path %s, the path is for a directory: %w", localSrcPath, types.NewFileNotFoundError(localSrcPath))
   264  	}
   265  
   266  	destStat, err := fs.Stat(irodsDestPath)
   267  	if err != nil {
   268  		if !types.IsFileNotFoundError(err) {
   269  			return err
   270  		}
   271  	} else {
   272  		switch destStat.Type {
   273  		case FileEntry:
   274  			// do nothing
   275  		case DirectoryEntry:
   276  			localFileName := filepath.Join(localSrcPath)
   277  			irodsFilePath = util.MakeIRODSPath(irodsDestPath, localFileName)
   278  		default:
   279  			return xerrors.Errorf("unknown entry type %s", destStat.Type)
   280  		}
   281  	}
   282  
   283  	err = irods_fs.UploadDataObjectParallel(fs.ioSession, localSrcPath, irodsFilePath, resource, taskNum, replicate, callback)
   284  	if err != nil {
   285  		return err
   286  	}
   287  
   288  	fs.invalidateCacheForFileCreate(irodsFilePath)
   289  	fs.cachePropagation.PropagateFileCreate(irodsFilePath)
   290  	return nil
   291  }