// Attentez: It is not atomic // If byForce set to false and the destination file exists, an EX_FOLDER_ALREADY_EXIST will be returned func (this *Fs) MvXParalleled(srcName, srcInode, desName, desInode string, byForce bool) error { //Insider.LogD("MvXParalleled start") //defer Insider.LogD("MvXParalleled end") if !CheckValidFilename(srcName) || !CheckValidFilename(desName) { return exception.EX_INVALID_FILENAME } if !byForce && outapi.ForceCheckExist(this.io.CheckExist(GenFileName(desInode, desName))) { return exception.EX_FOLDER_ALREADY_EXIST } var modifiedMeta = FileMeta(map[string]string{ META_PARENT_INODE: desInode, }) //Insider.LogD("MvXParalleled::copy start") if err := this.io.Copy(GenFileName(srcInode, srcName), GenFileName(desInode, desName), modifiedMeta); err != nil { return exception.EX_FILE_NOT_EXIST } //Insider.LogD("MvXParalleled::copy end") var globalError *errorgroup.ErrorAssembly = nil var geLock sync.Mutex var wg sync.WaitGroup var routineToUpdateDesParentMap = func(oriMeta FileMeta) { defer wg.Done() //Insider.LogD("routineToUpdateDesParentMap start") //defer Insider.LogD("routineToUpdateDesParentMap end") if oriMeta == nil { return } { var desParentMap = dvc.GetFD(GenFileName(desInode, FOLDER_MAP), this.io) //Insider.Log("routineToUpdateDesParentMap", "GOT FD") if desParentMap == nil { Secretary.Error("kernel.filesystem::MvXParalleled", "Fail to get foldermap fd for folder "+desInode) geLock.Lock() globalError = errorgroup.AddIn(globalError, exception.EX_IO_ERROR) geLock.Unlock() return } if err := desParentMap.Submit(fc.FastMakeWithMeta(desName, InferFMapMetaFromNNodeMeta(oriMeta))); err != nil { Secretary.Error("kernel.filesystem::MvXParalleled", "Fail to submit foldermap patch for folder "+desInode) desParentMap.Release() geLock.Lock() globalError = errorgroup.AddIn(globalError, err) geLock.Unlock() return } //Insider.Log("routineToUpdateDesParentMap", "SUBMITTED") desParentMap.Release() //Insider.Log("routineToUpdateDesParentMap", "RELEASED") } } var routineToRemoveOldNnode = func() { defer wg.Done() //Insider.LogD("routineToRemoveOldNnode start") //defer Insider.LogD("routineToRemoveOldNnode end") this.io.Delete(GenFileName(srcInode, srcName)) } var routineToUpdateSrcParentMap = func() { defer wg.Done() //Insider.LogD("routineToUpdateSrcParentMap start") //defer Insider.LogD("routineToUpdateSrcParentMap end") { var srcParentMap = dvc.GetFD(GenFileName(srcInode, FOLDER_MAP), this.io) //Insider.Log("routineToUpdateSrcParentMap", "GOT FD") if srcParentMap == nil { Secretary.Error("kernel.filesystem::MvXParalleled", "Fail to get foldermap fd for folder "+srcInode) geLock.Lock() globalError = errorgroup.AddIn(globalError, exception.EX_IO_ERROR) geLock.Unlock() return } if err := srcParentMap.Submit(filetype.FastAntiMake(srcName)); err != nil { Secretary.Error("kernel.filesystem::MvXParalleled", "Fail to submit foldermap patch for folder "+srcInode) srcParentMap.Release() geLock.Lock() globalError = errorgroup.AddIn(globalError, err) geLock.Unlock() return } //Insider.Log("routineToUpdateSrcParentMap", "SUBMITTED") srcParentMap.Release() //Insider.Log("routineToUpdateSrcParentMap", "RELEASED") } } var routineToUpdateDotDot = func() { defer wg.Done() //Insider.LogD("routineToUpdateDotDot start") //defer Insider.LogD("routineToUpdateDotDot end") var dstNnodeMeta, dstFileNnodeOriginal, _ = this.io.Get(GenFileName(desInode, desName)) go routineToUpdateDesParentMap(dstNnodeMeta) var dstFileNnode, _ = dstFileNnodeOriginal.(*filetype.Nnode) if dstFileNnode == nil { Secretary.Error("kernel.filesystem::MvX", "Fail to read nnode "+GenFileName(desInode, desName)+".") geLock.Lock() globalError = errorgroup.AddIn(globalError, exception.EX_IO_ERROR) geLock.Unlock() return } var target = GenFileName(dstFileNnode.DesName, "..") if err := this.io.Put(target, filetype.NewNnode(desInode), nil); err != nil { Secretary.Error("kernel.filesystem::MvX", "Fail to modify .. link for "+dstFileNnode.DesName+".") geLock.Lock() globalError = errorgroup.AddIn(globalError, err) geLock.Unlock() return } else { // Secretary.Log("kernel.filesystem::MvX", "Update file "+target) } } wg.Add(4) // routineToUpdateDesParentMap() is invoked in routineToUpdateDotDot() go routineToRemoveOldNnode() go routineToUpdateSrcParentMap() go routineToUpdateDotDot() wg.Wait() return globalError }
// Attentez: It is not atomic // If byForce set to false and the destination file exists, an EX_FOLDER_ALREADY_EXIST will be returned func (this *Fs) MvX(srcName, srcInode, desName, desInode string, byForce bool) error { // Create a mirror at destination position. // Then, remove the old one. // Third, modify the .. pointer. if !CheckValidFilename(srcName) || !CheckValidFilename(desName) { return exception.EX_INVALID_FILENAME } if !byForce && outapi.ForceCheckExist(this.io.CheckExist(GenFileName(desInode, desName))) { return exception.EX_FOLDER_ALREADY_EXIST } var modifiedMeta = FileMeta(map[string]string{ META_PARENT_INODE: desInode, }) if err := this.io.Copy(GenFileName(srcInode, srcName), GenFileName(desInode, desName), modifiedMeta); err != nil { return exception.EX_FILE_NOT_EXIST } // remove the old one. this.io.Delete(GenFileName(srcInode, srcName)) { var srcParentMap = dvc.GetFD(GenFileName(srcInode, FOLDER_MAP), this.io) if srcParentMap == nil { Secretary.Error("kernel.filesystem::MvX", "Fail to get foldermap fd for folder "+srcInode) return exception.EX_IO_ERROR } if err := srcParentMap.Submit(filetype.FastAntiMake(srcName)); err != nil { Secretary.Error("kernel.filesystem::MvX", "Fail to submit foldermap patch for folder "+srcInode) srcParentMap.Release() return err } srcParentMap.Release() } // modify the .. pointer var dstMeta, dstFileNnodeOriginal, _ = this.io.Get(GenFileName(desInode, desName)) var dstFileNnode, _ = dstFileNnodeOriginal.(*filetype.Nnode) if dstFileNnode == nil { Secretary.Error("kernel.filesystem::MvX", "Fail to read nnode "+GenFileName(desInode, desName)+".") return exception.EX_IO_ERROR } { var desParentMap = dvc.GetFD(GenFileName(desInode, FOLDER_MAP), this.io) if desParentMap == nil { Secretary.Error("kernel.filesystem::MvX", "Fail to get foldermap fd for folder "+desInode) return exception.EX_IO_ERROR } if err := desParentMap.Submit(fc.FastMakeWithMeta(desName, InferFMapMetaFromNNodeMeta(dstMeta))); err != nil { Secretary.Error("kernel.filesystem::MvX", "Fail to submit foldermap patch for folder "+desInode) desParentMap.Release() return err } desParentMap.Release() } var target = GenFileName(dstFileNnode.DesName, "..") if err := this.io.Put(target, filetype.NewNnode(desInode), nil); err != nil { Secretary.Error("kernel.filesystem::MvX", "Fail to modify .. link for "+dstFileNnode.DesName+".") return err } else { //Secretary.Log("kernel.filesystem::MvX", "Update file "+target) } // ALL DONE! return nil }