Beispiel #1
0
        internal static NeoVirtFSContent NewCache(ReadOnlySpan <byte> path, ObjectId nodeObj)
        {
            var fileuuid = GuidUtility.Create(GuidUtility.UrlNamespace, path.ToArray());

            var fileg = fileuuid.ToString().ToLower();

            // 8478e36a-669c-11ec-8541-17df4f57891e
            // 0123456789012345678901234567890123456789
            // 000000000011111111112222222222333333333

            // Ultimately will need real pool mechanism here

            // Original scheme was absurd - the 3 digit is 4096.  If we're sufficiently event driven and reactive then this shouldn't get
            // out of hand -- it should handle millions of physical cache files without too much difficulty, and really if they're annealled
            // quickly enough there should never be that many on a given filesystem

            //var cacheFile = $"/ua/NeoVirtCache/{fileg.Substring(0, 2)}/{fileg.Substring(2, 2)}/{fileg.Substring(4, 2)}/{fileg.Substring(6, 2)}/{fileg}_{nodeObj}";
            var cacheFile = $"/ua/NeoVirtCache/{fileg.Substring(0, 3)}/{fileg}_{nodeObj}";

            var rec = new NeoVirtFSContent
            {
                CachePoolGuid = fileuuid,
                ContentType   = VirtFSContentTypes.CachePool,
                CacheFile     = Encoding.UTF8.GetBytes(cacheFile)
            };

            return(rec);
        }
Beispiel #2
0
        }                                                           // serialized version of CachePoolGuid, full path, split

        public static NeoVirtFSContent Dir()
        {
            var ret = new NeoVirtFSContent
            {
                ContentType = VirtFSContentTypes.NotAFile,
                NotAFile    = true
            };

            return(ret);
        }
        public override int MkDir(ReadOnlySpan <byte> path, mode_t mode)
        {
            if (verbosity > 5)
            {
                Console.WriteLine($"MkDir {path.GetString()} mode={mode}");
            }

            int error = 0, level = 0;
            var procs = ProcPath(path, ref error, ref level, mustExist: false, isADir: true);

            if (error != 0)
            {
                return(-LibC.ENOENT);
            }


            if (procs.Count < 2)
            {
                Console.WriteLine($"Mkdir - path < 2");
                return(-LibC.EPERM);
            }

            var cNode  = procs.Pop();
            var inNode = procs.Pop();

            if (cNode.Item2 != null)
            {
                return(-LibC.EEXIST);  // File (or directory) already exists
            }
            if (inNode.Item2 == null)
            {
                return(-LibC.ENOENT);   // SHouldn't happen (2nd level will get error)
            }
            var createIn = inNode.Item2;

            if (createIn.MaintLevel)
            {
                return(-LibC.EPERM);     // Nobody can create in the maintenance levels (Namespace levels)
            }
            var newRec = new NeoAssets.Mongo.NeoVirtFS()
            {
                _id        = ObjectId.GenerateNewId(),
                Content    = NeoVirtFSContent.Dir(),
                Stat       = NeoVirtFSStat.DirDefault((uint)mode),
                Name       = cNode.Item1,
                VolumeId   = createIn.VolumeId,
                ParentId   = createIn._id,
                MaintLevel = false,
            };  // It will assign it's own objectId _id

            NeoVirtFSCol.InsertOne(newRec);
            Console.WriteLine($"Create Directory {cNode.Item1.GetString()} id={newRec._id}");

            return(0);
        }
Beispiel #4
0
        public static NeoVirtFSContent PhysicalFilePath(byte[] filePath)
        {
            var ret = new NeoVirtFSContent
            {
                ContentType  = VirtFSContentTypes.PhysicalFile,
                NotAFile     = false,
                PhysicalFile = filePath
            };

            return(ret);
        }
Beispiel #5
0
        public static NeoVirtFSContent AnnealedAsset(byte[] AssetSHA1, bool lost)
        {
            var ret = new NeoVirtFSContent
            {
                ContentType = VirtFSContentTypes.Asset,
                NotAFile    = false,
                AssetSHA1   = AssetSHA1,
                AssetLost   = lost
            };

            return(ret);
        }
Beispiel #6
0
        public static NeoVirtFS CreateDirectory(ObjectId parId, ObjectId volId, byte[] name, mode_t mode)
        {
            var newRec = new NeoVirtFS()
            {
                _id        = ObjectId.GenerateNewId(),
                Content    = NeoVirtFSContent.Dir(),
                Stat       = NeoVirtFSStat.DirDefault((uint)mode),
                Name       = name,
                VolumeId   = volId,
                ParentId   = parId,
                MaintLevel = false,
            };

            return(newRec);
        }
Beispiel #7
0
        public static NeoVirtFS CreateNewFile(ObjectId parId, ObjectId volId, byte[] name, ReadOnlySpan <byte> path, mode_t mode, NeoVirtFSContent cont = null)
        {
            var id = ObjectId.GenerateNewId();

            if (cont == null)
            {
                cont = NeoVirtFSContent.NewCache(path, id);
            }

            //Console.WriteLine($"Set newId for file to {id}");
            var newRec = new NeoVirtFS
            {
                _id        = id,
                Name       = name,
                VolumeId   = volId,
                ParentId   = parId,
                Stat       = NeoVirtFSStat.FileDefault((uint)mode),
                Content    = cont,
                MaintLevel = false
            };

            return(newRec);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }