// Open is part of the intents.file interface, it finds the metadata in the prelude and creates a bytes.Buffer from it. func (mpf *MetadataPreludeFile) Open() error { db, c := common.SplitNamespace(mpf.Origin) dbMetadatas, ok := mpf.Prelude.NamespaceMetadatasByDB[db] if !ok { return fmt.Errorf("no metadata found for '%s'", db) } for _, metadata := range dbMetadatas { if metadata.Collection == c { mpf.Buffer = bytes.NewBufferString(metadata.Metadata) return nil } } return fmt.Errorf("no matching metadata found for '%s'", mpf.Origin) }
// PutWithNamespace inserts an intent into the manager with the source set // to the provided namespace. Intents for the same collection are merged // together, so that BSON and metadata files for the same collection are // returned in the same intent. func (manager *Manager) PutWithNamespace(ns string, intent *Intent) { if intent == nil { panic("cannot insert nil *Intent into IntentManager") } db, _ := common.SplitNamespace(ns) // bucket special-case collections if intent.IsOplog() { manager.PutOplogIntent(intent, intent.Namespace()) return } if intent.IsSystemIndexes() { if intent.BSONFile != nil { manager.indexIntents[db] = intent manager.specialIntents[ns] = intent } return } if intent.IsUsers() { if intent.BSONFile != nil { manager.usersIntent = intent manager.specialIntents[ns] = intent } return } if intent.IsRoles() { if intent.BSONFile != nil { manager.rolesIntent = intent manager.specialIntents[ns] = intent } return } if intent.IsAuthVersion() { if intent.BSONFile != nil { manager.versionIntent = intent manager.specialIntents[ns] = intent } return } manager.putNormalIntentWithNamespace(ns, intent) }
// CreateIntentsForDB drills down into the dir folder, creating intents // for all of the collection dump files it finds for the db database. func (restore *MongoRestore) CreateIntentsForDB(db string, dir archive.DirLike) (err error) { var entries []archive.DirLike log.Logvf(log.DebugHigh, "reading collections for database %v in %v", db, dir.Name()) entries, err = dir.ReadDir() if err != nil { return fmt.Errorf("error reading db folder %v: %v", db, err) } usesMetadataFiles := hasMetadataFiles(entries) for _, entry := range entries { if entry.IsDir() { log.Logvf(log.Always, `don't know what to do with subdirectory "%v", skipping...`, filepath.Join(dir.Name(), entry.Name())) } else { collection, fileType := restore.getInfoFromFilename(entry.Name()) sourceNS := db + "." + collection switch fileType { case BSONFileType: var skip bool // Dumps of a single database (i.e. with the -d flag) may contain special // db-specific collections that start with a "$" (for example, $admin.system.users // holds the users for a database that was dumped with --dumpDbUsersAndRoles enabled). // If these special files manage to be included in a dump directory during a full // (multi-db) restore, we should ignore them. if restore.NSOptions.DB == "" && strings.HasPrefix(collection, "$") { log.Logvf(log.DebugLow, "not restoring special collection %v.%v", db, collection) skip = true } // TOOLS-717: disallow restoring to the system.profile collection. // Server versions >= 3.0.3 disallow user inserts to system.profile so // it would likely fail anyway. if collection == "system.profile" { log.Logvf(log.DebugLow, "skipping restore of system.profile collection", db) skip = true } // skip restoring the indexes collection if we are using metadata // files to store index information, to eliminate redundancy if collection == "system.indexes" && usesMetadataFiles { log.Logvf(log.DebugLow, "not restoring system.indexes collection because database %v "+ "has .metadata.json files", db) skip = true } if !restore.includer.Has(sourceNS) { log.Logvf(log.DebugLow, "skipping restoring %v.%v, it is not included", db, collection) skip = true } if restore.excluder.Has(sourceNS) { log.Logvf(log.DebugLow, "skipping restoring %v.%v, it is excluded", db, collection) skip = true } destNS := restore.renamer.Get(sourceNS) destDB, destC := common.SplitNamespace(destNS) intent := &intents.Intent{ DB: destDB, C: destC, Size: entry.Size(), } if restore.InputOptions.Archive != "" { if restore.InputOptions.Archive == "-" { intent.Location = "archive on stdin" } else { intent.Location = fmt.Sprintf("archive '%v'", restore.InputOptions.Archive) } if skip { // adding the DemuxOut to the demux, but not adding the intent to the manager mutedOut := &archive.MutedCollection{Intent: intent, Demux: restore.archive.Demux} restore.archive.Demux.Open(sourceNS, mutedOut) continue } if intent.IsSpecialCollection() { specialCollectionCache := archive.NewSpecialCollectionCache(intent, restore.archive.Demux) intent.BSONFile = specialCollectionCache restore.archive.Demux.Open(sourceNS, specialCollectionCache) } else { intent.BSONFile = &archive.RegularCollectionReceiver{ Origin: sourceNS, Intent: intent, Demux: restore.archive.Demux, } } } else { if skip { continue } intent.Location = entry.Path() intent.BSONFile = &realBSONFile{path: entry.Path(), intent: intent, gzip: restore.InputOptions.Gzip} } log.Logvf(log.Info, "found collection %v bson to restore to %v", sourceNS, destNS) restore.manager.PutWithNamespace(sourceNS, intent) case MetadataFileType: if collection == "system.profile" { log.Logvf(log.DebugLow, "skipping restore of system.profile metadata") continue } if !restore.includer.Has(sourceNS) { log.Logvf(log.DebugLow, "skipping restoring %v.%v metadata, it is not included", db, collection) continue } if restore.excluder.Has(sourceNS) { log.Logvf(log.DebugLow, "skipping restoring %v.%v metadata, it is excluded", db, collection) continue } usesMetadataFiles = true destNS := restore.renamer.Get(sourceNS) rnDB, rnC := common.SplitNamespace(destNS) intent := &intents.Intent{ DB: rnDB, C: rnC, } if restore.InputOptions.Archive != "" { if restore.InputOptions.Archive == "-" { intent.MetadataLocation = "archive on stdin" } else { intent.MetadataLocation = fmt.Sprintf("archive '%v'", restore.InputOptions.Archive) } intent.MetadataFile = &archive.MetadataPreludeFile{Origin: sourceNS, Intent: intent, Prelude: restore.archive.Prelude} } else { intent.MetadataLocation = entry.Path() intent.MetadataFile = &realMetadataFile{path: entry.Path(), intent: intent, gzip: restore.InputOptions.Gzip} } log.Logvf(log.Info, "found collection metadata from %v to restore to %v", sourceNS, destNS) restore.manager.PutWithNamespace(sourceNS, intent) default: log.Logvf(log.Always, `don't know what to do with file "%v", skipping...`, entry.Path()) } } } return nil }
func stripDBFromNS(ns string) string { _, c := common.SplitNamespace(ns) return c }