Skip to content

Commit 294173f

Browse files
authored
PBM-1459: PBM ignores index removal during selective PITR restore with name remapping (#1063)
Fix indexes cloning logic to support drop op: During drop operation within oplog, indexes catalog is modified with cloning-to ns. Therefore it is necessary to have modified index catalog (with cloned collection) before we start applying the oplog. The approach to modify index catalog with cloning collection during the snapshot restore phase, ensures that PITR restore will be correctly applied also on index catalog.
1 parent 564ba8e commit 294173f

File tree

3 files changed

+44
-24
lines changed

3 files changed

+44
-24
lines changed

pbm/oplog/restore.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ type cloneNS struct {
114114

115115
func (c *cloneNS) SetNSPair(nsPair snapshot.CloneNS) {
116116
c.CloneNS = nsPair
117-
c.fromDB, c.fromColl, _ = strings.Cut(nsPair.FromNS, ".")
118-
c.toDB, c.toColl, _ = strings.Cut(nsPair.ToNS, ".")
117+
c.fromDB, c.fromColl = nsPair.SplitFromNS()
118+
c.toDB, c.toColl = nsPair.SplitToNS()
119119
}
120120

121121
// OplogRestore is the oplog applyer
@@ -794,7 +794,7 @@ func (o *OplogRestore) cloneEntry(op *db.Oplog) {
794794
}
795795

796796
cmdName := op.Object[0].Key
797-
if cmdName != "create" && cmdName != "drop" {
797+
if _, ok := cloningNSSupportedCommands[cmdName]; !ok {
798798
return
799799
}
800800

pbm/restore/logical.go

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,11 @@ func (r *Restore) Snapshot(
273273
return err
274274
}
275275

276-
err = r.restoreIndexes(ctx, oplogOption.nss, cloneNS)
276+
if cloneNS.IsSpecified() {
277+
err = r.restoreIndexes(ctx, []string{cloneNS.ToNS})
278+
} else {
279+
err = r.restoreIndexes(ctx, oplogOption.nss)
280+
}
277281
if err != nil {
278282
return errors.Wrap(err, "restore indexes")
279283
}
@@ -439,7 +443,11 @@ func (r *Restore) PITR(
439443
return err
440444
}
441445

442-
err = r.restoreIndexes(ctx, oplogOption.nss, cloneNS)
446+
if cloneNS.IsSpecified() {
447+
err = r.restoreIndexes(ctx, []string{cloneNS.ToNS})
448+
} else {
449+
err = r.restoreIndexes(ctx, oplogOption.nss)
450+
}
443451
if err != nil {
444452
return errors.Wrap(err, "restore indexes")
445453
}
@@ -863,7 +871,7 @@ func (r *Restore) RunSnapshot(
863871
return nil, err
864872
}
865873

866-
err = r.loadIndexesFrom(bytes.NewReader(data))
874+
err = r.loadIndexesFrom(bytes.NewReader(data), cloneNS)
867875
if err != nil {
868876
return nil, errors.Wrap(err, "load indexes")
869877
}
@@ -1007,12 +1015,15 @@ func (r *Restore) restoreUsersAndRoles(ctx context.Context, nss []string) error
10071015
return nil
10081016
}
10091017

1010-
func (r *Restore) loadIndexesFrom(rdr io.Reader) error {
1018+
func (r *Restore) loadIndexesFrom(rdr io.Reader, cloneNS snapshot.CloneNS) error {
10111019
meta, err := archive.ReadMetadata(rdr)
10121020
if err != nil {
10131021
return errors.Wrap(err, "read metadata")
10141022
}
10151023

1024+
fromDB, fromColl := cloneNS.SplitFromNS()
1025+
toDB, toColl := cloneNS.SplitToNS()
1026+
10161027
for _, ns := range meta.Namespaces {
10171028
var md mongorestore.Metadata
10181029
err := bson.UnmarshalExtJSON([]byte(ns.Metadata), true, &md)
@@ -1021,7 +1032,11 @@ func (r *Restore) loadIndexesFrom(rdr io.Reader) error {
10211032
ns.Database, ns.Collection)
10221033
}
10231034

1024-
r.indexCatalog.AddIndexes(ns.Database, ns.Collection, md.Indexes)
1035+
if cloneNS.IsSpecified() && ns.Database == fromDB && ns.Collection == fromColl {
1036+
r.indexCatalog.AddIndexes(toDB, toColl, md.Indexes)
1037+
} else {
1038+
r.indexCatalog.AddIndexes(ns.Database, ns.Collection, md.Indexes)
1039+
}
10251040

10261041
simple := true
10271042
if md.Options != nil {
@@ -1048,7 +1063,7 @@ func (r *Restore) loadIndexesFrom(rdr io.Reader) error {
10481063
return nil
10491064
}
10501065

1051-
func (r *Restore) restoreIndexes(ctx context.Context, nss []string, cloneNS snapshot.CloneNS) error {
1066+
func (r *Restore) restoreIndexes(ctx context.Context, nss []string) error {
10521067
r.log.Debug("building indexes up")
10531068

10541069
isSelected := util.MakeSelectedPred(nss)
@@ -1073,32 +1088,24 @@ func (r *Restore) restoreIndexes(ctx context.Context, nss []string, cloneNS snap
10731088
}
10741089

10751090
var indexNames []string
1076-
var targetDB, targetColl string
10771091
for _, index := range indexes {
1078-
if cloneNS.IsSpecified() && ns.String() == cloneNS.FromNS {
1079-
// override index's ns for the collection cloning
1080-
targetDB, targetColl = util.ParseNS(cloneNS.ToNS)
1081-
index.Options["ns"] = cloneNS.ToNS
1082-
} else {
1083-
targetDB, targetColl = ns.DB, ns.Collection
1084-
index.Options["ns"] = ns.DB + "." + ns.Collection
1085-
}
1092+
index.Options["ns"] = ns.DB + "." + ns.Collection
10861093
indexNames = append(indexNames, index.Options["name"].(string))
10871094
// remove the index version, forcing an update
10881095
delete(index.Options, "v")
10891096
}
10901097

10911098
rawCommand := bson.D{
1092-
{"createIndexes", targetColl},
1099+
{"createIndexes", ns.Collection},
10931100
{"indexes", indexes},
10941101
{"ignoreUnknownIndexOptions", true},
10951102
}
10961103

10971104
r.log.Info("restoring indexes for %s.%s: %s",
1098-
targetDB, targetColl, strings.Join(indexNames, ", "))
1099-
err := r.nodeConn.Database(targetDB).RunCommand(ctx, rawCommand).Err()
1105+
ns.DB, ns.Collection, strings.Join(indexNames, ", "))
1106+
err := r.nodeConn.Database(ns.DB).RunCommand(ctx, rawCommand).Err()
11001107
if err != nil {
1101-
return errors.Wrapf(err, "createIndexes for %s.%s", targetDB, targetColl)
1108+
return errors.Wrapf(err, "createIndexes for %s.%s", ns.DB, ns.Collection)
11021109
}
11031110
}
11041111

pbm/snapshot/restore.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package snapshot
33
import (
44
"io"
55
"runtime"
6+
"strings"
67

78
"github.com/mongodb/mongo-tools/common/options"
89
"github.com/mongodb/mongo-tools/mongorestore"
@@ -42,17 +43,29 @@ var ExcludeFromRestore = []string{
4243

4344
type restorer struct{ *mongorestore.MongoRestore }
4445

45-
// CloneNS contains clone from/to info for cloning NS use case
46+
// CloneNS contains clone from/to info for cloning NS use case.
4647
type CloneNS struct {
4748
FromNS string
4849
ToNS string
4950
}
5051

51-
// IsSpecified returns true in case of cloning use case
52+
// IsSpecified returns true in case of cloning use case.
5253
func (c *CloneNS) IsSpecified() bool {
5354
return c.FromNS != "" && c.ToNS != ""
5455
}
5556

57+
// SplitFromNS breaks cloning-from namespace to database & collection pair.
58+
func (c *CloneNS) SplitFromNS() (string, string) {
59+
db, coll, _ := strings.Cut(c.FromNS, ".")
60+
return db, coll
61+
}
62+
63+
// SplitToNS breaks cloning-to namespace to database & collection pair.
64+
func (c *CloneNS) SplitToNS() (string, string) {
65+
db, coll, _ := strings.Cut(c.ToNS, ".")
66+
return db, coll
67+
}
68+
5669
func NewRestore(uri string,
5770
cfg *config.Config,
5871
cloneNS CloneNS,

0 commit comments

Comments
 (0)