Ejemplo n.º 1
0
// If the file exist and forceMake==false, an error EX_FOLDER_ALREADY_EXIST will be returned
func (this *Fs) MkdirParalleled(foldername string, frominode string, forceMake bool) error {
	if !CheckValidFilename(foldername) {
		return exception.EX_INVALID_FILENAME
	}

	// nnodeName: parentInode::foldername
	var nnodeName = GenFileName(frominode, foldername)
	if !forceMake {
		if tmeta, _ := this.io.Getinfo(nnodeName); tmeta != nil {
			return exception.EX_FOLDER_ALREADY_EXIST
		}
	}
	var newDomainname = uniqueid.GenGlobalUniqueName()

	var globalError *errorgroup.ErrorAssembly = nil
	var geLock sync.Mutex
	var wg sync.WaitGroup
	// create target inode and write parent folder map
	var routineToCreateInode = func() {
		defer wg.Done()

		var newNnode = filetype.NewNnode(newDomainname)
		var initMeta = FileMeta(map[string]string{
			META_INODE_TYPE:   META_INODE_TYPE_FOLDER,
			META_PARENT_INODE: frominode,
		})
		if err := this.io.Put(nnodeName, newNnode, initMeta); err != nil {
			geLock.Lock()
			globalError = errorgroup.AddIn(globalError, err)
			geLock.Unlock()
			return
		}

		// submit patch to parent folder's map
		{
			var parentFolderMapFD = dvc.GetFD(GenFileName(frominode, FOLDER_MAP), this.io)
			if parentFolderMapFD == nil {
				Secretary.Error("kernel.filesystem::MkdirParalleled", "Fail to create foldermap fd for new folder "+nnodeName+"'s parent map'")
				geLock.Lock()
				globalError = errorgroup.AddIn(globalError, exception.EX_IO_ERROR)
				geLock.Unlock()
				return
			}
			if err := parentFolderMapFD.Submit(fc.FastMakeFolderPatch(foldername)); err != nil {
				Secretary.Error("kernel.filesystem::MkdirParalleled", "Fail to submit patch to foldermap for new folder "+nnodeName+"'s parent map'")
				parentFolderMapFD.Release()
				geLock.Lock()
				globalError = errorgroup.AddIn(globalError, err)
				geLock.Unlock()
				return
			}
			parentFolderMapFD.Release()
		}
	}

	var initMetaSelf = FileMeta(map[string]string{
		META_INODE_TYPE:   META_INODE_TYPE_FOLDER,
		META_PARENT_INODE: newDomainname,
	})
	var routineToCreateDotDot = func() {
		defer wg.Done()

		if err := this.io.Put(GenFileName(newDomainname, ".."), filetype.NewNnode(frominode), initMetaSelf); err != nil {
			Secretary.Error("kernel.filesystem::MkdirParalleled", "Fail to create .. link for new folder "+nnodeName+".")
			geLock.Lock()
			globalError = errorgroup.AddIn(globalError, err)
			geLock.Unlock()
			return
		}
	}
	var routineToCreateDot = func() {
		defer wg.Done()

		if err := this.io.Put(GenFileName(newDomainname, "."), filetype.NewNnode(newDomainname), initMetaSelf); err != nil {
			Secretary.Error("kernel.filesystem::MkdirParalleled", "Fail to create . link for new folder "+nnodeName+".")
			geLock.Lock()
			globalError = errorgroup.AddIn(globalError, err)
			geLock.Unlock()
			return
		}
	}

	var routineToWriteNewMap = func() {
		defer wg.Done()

		{
			var newFolderMapFD = dvc.GetFD(GenFileName(newDomainname, FOLDER_MAP), this.io)
			if newFolderMapFD == nil {
				Secretary.Error("kernel.filesystem::MkdirParalleled", "Fail to create foldermap fd for new folder "+nnodeName+".")
				geLock.Lock()
				globalError = errorgroup.AddIn(globalError, exception.EX_IO_ERROR)
				geLock.Unlock()
				return
			}
			if err := newFolderMapFD.Submit(fc.FastMakeFolderPatch(".", "..")); err != nil {
				Secretary.Error("kernel.filesystem::MkdirParalleled", "Fail to init foldermap for new folder "+nnodeName+".")
				newFolderMapFD.Release()
				geLock.Lock()
				globalError = errorgroup.AddIn(globalError, err)
				geLock.Unlock()
				return
			}
			newFolderMapFD.Release()
		}
	}

	wg.Add(4)
	go routineToCreateInode()
	go routineToCreateDotDot()
	go routineToCreateDot()
	go routineToWriteNewMap()
	wg.Wait()

	// NOW All the routines have returned and globalError stores all the errors
	// TODO: consider clearing roll-back

	return globalError
}
Ejemplo n.º 2
0
// If the file exist and forceMake==false, an error EX_FOLDER_ALREADY_EXIST will be returned
func (this *Fs) Mkdir(foldername string, frominode string, forceMake bool) error {
	if !CheckValidFilename(foldername) {
		return exception.EX_INVALID_FILENAME
	}

	// nnodeName: parentInode::foldername
	var nnodeName = GenFileName(frominode, foldername)
	if !forceMake {
		if tmeta, _ := this.io.Getinfo(nnodeName); tmeta != nil {
			return exception.EX_FOLDER_ALREADY_EXIST
		}
	}

	// newDomainname: <GENERATED>
	var newDomainname = uniqueid.GenGlobalUniqueName()
	var newNnode = filetype.NewNnode(newDomainname)
	var initMeta = FileMeta(map[string]string{
		META_INODE_TYPE:   META_INODE_TYPE_FOLDER,
		META_PARENT_INODE: frominode,
	})
	if err := this.io.Put(nnodeName, newNnode, initMeta); err != nil {
		return err
	}
	// initialize two basic element
	var initMetaSelf = FileMeta(map[string]string{
		META_INODE_TYPE:   META_INODE_TYPE_FOLDER,
		META_PARENT_INODE: newDomainname,
	})
	if err := this.io.Put(GenFileName(newDomainname, ".."), filetype.NewNnode(frominode), initMetaSelf); err != nil {
		Secretary.Error("kernel.filesystem::Mkdir", "Fail to create .. link for new folder "+nnodeName+".")
		return err
	}

	if err := this.io.Put(GenFileName(newDomainname, "."), filetype.NewNnode(newDomainname), initMetaSelf); err != nil {
		Secretary.Error("kernel.filesystem::Mkdir", "Fail to create . link for new folder "+nnodeName+".")
		return err
	}

	// write new folder's map
	{
		var newFolderMapFD = dvc.GetFD(GenFileName(newDomainname, FOLDER_MAP), this.io)
		if newFolderMapFD == nil {
			Secretary.Error("kernel.filesystem::Mkdir", "Fail to create foldermap fd for new folder "+nnodeName+".")
			return exception.EX_IO_ERROR
		}
		if err := newFolderMapFD.Submit(fc.FastMakeFolderPatch(".", "..")); err != nil {
			Secretary.Error("kernel.filesystem::Mkdir", "Fail to init foldermap for new folder "+nnodeName+".")
			newFolderMapFD.Release()
			return err
		}
		newFolderMapFD.Release()
	}

	// submit patch to parent folder's map
	{
		var parentFolderMapFD = dvc.GetFD(GenFileName(frominode, FOLDER_MAP), this.io)
		if parentFolderMapFD == nil {
			Secretary.Error("kernel.filesystem::Mkdir", "Fail to create foldermap fd for new folder "+nnodeName+"'s parent map'")
			return exception.EX_IO_ERROR
		}
		if err := parentFolderMapFD.Submit(fc.FastMakeFolderPatch(foldername)); err != nil {
			Secretary.Error("kernel.filesystem::Mkdir", "Fail to submit patch to foldermap for new folder "+nnodeName+"'s parent map'")
			parentFolderMapFD.Release()
			return err
		}
		parentFolderMapFD.Release()
	}

	return nil
}