/// <summary> /// Walk the path through the namespaces and see if this is a valid path. Really we're finding /// the parent for the volume. Someday this needs to be more dynamic in case we move the volume's rooting. /// </summary> /// <param name="volumeNamePath"></param> /// <param name="namespaces"></param> /// <param name="rootNameSpace"></param> /// <returns></returns> /// <exception cref="ArgumentException"></exception> private static (NeoVirtFSNamespaces parentPath, string volumeName) FindVolumeNameWithPath(string volumeNamePath, Dictionary <ObjectId, NeoVirtFSNamespaces> namespaces, NeoVirtFSNamespaces rootNameSpace) { NeoVirtFSNamespaces retParent = null; // Build a quick index to traverse namespaces in a tree by name - ultimately we need to cache this var nameTree = new Dictionary <ObjectId, Dictionary <string, ObjectId> >(); Console.WriteLine("Build Tree Index"); foreach (var n in namespaces) { var p = n.Value.ParentId; if (nameTree.ContainsKey(p)) { nameTree[p].Add(n.Value.NameSpace, n.Key); } else { var newT = new Dictionary <string, ObjectId>(); newT.Add(n.Value.NameSpace, n.Key); nameTree.Add(n.Value.ParentId, newT); }; } var paths = volumeNamePath.Split('/'); // Start at the top var rootLevel = rootNameSpace._id; var levelMembers = nameTree[rootLevel]; //var levelStack = new List<NeoVirtFSNamespaces>(); // Have top stop one before the end foreach (var p in paths[..^ 1])
public static ObjectId EnsureVolumeSetUpProperly(IMongoDatabase db, string volumeNamePath) { var HaveRoot = false; var NamespaceNames = new Dictionary <string, NeoVirtFSNamespaces>(); var Namespaces = new Dictionary <ObjectId, NeoVirtFSNamespaces>(); NeoVirtFSNamespaces RootNameSpace = null; var NeoVirtFSCol = db.NeoVirtFS(); var NeoVirtFSDeletedCol = db.NeoVirtFSDeleted(); var NeoVirtFSNamespacesCol = db.NeoVirtFSNamespaces(); var NeoVirtFSVolumesCol = db.NeoVirtFSVolumes(); var NeoVirtFSSecPrincipalsCol = db.NeoVirtFSSecPrincipals(); var NeoVirtFSSecACLsCol = db.NeoVirtFSSecACLs(); // Prepare for bulk update var updates = new List <WriteModel <NeoVirtFS> >(); // Load up the namespaces -- there just shouldn't be too many of these ProcessNamespaces(db, NamespaceNames, Namespaces, ref RootNameSpace, ref HaveRoot, updates); if (!HaveRoot) { throw new ApplicationException("Volume Namespaces don't define a Root - Setup Issue"); } // Now do volumes var(parentPath, VolumeName) = FindVolumeNameWithPath(volumeNamePath, Namespaces, RootNameSpace); if (parentPath == null) // We won't really get here - the above will throw { throw new ArgumentException($"Volume Path Not Valid: {volumeNamePath}"); } // So we actually need to create this volume into NeoVirtFSVolumes, which unfortunately needs business logic // We need some sort of policy for this. Maybe we're overthinking. Maybe we just need to be passed the path so we // don't need to decide? We have the Namespaces above so we can decode var volume = NeoVirtFSVolumesCol.FindSync(Builders <NeoVirtFSVolumes> .Filter.Eq(x => x.Name, VolumeName)).FirstOrDefault(); if (volume == null) { Console.WriteLine($"[Create Volume {VolumeName} into Namespace {parentPath.NameSpace}]"); var newNode = ObjectId.GenerateNewId(); // If the namespace moved then this isn't going to change it, though we may assert below NeoVirtFSVolumesCol.InsertOne(new NeoVirtFSVolumes() { _id = newNode, Name = VolumeName, NameSpace = parentPath._id, NodeId = newNode, // These are intentionally the same VolumeDefaultACL = null, ImportLocked = false, VolumeLocked = false, }); } // This is only going to return our one volume (which we may have just created) var volFilter = Builders <NeoVirtFSVolumes> .Filter.Eq(x => x.Name, VolumeName); var v = NeoVirtFSVolumesCol.FindSync(volFilter).FirstOrDefault(); // This is making sure that the NeoVirtFS elements match the Volume setup (they use the same keys for clarity) Console.WriteLine($"Volume: {v.Name}, NameSpace: {Namespaces[v.NameSpace].NameSpace}"); // Assert if the namespace has moved - We can just move it if (v.NameSpace != parentPath._id) { Console.WriteLine($"Volume Namespace {Namespaces[v.NameSpace].NameSpace} is not same as current Namespace {Namespaces[parentPath._id].NameSpace}"); v.NameSpace = parentPath._id; // Just move the node to the correct place within namespaces // And do it in the table (not bulk) var fixPar = new UpdateDefinitionBuilder <NeoVirtFSVolumes>() .Set("NameSpace", parentPath._id); NeoVirtFSVolumesCol.UpdateOne(volFilter, fixPar); } // Ensure that the filesystem nodes exist at the top level FilterDefinition <NeoVirtFS> filter = Builders <NeoAssets.Mongo.NeoVirtFS> .Filter.Eq(x => x._id, v._id); var upd = new UpdateDefinitionBuilder <NeoAssets.Mongo.NeoVirtFS>() .Set("_id", v._id) .SetOnInsert("Content", NeoVirtFSContent.Dir()) .SetOnInsert("Stat", NeoVirtFSStat.DirDefault()) .Set("VolumeId", v.NameSpace) .Set("ParentId", Namespaces[v.NameSpace]._id) // Set's see what root does - this will also move the Node to match the Volume .Set("Name", Encoding.UTF8.GetBytes(v.Name)) .Set("MaintLevel", false); // This is the volume level - users can do stuff here (by their policy) UpdateOneModel <NeoVirtFS> update = new UpdateOneModel <NeoAssets.Mongo.NeoVirtFS>(filter, upd) { IsUpsert = true }; updates.Add(update); // Persist NeoVirtFSCol.BulkWrite(updates); return(v._id); }
public static bool PullNamespacesAndVolumes(IMongoDatabase db, ref Dictionary <string, NeoVirtFSNamespaces> NamespaceNames, ref Dictionary <ObjectId, NeoVirtFSNamespaces> Namespaces, ref NeoVirtFSNamespaces RootNameSpace) { bool HaveRoot = false; var NeoVirtFSCol = db.NeoVirtFS(); var NeoVirtFSDeletedCol = db.NeoVirtFSDeleted(); var NeoVirtFSNamespacesCol = db.NeoVirtFSNamespaces(); var NeoVirtFSVolumesCol = db.NeoVirtFSVolumes(); var NeoVirtFSSecPrincipalsCol = db.NeoVirtFSSecPrincipals(); var NeoVirtFSSecACLsCol = db.NeoVirtFSSecACLs(); // Prepare for bulk update var updates = new List <WriteModel <NeoAssets.Mongo.NeoVirtFS> >(); // Load up the namespaces -- there just shouldn't be too many of these var nCount = ProcessNamespaces(db, NamespaceNames, Namespaces, ref RootNameSpace, ref HaveRoot, updates); if (!HaveRoot) { throw new ApplicationException("Volume Namespaces don't define a Root - Setup Issue"); } // Now do volumes int vCount = 0; var volumes = NeoVirtFSVolumesCol.FindSync(Builders <NeoVirtFSVolumes> .Filter.Empty).ToList(); foreach (var v in volumes) { //Console.WriteLine($"Volume: {v.Name}"); vCount++; // Ensure that the filesystem nodes exist at the top level FilterDefinition <NeoVirtFS> filter = Builders <NeoAssets.Mongo.NeoVirtFS> .Filter.Eq(x => x._id, v._id); var upd = new UpdateDefinitionBuilder <NeoAssets.Mongo.NeoVirtFS>() .Set("_id", v._id) .SetOnInsert("Content", NeoVirtFSContent.Dir()) .SetOnInsert("Stat", NeoVirtFSStat.DirDefault()) .Set("VolumeId", v.NameSpace) .Set("ParentId", Namespaces[v.NameSpace]._id) // Set's see what root does .Set("Name", Encoding.UTF8.GetBytes(v.Name)) .Set("MaintLevel", false); // This is the volume level - users can do stuff here (by their policy) UpdateOneModel <NeoVirtFS> update = new UpdateOneModel <NeoAssets.Mongo.NeoVirtFS>(filter, upd) { IsUpsert = true }; updates.Add(update); } Console.WriteLine($"[Loaded {nCount} Namespaces and {vCount} Volumes]"); // Persist NeoVirtFSCol.BulkWrite(updates); return(HaveRoot); }