Ejemplo n.º 1
0
        public void AddPreAllocatedBuffers(NewPageAllocator tablePageAllocator, bool includeDetails)
        {
            if (PreAllocatedBuffers != null)
            {
                throw new InvalidOperationException("Pre allocated buffers already defined");
            }

            PreAllocatedBuffers = StorageReportGenerator.GetReport(tablePageAllocator, includeDetails);

            AllocatedSpaceInBytes += PreAllocatedBuffers.AllocatedSpaceInBytes;

            if (includeDetails)
            {
                var allocationTree = PreAllocatedBuffers.AllocationTree;
                UsedSizeInBytes += (long)(allocationTree.AllocatedSpaceInBytes * allocationTree.Density);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// A table is stored inside a tree, and has the following keys in it
        ///
        /// - active-section -> page number - the page number of the current active small data section
        /// - inactive-sections -> fixed size tree with no content where the keys are the page numbers of inactive small raw data sections
        /// - large-values -> fixed size tree with no content where the keys are the page numbers of the large values
        /// - for each index:
        ///     - If can fit into fixed size tree, use that.
        ///     - Otherwise, create a tree (whose key would be the indexed field value and the value would
        ///         be a fixed size tree of the ids of all the matching values)
        ///  - stats -> header information about the table (number of entries, etc)
        ///  - schemas -> schema definition for the table
        ///
        /// </summary>
        public void Create(Transaction tx, Slice name, ushort?sizeInPages)
        {
            if (_primaryKey == null && _indexes.Count == 0 && _fixedSizeIndexes.Count == 0)
            {
                throw new InvalidOperationException($"Cannot create table {name} without a primary key and no indexes");
            }

            var tableTree = tx.CreateTree(name, RootObjectType.Table);

            if (tableTree.State.NumberOfEntries > 0)
            {
                return; // this was already created
            }
            // Create raw data. This is where we will actually store the documents
            using (var rawDataActiveSection = ActiveRawDataSmallSection.Create(tx.LowLevelTransaction, name, TableType, sizeInPages))
            {
                long  val = rawDataActiveSection.PageNumber;
                Slice pageNumber;
                using (
                    Slice.External(tx.Allocator, (byte *)&val, sizeof(long), ByteStringType.Immutable, out pageNumber))
                {
                    tableTree.Add(ActiveSectionSlice, pageNumber);
                }

                byte *ptr;
                using (tableTree.DirectAdd(StatsSlice, sizeof(TableSchemaStats), out ptr))
                {
                    var stats = (TableSchemaStats *)ptr;
                    stats->NumberOfEntries = 0;
                }

                var tablePageAllocator = new NewPageAllocator(tx.LowLevelTransaction, tableTree);
                tablePageAllocator.Create();

                var globalPageAllocator = new NewPageAllocator(tx.LowLevelTransaction,
                                                               tx.LowLevelTransaction.RootObjects);
                globalPageAllocator.Create();

                if (_primaryKey != null)
                {
                    if (_primaryKey.IsGlobal == false)
                    {
                        using (var indexTree = Tree.Create(tx.LowLevelTransaction, tx, _primaryKey.Name, isIndexTree: true, newPageAllocator: tablePageAllocator))
                        {
                            using (tableTree.DirectAdd(_primaryKey.Name, sizeof(TreeRootHeader), out ptr))
                            {
                                indexTree.State.CopyTo((TreeRootHeader *)ptr);
                            }
                        }
                    }
                    else
                    {
                        tx.CreateTree(_primaryKey.Name.ToString(), isIndexTree: true, newPageAllocator: globalPageAllocator);
                    }
                }

                foreach (var indexDef in _indexes.Values)
                {
                    if (indexDef.IsGlobal == false)
                    {
                        using (var indexTree = Tree.Create(tx.LowLevelTransaction, tx, indexDef.Name, isIndexTree: true, newPageAllocator: tablePageAllocator))
                        {
                            using (tableTree.DirectAdd(indexDef.Name, sizeof(TreeRootHeader), out ptr))
                            {
                                indexTree.State.CopyTo((TreeRootHeader *)ptr);
                            }
                        }
                    }
                    else
                    {
                        tx.CreateTree(indexDef.Name.ToString(), isIndexTree: true, newPageAllocator: globalPageAllocator);
                    }
                }

                // Serialize the schema into the table's tree
                var serializer = SerializeSchema();

                using (tableTree.DirectAdd(SchemasSlice, serializer.Length, out ptr))
                {
                    fixed(byte *source = serializer)
                    {
                        Memory.Copy(ptr, source, serializer.Length);
                    }
                }
            }
        }