Browse Source

Add a different mode to stindex

Audrius Butkevicius 10 years ago
parent
commit
4fd614be09
4 changed files with 223 additions and 52 deletions
  1. 63 0
      cmd/stindex/dump.go
  2. 90 0
      cmd/stindex/dumpsize.go
  3. 18 52
      cmd/stindex/main.go
  4. 52 0
      cmd/stindex/util.go

+ 63 - 0
cmd/stindex/dump.go

@@ -0,0 +1,63 @@
+// Copyright (C) 2015 The Syncthing Authors.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package main
+
+import (
+	"encoding/binary"
+	"fmt"
+	"log"
+
+	"github.com/syncthing/protocol"
+	"github.com/syncthing/syncthing/lib/db"
+	"github.com/syndtr/goleveldb/leveldb"
+)
+
+func dump(ldb *leveldb.DB) {
+	it := ldb.NewIterator(nil, nil)
+	var dev protocol.DeviceID
+	for it.Next() {
+		key := it.Key()
+		switch key[0] {
+		case db.KeyTypeDevice:
+			folder := nulString(key[1 : 1+64])
+			devBytes := key[1+64 : 1+64+32]
+			name := nulString(key[1+64+32:])
+			copy(dev[:], devBytes)
+			fmt.Printf("[device] F:%q N:%q D:%v\n", folder, name, dev)
+
+			var f protocol.FileInfo
+			err := f.UnmarshalXDR(it.Value())
+			if err != nil {
+				log.Fatal(err)
+			}
+			fmt.Printf("  N:%q\n  F:%#o\n  M:%d\n  V:%v\n  S:%d\n  B:%d\n", f.Name, f.Flags, f.Modified, f.Version, f.Size(), len(f.Blocks))
+
+		case db.KeyTypeGlobal:
+			folder := nulString(key[1 : 1+64])
+			name := nulString(key[1+64:])
+			fmt.Printf("[global] F:%q N:%q V:%x\n", folder, name, it.Value())
+
+		case db.KeyTypeBlock:
+			folder := nulString(key[1 : 1+64])
+			hash := key[1+64 : 1+64+32]
+			name := nulString(key[1+64+32:])
+			fmt.Printf("[block] F:%q H:%x N:%q I:%d\n", folder, hash, name, binary.BigEndian.Uint32(it.Value()))
+
+		case db.KeyTypeDeviceStatistic:
+			fmt.Printf("[dstat]\n  %x\n  %x\n", it.Key(), it.Value())
+
+		case db.KeyTypeFolderStatistic:
+			fmt.Printf("[fstat]\n  %x\n  %x\n", it.Key(), it.Value())
+
+		case db.KeyTypeVirtualMtime:
+			fmt.Printf("[mtime]\n  %x\n  %x\n", it.Key(), it.Value())
+
+		default:
+			fmt.Printf("[???]\n  %x\n  %x\n", it.Key(), it.Value())
+		}
+	}
+}

+ 90 - 0
cmd/stindex/dumpsize.go

