// 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
	}
}
Example #2
0
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
}