Browse Source

lib/db: Remove index ids when dropping folder (#7200)

Simon Frei 5 years ago
parent
commit
bd0c9913cf
4 changed files with 33 additions and 0 deletions
  1. 5 0
      lib/db/keyer.go
  2. 20 0
      lib/db/lowlevel.go
  3. 1 0
      lib/db/set.go
  4. 7 0
      lib/db/transactions.go

+ 5 - 0
lib/db/keyer.go

@@ -102,6 +102,7 @@ type keyer interface {
 
 	// index IDs
 	GenerateIndexIDKey(key, device, folder []byte) (indexIDKey, error)
+	FolderFromIndexIDKey(key []byte) ([]byte, bool)
 
 	// Mtimes
 	GenerateMtimesKey(key, folder []byte) (mtimesKey, error)
@@ -303,6 +304,10 @@ func (k defaultKeyer) GenerateIndexIDKey(key, device, folder []byte) (indexIDKey
 	return key, nil
 }
 
+func (k defaultKeyer) FolderFromIndexIDKey(key []byte) ([]byte, bool) {
+	return k.folderIdx.Val(binary.BigEndian.Uint32(key[keyPrefixLen+keyDeviceLen:]))
+}
+
 type mtimesKey []byte
 
 func (k defaultKeyer) GenerateMtimesKey(key, folder []byte) (mtimesKey, error) {

+ 20 - 0
lib/db/lowlevel.go

@@ -553,6 +553,26 @@ func (db *Lowlevel) setIndexID(device, folder []byte, id protocol.IndexID) error
 	return db.Put(key, bs)
 }
 
+func (db *Lowlevel) dropFolderIndexIDs(folder []byte) error {
+	t, err := db.newReadWriteTransaction()
+	if err != nil {
+		return err
+	}
+	defer t.close()
+
+	if err := t.deleteKeyPrefixMatching([]byte{KeyTypeIndexID}, func(key []byte) bool {
+		keyFolder, ok := t.keyer.FolderFromIndexIDKey(key)
+		if !ok {
+			l.Debugf("Deleting IndexID with missing FolderIdx: %v", key)
+			return true
+		}
+		return bytes.Equal(keyFolder, folder)
+	}); err != nil {
+		return err
+	}
+	return t.Commit()
+}
+
 func (db *Lowlevel) dropMtimes(folder []byte) error {
 	key, err := db.keyer.GenerateMtimesKey(nil, folder)
 	if err != nil {

+ 1 - 0
lib/db/set.go

@@ -419,6 +419,7 @@ func DropFolder(db *Lowlevel, folder string) {
 		db.dropFolder,
 		db.dropMtimes,
 		db.dropFolderMeta,
+		db.dropFolderIndexIDs,
 		db.folderIdx.Delete,
 	}
 	for _, drop := range droppers {

+ 7 - 0
lib/db/transactions.go

@@ -889,12 +889,19 @@ func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device, file
 }
 
 func (t readWriteTransaction) deleteKeyPrefix(prefix []byte) error {
+	return t.deleteKeyPrefixMatching(prefix, func([]byte) bool { return true })
+}
+
+func (t readWriteTransaction) deleteKeyPrefixMatching(prefix []byte, match func(key []byte) bool) error {
 	dbi, err := t.NewPrefixIterator(prefix)
 	if err != nil {
 		return err
 	}
 	defer dbi.Release()
 	for dbi.Next() {
+		if !match(dbi.Key()) {
+			continue
+		}
 		if err := t.Delete(dbi.Key()); err != nil {
 			return err
 		}