// All the folder will be removed. No matter if it is empty or not. // Move it to the trash func (this *Fs) RmParalleled(foldername string, frominode string) error { if tsinode := this.GetTrashInode(); tsinode == "" { Secretary.ErrorD("IO: " + this.io.GenerateUniqueID() + " has an invalid trashbox, which leads to removing failure.") return exception.EX_TRASHBOX_NOT_INITED } else { return this.MvXParalleled(foldername, frominode, uniqueid.GenGlobalUniqueNameWithTag("removed"), tsinode, true) // TODO: logging the original position for recovery } }
func (this *Fs) Put(filename string, frominode string, meta FileMeta /*=nil*/, dataSource io.Reader) (error, string) { var targetFileinode string var oldOriName string if filename != "" { // CREATE MODE if !CheckValidFilename(filename) { return exception.EX_INVALID_FILENAME, "" } // set inode targetFileinode = uniqueid.GenGlobalUniqueNameWithTag("Stream") } else { // OVERRIDE MODE var oldMeta, err = this.io.Getinfo(frominode) if oldMeta == nil { if err != nil { return err, "" } return exception.EX_FILE_NOT_EXIST, "" } oldOriName = oldMeta[META_ORIGINAL_NAME] targetFileinode = frominode } // set object node if meta == nil { meta = NewMeta() } meta = meta.Clone() meta[METAKEY_TYPE] = STREAM_TYPE if filename != "" { meta[META_ORIGINAL_NAME] = filename } else { meta[META_ORIGINAL_NAME] = oldOriName } if wc, err := this.io.PutStream(targetFileinode, meta); err != nil { Secretary.Error("kernel.filesystem::Put", "Put stream for new file "+GenFileName(frominode, filename)+" failed.") return err, targetFileinode } else { if _, err2 := io.Copy(wc, dataSource); err2 != nil { wc.Close() Secretary.Error("kernel.filesystem::Put", "Piping stream for new file "+GenFileName(frominode, filename)+" failed.") return err2, targetFileinode } if err2 := wc.Close(); err2 != nil { Secretary.Error("kernel.filesystem::Put", "Close writer for new file "+GenFileName(frominode, filename)+" failed.") return err2, targetFileinode } } if filename != "" { // CREATE MODE. Set its parent node's foldermap and write the nnode concurrently var currentHeader, terr = this.io.GetinfoX(targetFileinode) if currentHeader == nil { if terr != nil { Secretary.Warn("kernel.filesystem::Put", "Fail to refetch supposed-to-be file meta: "+targetFileinode+". Error is "+terr.Error()) } else { Secretary.Warn("kernel.filesystem::Put", "Fail to refetch supposed-to-be file meta: "+targetFileinode+". The file seems to be non-existence.") } return exception.EX_CONCURRENT_CHAOS, targetFileinode } //fmt.Println(currentHeader) var pointedMeta = ConvertFileHeaderToNNodeMeta(currentHeader) var metaToSet = pointedMeta metaToSet[META_PARENT_INODE] = frominode metaToSet[META_INODE_TYPE] = META_INODE_TYPE_FILE var wg = sync.WaitGroup{} var globalError *egg.ErrorAssembly = nil var geLock sync.Mutex wg.Add(2) go (func() { defer wg.Done() // Write the nnode if err := this.io.Put(GenFileName(frominode, filename), filetype.NewNnode(targetFileinode), metaToSet); err != nil { Secretary.Warn("kernel.filesystem::Put", "Put nnode for new file "+GenFileName(frominode, filename)+" failed.") geLock.Lock() globalError = egg.AddIn(globalError, err) geLock.Unlock() return } })() go (func() { // update parentNode's foldermap defer wg.Done() var parentFD = dvc.GetFD(GenFileName(frominode, FOLDER_MAP), this.io) if parentFD == nil { Secretary.Error("kernel.filesystem::Put", "Get FD for "+GenFileName(frominode, FOLDER_MAP)+" failed.") geLock.Lock() globalError = egg.AddIn(globalError, exception.EX_INDEX_ERROR) geLock.Unlock() return } if err := parentFD.Submit(fc.FastMakeWithMeta(filename, InferFMapMetaFromNNodeMeta(metaToSet))); err != nil { Secretary.Error("kernel.filesystem::Put", "Submit patch for "+GenFileName(frominode, filename)+" failed: "+err.Error()) parentFD.Release() geLock.Lock() globalError = egg.AddIn(globalError, exception.EX_INDEX_ERROR) geLock.Unlock() return } parentFD.Release() })() wg.Wait() if globalError != nil { return globalError, targetFileinode } } return nil, targetFileinode }