@@ -0,0 +1,90 @@
+// Copyright (C) 2015 The Syncthing Authors.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package main
+
+import (
+	"container/heap"
+	"fmt"
+
+	"github.com/syncthing/protocol"
+	"github.com/syncthing/syncthing/lib/db"
+	"github.com/syndtr/goleveldb/leveldb"
+)
+
+// An IntHeap is a min-heap of ints.
+type SizedElement struct {
+	key  string
+	size int
+}
+
+type ElementHeap []SizedElement
+
+func (h ElementHeap) Len() int           { return len(h) }
+func (h ElementHeap) Less(i, j int) bool { return h[i].size > h[j].size }
+func (h ElementHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
+
+func (h *ElementHeap) Push(x interface{}) {
+	*h = append(*h, x.(SizedElement))
+}
+
+func (h *ElementHeap) Pop() interface{} {
+	old := *h
+	n := len(old)
+	x := old[n-1]
+	*h = old[0 : n-1]
+	return x
+}
+
+func dumpsize(ldb *leveldb.DB) {
+	h := &ElementHeap{}
+	heap.Init(h)
+
+	it := ldb.NewIterator(nil, nil)
+	var dev protocol.DeviceID
+	var ele SizedElement
+	for it.Next() {
+		key := it.Key()
+		switch key[0] {
+		case db.KeyTypeDevice:
+			folder := nulString(key[1 : 1+64])
+			devBytes := key[1+64 : 1+64+32]
+			name := nulString(key[1+64+32:])
+			copy(dev[:], devBytes)
+			ele.key = fmt.Sprintf("DEVICE:%s:%s:%s", dev, folder, name)
+
+		case db.KeyTypeGlobal:
+			folder := nulString(key[1 : 1+64])
+			name := nulString(key[1+64:])
+			ele.key = fmt.Sprintf("GLOBAL:%s:%s", folder, name)
+
+		case db.KeyTypeBlock:
+			folder := nulString(key[1 : 1+64])
+			hash := key[1+64 : 1+64+32]
+			name := nulString(key[1+64+32:])
+			ele.key = fmt.Sprintf("BLOCK:%s:%x:%s", folder, hash, name)
+
+		case db.KeyTypeDeviceStatistic:
+			ele.key = fmt.Sprintf("DEVICESTATS:%s", key[1:])
+
+		case db.KeyTypeFolderStatistic:
+			ele.key = fmt.Sprintf("FOLDERSTATS:%s", key[1:])
+
+		case db.KeyTypeVirtualMtime:
+			ele.key = fmt.Sprintf("MTIME:%s", key[1:])
+
+		default:
+			ele.key = fmt.Sprintf("UNKNOWN:%x", key)
+		}
+		ele.size = len(it.Value())
+		heap.Push(h, ele)
+	}
+
+	for h.Len() > 0 {
+		ele = heap.Pop(h).(SizedElement)
+		fmt.Println(ele.key, ele.size)
+	}
+}

+ 18 - 52
cmd/stindex/main.go

@@ -7,25 +7,33 @@
 package main
 
 import (
-	"encoding/binary"
 	"flag"
 	"fmt"
 	"log"
 	"os"
+	"path/filepath"
 
-	"github.com/syncthing/syncthing/lib/db"
-	"github.com/syncthing/syncthing/lib/protocol"
 	"github.com/syndtr/goleveldb/leveldb"
 	"github.com/syndtr/goleveldb/leveldb/opt"
 )
 
 func main() {
+	var mode string
 	log.SetFlags(0)
 	log.SetOutput(os.Stdout)
 
+	flag.StringVar(&mode, "mode", "dump", "Mode of operation: dump, dumpsize")
+
 	flag.Parse()
 
-	ldb, err := leveldb.OpenFile(flag.Arg(0), &opt.Options{
+	path := flag.Arg(0)
+	if path == "" {
+		path = filepath.Join(defaultConfigDir(), "index-v0.11.0.db")
+	}
+
+	fmt.Println("Path:", path)
+
+	ldb, err := leveldb.OpenFile(path, &opt.Options{
 		ErrorIfMissing:         true,
 		Strict:                 opt.StrictAll,
 		OpenFilesCacheCapacity: 100,
@@ -34,53 +42,11 @@ func main() {
 		log.Fatal(err)
 	}
 
-	it := ldb.NewIterator(nil, nil)
-	var dev protocol.DeviceID
-	for it.Next() {
-		key := it.Key()
-		switch key[0] {
-		case db.KeyTypeDevice:
-			folder := nulString(key[1 : 1+64])
-			devBytes := key[1+64 : 1+64+32]
-			name := nulString(key[1+64+32:])
-			copy(dev[:], devBytes)
-			fmt.Printf("[device] F:%q N:%q D:%v\n", folder, name, dev)
-
-			var f protocol.FileInfo
-			err := f.UnmarshalXDR(it.Value())
-			if err != nil {
-				log.Fatal(err)
-			}
-			fmt.Printf("  N:%q\n  F:%#o\n  M:%d\n  V:%v\n  S:%d\n  B:%d\n", f.Name, f.Flags, f.Modified, f.Version, f.Size(), len(f.Blocks))
-
-		case db.KeyTypeGlobal:
-			folder := nulString(key[1 : 1+64])
-			name := nulString(key[1+64:])
-			fmt.Printf("[global] F:%q N:%q V:%x\n", folder, name, it.Value())
-
-		case db.KeyTypeBlock:
-			folder := nulString(key[1 : 1+64])
-			hash := key[1+64 : 1+64+32]
-			name := nulString(key[1+64+32:])
-			fmt.Printf("[block] F:%q H:%x N:%q I:%d\n", folder, hash, name, binary.BigEndian.Uint32(it.Value()))
-
-		case db.KeyTypeDeviceStatistic:
-			fmt.Printf("[dstat]\n  %x\n  %x\n", it.Key(), it.Value())
-
-		case db.KeyTypeFolderStatistic:
-			fmt.Printf("[fstat]\n  %x\n  %x\n", it.Key(), it.Value())
-
-		default:
-			fmt.Printf("[???]\n  %x\n  %x\n", it.Key(), it.Value())
-		}
-	}
-}
-
-func nulString(bs []byte) string {
-	for i := range bs {
-		if bs[i] == 0 {
-			return string(bs[:i])
-		}
+	if mode == "dump" {
+		dump(ldb)
+	} else if mode == "dumpsize" {
+		size(ldb)
+	} else {
+		fmt.Println("Unknown mode")
 	}
-	return string(bs)
 }

+ 52 - 0
cmd/stindex/util.go

@@ -0,0 +1,52 @@
+// Copyright (C) 2015 The Syncthing Authors.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package main
+
+import (
+	"log"
+	"os"
+	"path/filepath"
+	"runtime"
+
+	"github.com/syncthing/syncthing/lib/osutil"
+)
+
+func nulString(bs []byte) string {
+	for i := range bs {
+		if bs[i] == 0 {
+			return string(bs[:i])
+		}
+	}
+	return string(bs)
+}
+
+func defaultConfigDir() string {
+	switch runtime.GOOS {
+	case "windows":
+		if p := os.Getenv("LocalAppData"); p != "" {
+			return filepath.Join(p, "Syncthing")
+		}
+		return filepath.Join(os.Getenv("AppData"), "Syncthing")
+
+	case "darwin":
+		dir, err := osutil.ExpandTilde("~/Library/Application Support/Syncthing")
+		if err != nil {
+			log.Fatal(err)
+		}
+		return dir
+
+	default:
+		if xdgCfg := os.Getenv("XDG_CONFIG_HOME"); xdgCfg != "" {
+			return filepath.Join(xdgCfg, "syncthing")
+		}
+		dir, err := osutil.ExpandTilde("~/.config/syncthing")
+		if err != nil {
+			log.Fatal(err)
+		}
+		return dir
+	}
+}