// ReadBytes reads bytes from a data object at the specified position and length, returns []byte slice and error. func (obj *DataObj) ReadBytes(pos int64, length int) ([]byte, error) { if er := obj.init(); er != nil { return nil, er } var ( buffer C.bytesBuf_t err *C.char bytesRead C.int ) if er := obj.LSeek(pos); er != nil { return nil, er } ccon := obj.con.GetCcon() defer obj.con.ReturnCcon(ccon) if status := C.gorods_read_dataobject(obj.chandle, C.rodsLong_t(length), &buffer, &bytesRead, ccon, &err); status != 0 { return nil, newError(Fatal, fmt.Sprintf("iRODS ReadBytes DataObject Failed: %v, %v", obj.path, C.GoString(err))) } buf := unsafe.Pointer(buffer.buf) defer C.free(buf) data := C.GoBytes(buf, bytesRead) return data, nil }
// Put reads the entire file from localPath and adds it the collection, using the options specified. func (col *Collection) Put(localPath string, opts DataObjOptions) (*DataObj, error) { var ( errMsg *C.char force int resource *C.char ) if opts.Force { force = 1 } else { force = 0 } if opts.Resource != nil { switch opts.Resource.(type) { case string: resource = C.CString(opts.Resource.(string)) case *Resource: r := opts.Resource.(*Resource) resource = C.CString(r.Name()) default: return nil, newError(Fatal, fmt.Sprintf("Wrong variable type passed in Resource field")) } } else { resource = C.CString("") } if opts.Name == "" { opts.Name = filepath.Base(localPath) } path := C.CString(col.path + "/" + opts.Name) cLocalPath := C.CString(localPath) defer C.free(unsafe.Pointer(path)) defer C.free(unsafe.Pointer(resource)) defer C.free(unsafe.Pointer(cLocalPath)) ccon := col.con.GetCcon() if status := C.gorods_put_dataobject(cLocalPath, path, C.rodsLong_t(opts.Size), C.int(opts.Mode), C.int(force), resource, ccon, &errMsg); status != 0 { col.con.ReturnCcon(ccon) return nil, newError(Fatal, fmt.Sprintf("iRODS Put DataObject Failed: %v, Does the file already exist?", C.GoString(errMsg))) } col.con.ReturnCcon(ccon) if err := col.Refresh(); err != nil { return nil, err } if do, err := getDataObj(C.GoString(path), col.con); err != nil { return nil, err } else { return do, nil } }
// ReadChunk reads the entire data object in chunks (size of chunk specified by size parameter), passing the data into a callback function for each chunk. Use this to read/write large files. func (obj *DataObj) ReadChunk(size int64, callback func([]byte)) error { if er := obj.init(); er != nil { return er } var ( buffer C.bytesBuf_t err *C.char bytesRead C.int ) if er := obj.LSeek(0); er != nil { return er } for obj.offset < obj.size { ccon := obj.con.GetCcon() if status := C.gorods_read_dataobject(obj.chandle, C.rodsLong_t(size), &buffer, &bytesRead, ccon, &err); status != 0 { obj.con.ReturnCcon(ccon) return newError(Fatal, fmt.Sprintf("iRODS Read DataObject Failed: %v, %v", obj.path, C.GoString(err))) } obj.con.ReturnCcon(ccon) buf := unsafe.Pointer(buffer.buf) chunk := C.GoBytes(buf, bytesRead) C.free(buf) callback(chunk) if er := obj.LSeek(obj.offset + size); er != nil { return er } } if er := obj.LSeek(0); er != nil { return er } return obj.Close() }
// LSeek sets the read/write offset pointer of a data object, returns error func (obj *DataObj) LSeek(offset int64) error { if er := obj.init(); er != nil { return er } var ( err *C.char ) ccon := obj.con.GetCcon() defer obj.con.ReturnCcon(ccon) if status := C.gorods_lseek_dataobject(obj.chandle, C.rodsLong_t(offset), ccon, &err); status != 0 { return newError(Fatal, fmt.Sprintf("iRODS LSeek DataObject Failed: %v, %v", obj.path, C.GoString(err))) } obj.offset = offset return nil }
// Backup is similar to Replicate. In backup mode, if a good copy already exists in this resource group or resource, don't make another one. func (obj *DataObj) Backup(targetResource interface{}, opts DataObjOptions) error { var ( err *C.char resourceStr string ) switch targetResource.(type) { case string: resourceStr = targetResource.(string) case *Resource: resourceStr = (targetResource.(*Resource)).Name() default: return newError(Fatal, fmt.Sprintf("Unknown type passed as targetResource")) } cPath := C.CString(obj.Path()) cResource := C.CString(resourceStr) defer C.free(unsafe.Pointer(cPath)) defer C.free(unsafe.Pointer(cResource)) ccon := obj.con.GetCcon() defer obj.con.ReturnCcon(ccon) if status := C.gorods_repl_dataobject(ccon, cPath, cResource, C.int(1), C.int(opts.Mode), C.rodsLong_t(opts.Size), &err); status != 0 { return newError(Fatal, fmt.Sprintf("iRODS Backup Failed: %v, %v", obj.path, C.GoString(err))) } return nil }