Exemple #1
0
        public static IStorageSchema AddStorageExtension(string tslSrcDir, string rootNamespace)
        {
            //  assemblyName serves as a global-unique identifier for a storage extension.
            var assemblyName = Guid.NewGuid().ToString("N");
            var projDir      = GetTempDirectory();
            var buildDir     = GetTempDirectory();
            var outDir       = GetTempDirectory();
            var ext          = new StorageExtensionRecord(s_currentCellTypeOffset, rootNamespace, assemblyName);

            IStorageSchema schema;

            CreateCSProj(projDir, assemblyName);

            CodeGen(tslSrcDir, rootNamespace, ext.CellTypeOffset, projDir);

            Build(projDir, outDir, assemblyName);

            schema = Load(ext, true);

            SaveMetadata();

            AggregatedStorageSchema.s_singleton.Update();

            return(schema);
        }
Exemple #2
0
        private static IStorageSchema Load(StorageExtensionRecord ext, bool primary)
        {
            //  capture states
            var ctoffset = ext.CellTypeOffset;
            var ctmap    = new Dictionary <string, int>(s_CellTypeIDs);
            var gcops    = new List <IGenericCellOperations>(s_GenericCellOperations);
            var schemas  = new List <IStorageSchema>(s_StorageSchemas);
            var iditv    = new List <int>(s_IDIntervals);

            var pshadow = ShadowCopy(Path.Combine(PathHelper.StorageSlot(primary), ext.AssemblyName));
            var apath   = Path.Combine(pshadow, ext.AssemblyName + ".dll");
            var asm     = Assembly.LoadFrom(apath);

            Log.WriteLine(LogLevel.Debug, $"{nameof(CompositeStorage)}: assembly from {apath} is loaded.");

            new[] { "Current Storage Info:",
                    $"#Loaded extensions: {s_Extensions.Count}",
                    $"#IDIntervals: : {iditv.Count}",
                    $"#CellTypeIDs:{ctmap.Count}",
                    $"#StorageSchema:{schemas.Count}",
                    $"#GenericCellOperations:{gcops.Count}" }
            .Each(_ => Log.WriteLine(LogLevel.Debug, $"{nameof(CompositeStorage)}: {{0}}", _));

            var schema  = AssemblyUtility.GetAllClassInstances <IStorageSchema>(assembly: asm).FirstOrDefault();
            var cellOps = AssemblyUtility.GetAllClassInstances <IGenericCellOperations>(assembly: asm).FirstOrDefault();

            if (schema == null || cellOps == null)
            {
                throw new AsmLoadException("Not a TSL extension.");
            }

            var cellDescs = schema.CellDescriptors.ToList();

            schemas.Add(schema);
            gcops.Add(cellOps);

            int maxoffset = ctoffset;

            foreach (var cellDesc in cellDescs)
            {
                if (ctmap.TryGetValue(cellDesc.TypeName, out var existing_tid))
                {
                    Log.WriteLine(LogLevel.Info, $"{nameof(CompositeStorage)}: overriding type {cellDesc.TypeName}: TypeId {existing_tid}->{cellDesc.CellType}");
                }

                ctmap[cellDesc.TypeName] = cellDesc.CellType;
                if (cellDesc.CellType < ctoffset)
                {
                    throw new AsmLoadException("New cell type id conflicts existing type space");
                }
                maxoffset = Math.Max(maxoffset, cellDesc.CellType);
            }

            ctoffset += cellDescs.Count + 1; // extra typeid for undefined/reserved cell type
            if (ctoffset != maxoffset + 1)
            {
                throw new AsmLoadException("The whole type id space is not compact");
            }

            iditv.Add(ctoffset);
            if (!iditv.OrderBy(_ => _).SequenceEqual(iditv))
            {
                throw new AsmLoadException("intervals do not grow monotonically");
            }

            //  commit states
            lock (s_lock)
            {
                s_currentCellTypeOffset = ctoffset;
                s_CellTypeIDs           = ctmap;
                s_GenericCellOperations = gcops;
                s_StorageSchemas        = schemas;
                s_IDIntervals           = iditv;
                s_Extensions.Add(ext);

                Log.WriteLine(LogLevel.Info, $"{nameof(CompositeStorage)}: storage extension '{ext.RootNamespace}' loaded");

                return(schema);
            }
        }