diff --git a/go/filer/directory_in_map.go b/go/filer/directory_in_map.go index d288f3502..9c2ecdf80 100644 --- a/go/filer/directory_in_map.go +++ b/go/filer/directory_in_map.go @@ -81,7 +81,11 @@ func (dm *DirectoryManagerInMap) processEachLine(line string) error { return e } case "mov": - if e := dm.MoveUnderDirectory(parts[1], parts[2]); e != nil { + newName := "" + if len(parts) >= 4 { + newName = parts[3] + } + if e := dm.MoveUnderDirectory(parts[1], parts[2], newName); e != nil { return e } case "del": @@ -188,7 +192,7 @@ func (dm *DirectoryManagerInMap) MakeDirectory(dirPath string) (DirectoryId, err return dir.Id, nil } -func (dm *DirectoryManagerInMap) MoveUnderDirectory(oldDirPath string, newParentDirPath string) error { +func (dm *DirectoryManagerInMap) MoveUnderDirectory(oldDirPath string, newParentDirPath string, newName string) error { oldDir, oe := dm.findDirectory(oldDirPath) if oe != nil { return oe @@ -197,10 +201,14 @@ func (dm *DirectoryManagerInMap) MoveUnderDirectory(oldDirPath string, newParent if pe != nil { return pe } + dm.log("mov", oldDirPath, newParentDirPath, newName) delete(oldDir.Parent.SubDirectories, oldDir.Name) - parentDir.SubDirectories[oldDir.Name] = oldDir + if newName == "" { + newName = oldDir.Name + } + parentDir.SubDirectories[newName] = oldDir + oldDir.Name = newName oldDir.Parent = parentDir - dm.log("mov", oldDirPath, newParentDirPath) return nil } diff --git a/go/filer/directory_test.go b/go/filer/directory_test.go index bfd1493e5..40c53755b 100644 --- a/go/filer/directory_test.go +++ b/go/filer/directory_test.go @@ -7,38 +7,44 @@ import ( ) func TestDirectory(t *testing.T) { - { - dm, _ := NewDirectoryManagerInMap("/tmp/dir.log") - dm.MakeDirectory("/a/b/c") - dm.MakeDirectory("/a/b/d") - dm.MakeDirectory("/a/b/e") - dm.MakeDirectory("/a/b/e/f") - dm.MakeDirectory("/a/b/e/f/g") - dm.MoveUnderDirectory("/a/b/e/f/g", "/a/b") - dm.MakeDirectory("/a/b/g/h/i") - dm.DeleteDirectory("/a/b/e/f") - dm.DeleteDirectory("/a/b/e") - dirNames, _ := dm.ListDirectories("/a/b/e") - for _, v := range dirNames { - println("sub1 dir:", v.Name, "id", v.Id) + dm, _ := NewDirectoryManagerInMap("/tmp/dir.log") + defer func() { + if true { + os.Remove("/tmp/dir.log") } - dm.logFile.Close() + }() + dm.MakeDirectory("/a/b/c") + dm.MakeDirectory("/a/b/d") + dm.MakeDirectory("/a/b/e") + dm.MakeDirectory("/a/b/e/f") + dm.MakeDirectory("/a/b/e/f/g") + dm.MoveUnderDirectory("/a/b/e/f/g", "/a/b") + if _, err := dm.FindDirectory("/a/b/e/f/g"); err == nil { + t.Fatal("/a/b/e/f/g should not exist any more after moving") + } + if _, err := dm.FindDirectory("/a/b/g"); err != nil { + t.Fatal("/a/b/g should exist after moving") + } + dm.MakeDirectory("/a/b/g/h/i") + dm.DeleteDirectory("/a/b/e/f") + dm.DeleteDirectory("/a/b/e") + dirNames, _ := dm.ListDirectories("/a/b/e") + for _, v := range dirNames { + println("sub1 dir:", v.Name, "id", v.Id) + } + dm.logFile.Close() - var path []string - printTree(dm.Root, path) + var path []string + printTree(dm.Root, path) - dm2, e := NewDirectoryManagerInMap("/tmp/dir.log") - if e != nil { - println("load error", e.Error()) - } - if !compare(dm.Root, dm2.Root) { - t.Fatal("restored dir not the same!") - } - printTree(dm2.Root, path) + dm2, e := NewDirectoryManagerInMap("/tmp/dir.log") + if e != nil { + println("load error", e.Error()) } - if true { - os.Remove("/tmp/dir.log") + if !compare(dm.Root, dm2.Root) { + t.Fatal("restored dir not the same!") } + printTree(dm2.Root, path) } func printTree(node *DirectoryEntryInMap, path []string) { diff --git a/go/filer/filer.go b/go/filer/filer.go index 8d2da901b..de877fc1f 100644 --- a/go/filer/filer.go +++ b/go/filer/filer.go @@ -12,8 +12,10 @@ type FileEntry struct { type Filer interface { CreateFile(filePath string, fid string) (err error) FindFile(filePath string) (fid string, err error) + FindDirectory(dirPath string) (dirId DirectoryId, err error) ListDirectories(dirPath string) (dirs []DirectoryEntry, err error) ListFiles(dirPath string, lastFileName string, limit int) (files []FileEntry, err error) DeleteDirectory(dirPath string, recursive bool) (err error) DeleteFile(filePath string) (fid string, err error) + Move(fromPath string, toPath string) (err error) } diff --git a/go/filer/filer_embedded.go b/go/filer/filer_embedded.go index 2a13805e9..a3b64d37b 100644 --- a/go/filer/filer_embedded.go +++ b/go/filer/filer_embedded.go @@ -47,6 +47,9 @@ func (filer *FilerEmbedded) FindFile(filePath string) (fid string, err error) { } return filer.files.FindFile(dirId, file) } +func (filer *FilerEmbedded) FindDirectory(dirPath string) (dirId DirectoryId, err error) { + return filer.directories.FindDirectory(dirPath) +} func (filer *FilerEmbedded) ListDirectories(dirPath string) (dirs []DirectoryEntry, err error) { return filer.directories.ListDirectories(dirPath) } @@ -98,6 +101,7 @@ func (filer *FilerEmbedded) DeleteDirectory(dirPath string, recursive bool) (err } } + func (filer *FilerEmbedded) DeleteFile(filePath string) (fid string, err error) { dir, file := filepath.Split(filePath) dirId, e := filer.directories.FindDirectory(dir) @@ -106,3 +110,32 @@ func (filer *FilerEmbedded) DeleteFile(filePath string) (fid string, err error) } return filer.files.DeleteFile(dirId, file) } + +/* +Move a folder or a file, with 4 Use cases: +mv fromDir toNewDir +mv fromDir toOldDir +mv fromFile toDir +mv fromFile toFile +*/ +func (filer *FilerEmbedded) Move(fromPath string, toPath string) error { + if _, dir_err := filer.FindDirectory(fromPath); dir_err == nil { + if _, err := filer.FindDirectory(toPath); err == nil { + // move folder under an existing folder + return filer.directories.MoveUnderDirectory(fromPath, toPath, "") + } else { + // move folder to a new folder + return filer.directories.MoveUnderDirectory(fromPath, filepath.Dir(toPath), filepath.Base(toPath)) + } + } + if fid, file_err := filer.DeleteFile(fromPath); file_err == nil { + if _, err := filer.FindDirectory(toPath); err == nil { + // move file under an existing folder + return filer.CreateFile(filepath.Join(toPath, filepath.Base(fromPath)), fid) + } else { + // move to a folder with new name + return filer.CreateFile(toPath, fid) + } + } + return fmt.Errorf("File %s is not found!", fromPath) +} diff --git a/go/filer/files_in_leveldb.go b/go/filer/files_in_leveldb.go index aef43a7c3..dbf2e6c52 100644 --- a/go/filer/files_in_leveldb.go +++ b/go/filer/files_in_leveldb.go @@ -7,6 +7,13 @@ import ( "github.com/syndtr/goleveldb/leveldb/util" ) +/* +The entry in level db has this format: + key: genKey(dirId, fileName) + value: []byte(fid) +And genKey(dirId, fileName) use first 4 bytes to store dirId, and rest for fileName +*/ + type FileListInLevelDb struct { db *leveldb.DB } diff --git a/go/images/resizing.go b/go/images/resizing.go index 7e21db70b..08a1e15d2 100644 --- a/go/images/resizing.go +++ b/go/images/resizing.go @@ -23,8 +23,8 @@ func Resized(ext string, data []byte, width, height int) (resized []byte, w int, } else { dstImage = imaging.Resize(srcImage, width, height, imaging.Lanczos) } - }else{ - return data, bounds.Dx(), bounds.Dy() + } else { + return data, bounds.Dx(), bounds.Dy() } var buf bytes.Buffer switch ext { diff --git a/go/weed/weed_server/filer_server.go b/go/weed/weed_server/filer_server.go index 996de5020..e56cb5964 100644 --- a/go/weed/weed_server/filer_server.go +++ b/go/weed/weed_server/filer_server.go @@ -26,6 +26,7 @@ func NewFilerServer(r *http.ServeMux, port int, master string, dir string, colle return } + r.HandleFunc("/admin/mv", fs.moveHandler) r.HandleFunc("/", fs.filerHandler) return fs, nil diff --git a/go/weed/weed_server/filer_server_handlers_admin.go b/go/weed/weed_server/filer_server_handlers_admin.go new file mode 100644 index 000000000..08b0e336e --- /dev/null +++ b/go/weed/weed_server/filer_server_handlers_admin.go @@ -0,0 +1,28 @@ +package weed_server + +import ( + "code.google.com/p/weed-fs/go/glog" + "net/http" +) + +/* +Move a folder or a file, with 4 Use cases: +mv fromDir toNewDir +mv fromDir toOldDir +mv fromFile toDir +mv fromFile toFile + +Wildcard is not supported. + +*/ +func (fs *FilerServer) moveHandler(w http.ResponseWriter, r *http.Request) { + from := r.FormValue("from") + to := r.FormValue("to") + err := fs.filer.Move(from, to) + if err != nil { + glog.V(4).Infoln("moving", from, "->", to, err.Error()) + writeJsonError(w, r, err) + } else { + w.WriteHeader(http.StatusOK) + } +} diff --git a/go/weed/weed_server/master_server_handlers_admin.go b/go/weed/weed_server/master_server_handlers_admin.go index bd6747e99..d50075fd5 100644 --- a/go/weed/weed_server/master_server_handlers_admin.go +++ b/go/weed/weed_server/master_server_handlers_admin.go @@ -99,7 +99,7 @@ func (ms *MasterServer) volumeGrowHandler(w http.ResponseWriter, r *http.Request w.WriteHeader(http.StatusNotAcceptable) writeJsonQuiet(w, r, map[string]string{"error": err.Error()}) } else { - w.WriteHeader(http.StatusNotAcceptable) + w.WriteHeader(http.StatusOK) writeJsonQuiet(w, r, map[string]interface{}{"count": count}) } }