예제 #1
0
        /// <summary>
        /// Flushes a table header to disk
        /// </summary>
        /// <param name="Path"></param>
        /// <param name="Key"></param>
        internal static void Flush(string Path, TableHeader Element)
        {
            // Convert to a hash //
            byte[] b = new byte[TableHeader.SIZE];
            TableHeader.ToHash(b, 0, Element);

            // Hit the disk //
            using (FileStream x = File.Open(Path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
            {
                x.Write(b, 0, b.Length);
            }
        }
예제 #2
0
        /// <summary>
        /// Reads the table header from disk, but does NOT allocate in the Spike heap
        /// </summary>
        /// <param name="Path"></param>
        /// <returns></returns>
        internal static TableHeader Buffer(string Path)
        {
            byte[] buffer = new byte[TableHeader.SIZE];
            using (FileStream x = File.Open(Path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                x.Read(buffer, 0, TableHeader.SIZE);
            }

            TableHeader h = TableHeader.FromHash(buffer, 0);

            return(h);
        }
예제 #3
0
        /// <summary>
        /// This method should be used for creating a table object from an existing table on disk
        /// </summary>
        /// <param name="Host"></param>
        /// <param name="Header"></param>
        /// <param name="ClusterKey"></param>
        public TreeTable(Host Host, TableHeader Header)
            : base(Host, Header)
        {
            if (Header.RootPageID == -1)
            {
                throw new ArgumentException("The root page ID cannot be null");
            }

            // Get the sort key //
            Key k = Header.ClusterKey;

            // Get the root page ID //
            Page root = this.GetPage(Header.RootPageID);

            // Cluster //
            BinaryRecordTree.TreeAffinity x = this._Header.ClusterKeyState;
            this._Cluster = new BinaryRecordTree(this, k, this.Columns, root, this.Header, x);

            this._TableType = "CLUSTER_SCRIBE";
        }
예제 #4
0
        /// <summary>
        /// Copies a table to a new directory
        /// </summary>
        /// <param name="Element"></param>
        /// <param name="NewDir"></param>
        /// <param name="NewName"></param>
        public void CopyTable(Table Element, string NewDir, string NewName)
        {
            // Need to save the current copy to disk //
            this.FlushTable(Element.Key);

            // Save the key //
            string OldPath = Element.Header.Path;
            string NewPath = TableHeader.DeriveV1Path(NewDir, NewName);

            // Copy the file //
            File.Copy(OldPath, NewPath);

            // Buffer the header //
            TableHeader h = Buffer(NewPath);

            // Change the dir and name //
            h.Directory = NewDir;
            h.Name      = NewName;

            // Save the header //
            Flush(NewPath, h);
        }
예제 #5
0
 /// <summary>
 /// This method should be used for creating a table object from an existing table on disk
 /// </summary>
 /// <param name="Host"></param>
 /// <param name="Header"></param>
 /// <param name="ClusterKey"></param>
 public ShellTable(Host Host, TableHeader Header)
     : base(Host, Header)
 {
     this._TableType = "HEAP_SCRIBE";
 }
예제 #6
0
        /// <summary>
        /// Converts a TableHeader to a byte array
        /// </summary>
        /// <param name="Buffer"></param>
        /// <param name="Location"></param>
        /// <param name="Key"></param>
        public static void ToHash(byte[] Buffer, int Location, TableHeader Element)
        {
            // Check the size //
            if (Buffer.Length - Location < TableHeader.SIZE)
            {
                throw new Exception("Buffer is incorrect size");
            }

            // Write the hash key //
            Array.Copy(BitConverter.GetBytes(HASH_KEY), 0, Buffer, Location + OFFSET_HASH_KEY, LEN_SIZE);

            // Write the name //
            Array.Copy(BitConverter.GetBytes(Element.Name.Length), 0, Buffer, Location + OFFSET_NAME_LEN, LEN_SIZE);
            Array.Copy(ASCIIEncoding.ASCII.GetBytes(Element.Name), 0, Buffer, Location + OFFSET_NAME, Element.Name.Length);

            // Write the directory //
            Array.Copy(BitConverter.GetBytes(Element.Directory.Length), 0, Buffer, Location + OFFSET_DIR_LEN, LEN_SIZE);
            Array.Copy(ASCIIEncoding.ASCII.GetBytes(Element.Directory), 0, Buffer, Location + OFFSET_DIR, Element.Directory.Length);

            // Write the extension //
            Array.Copy(BitConverter.GetBytes(Element.Extension.Length), 0, Buffer, Location + OFFSET_EXT_LEN, LEN_SIZE);
            Array.Copy(ASCIIEncoding.ASCII.GetBytes(Element.Extension), 0, Buffer, Location + OFFSET_EXT, Element.Extension.Length);

            // Write page count //
            Array.Copy(BitConverter.GetBytes(Element.PageCount), 0, Buffer, Location + OFFSET_PAGE_COUNT, LEN_SIZE);

            // Write record count //
            Array.Copy(BitConverter.GetBytes(Element.RecordCount), 0, Buffer, Location + OFFSET_RECORD_COUNT, 8); // Long integer

            // Write column count //
            Array.Copy(BitConverter.GetBytes(Element.Columns.Count), 0, Buffer, Location + OFFSET_COLUMN_COUNT, LEN_SIZE);

            // Write first page ID //
            Array.Copy(BitConverter.GetBytes(Element.OriginPageID), 0, Buffer, Location + OFFSET_FIRST_PAGE_ID, LEN_SIZE);

            // Write last page ID //
            Array.Copy(BitConverter.GetBytes(Element.TerminalPageID), 0, Buffer, Location + OFFSET_LAST_PAGE_ID, LEN_SIZE);

            // Write page size //
            Array.Copy(BitConverter.GetBytes(Element.PageSize), 0, Buffer, Location + OFFSET_PAGE_SIZE, LEN_SIZE);

            // Write radix page //
            Array.Copy(BitConverter.GetBytes(Element.RootPageID), 0, Buffer, Location + OFFSET_ROOT_PAGE_ID, LEN_SIZE);

            // Write key //
            Buffer[Location + OFFSET_SORT_KEY] = (byte)Element.ClusterKeyState;
            byte[] b = Element.ClusterKey.Bash();
            Array.Copy(b, 0, Buffer, Location + OFFSET_SORT_KEY + 4, b.Length);

            // Write the index table //
            Array.Copy(BitConverter.GetBytes(Element.IndexHeaders.Count), 0, Buffer, Location + OFFSET_INDEX_COUNT, LEN_SIZE);
            for (int i = 0; i < Element.IndexHeaders.Count; i++)
            {
                int pos = Location + OFFSET_INDEX_TABLE + i * IndexHeader.SIZE_HASH;
                IndexHeader.Write(Buffer, pos, Element.IndexHeaders[i]);
            }

            // Write schema //
            for (int i = 0; i < Element.Columns.Count; i++)
            {
                Cell c = new Cell((short)(Element.Columns.ColumnSize(i) * (Element.Columns.ColumnNull(i) ? 1 : -1)));

                byte   NameLen  = (byte)Element.Columns.ColumnName(i).Length;
                byte   Affinity = (byte)Element.Columns.ColumnAffinity(i);
                byte   Size1    = c.B0;
                byte   Size2    = c.B1;
                byte[] Name     = ASCIIEncoding.ASCII.GetBytes(Element.Columns.ColumnName(i));

                int ptr = Location + OFFSET_COLUMNS + i * COL_REC_LEN;
                Buffer[ptr + COL_NAME_LEN_PTR] = NameLen;
                Buffer[ptr + COL_AFFINITY]     = Affinity;
                Buffer[ptr + COL_SIZE]         = Size1;
                Buffer[ptr + COL_SIZE + 1]     = Size2;
                //Buffer[ptr + COL_NULL] = Nullness;
                Array.Copy(Name, 0, Buffer, ptr + COL_NAME_PTR, Name.Length);
            }
        }
예제 #7
0
        // Static Methods //
        /// <summary>
        /// Converts a byte array to a TableHeader
        /// </summary>
        /// <param name="Buffer"></param>
        /// <param name="Location"></param>
        /// <returns></returns>
        public static TableHeader FromHash(byte[] Buffer, int Location)
        {
            // Check the size //
            if (Buffer.Length - Location < TableHeader.SIZE)
            {
                throw new Exception("Buffer is incorrect size");
            }

            // Check the hash key //
            if (BitConverter.ToInt32(Buffer, Location + OFFSET_HASH_KEY) != HASH_KEY)
            {
                throw new Exception("Invalid hash key");
            }

            // Create //
            TableHeader h   = new TableHeader();
            int         Len = 0;

            // Alias //
            Len    = BitConverter.ToInt32(Buffer, Location + OFFSET_NAME_LEN);
            h.Name = ASCIIEncoding.ASCII.GetString(Buffer, Location + OFFSET_NAME, Len);

            // Directory //
            Len         = BitConverter.ToInt32(Buffer, Location + OFFSET_DIR_LEN);
            h.Directory = ASCIIEncoding.ASCII.GetString(Buffer, Location + OFFSET_DIR, Len);

            // Extension //
            Len         = BitConverter.ToInt32(Buffer, Location + OFFSET_EXT_LEN);
            h.Extension = ASCIIEncoding.ASCII.GetString(Buffer, Location + OFFSET_EXT, Len);

            // Page count //
            h.PageCount = BitConverter.ToInt32(Buffer, Location + OFFSET_PAGE_COUNT);

            // Row count //
            h.RecordCount = BitConverter.ToInt64(Buffer, Location + OFFSET_RECORD_COUNT);

            // Column Count //
            int ColCount = BitConverter.ToInt32(Buffer, Location + OFFSET_COLUMN_COUNT);

            // First Page //
            h.OriginPageID = BitConverter.ToInt32(Buffer, Location + OFFSET_FIRST_PAGE_ID);

            // Last Page //
            h.TerminalPageID = BitConverter.ToInt32(Buffer, Location + OFFSET_LAST_PAGE_ID);

            // Page PageSize //
            h.PageSize = BitConverter.ToInt32(Buffer, Location + OFFSET_PAGE_SIZE);

            // Radix Page //
            h.RootPageID = BitConverter.ToInt32(Buffer, Location + OFFSET_ROOT_PAGE_ID);

            // Key //
            h.ClusterKey      = new Key();
            h.ClusterKeyState = (BinaryRecordTree.TreeAffinity)Buffer[Location + OFFSET_SORT_KEY]; // gets the unique
            int KeyCount = BitConverter.ToInt32(Buffer, Location + OFFSET_SORT_KEY + 4);           // gets the key size

            for (int i = 0; i < KeyCount; i++)
            {
                int         loc      = Location + OFFSET_SORT_KEY + 8 + 8 * i;
                int         idx      = BitConverter.ToInt32(Buffer, loc);
                KeyAffinity affinity = (KeyAffinity)BitConverter.ToInt32(Buffer, loc + 4);
                h.ClusterKey.Add(idx, affinity);
            }

            // Read the index table //
            int idx_cnt = BitConverter.ToInt32(Buffer, Location + OFFSET_INDEX_COUNT);

            for (int i = 0; i < idx_cnt; i++)
            {
                int         pos   = Location + OFFSET_INDEX_TABLE + i * IndexHeader.SIZE_HASH;
                IndexHeader idx_h = IndexHeader.Read(Buffer, pos);
                h.IndexHeaders.Add(idx_h);
            }

            // Load the columns //
            h.Columns = new Schema();
            for (int i = 0; i < ColCount; i++)
            {
                int          RecordOffset = Location + OFFSET_COLUMNS + i * COL_REC_LEN;
                int          NameLen      = (int)Buffer[RecordOffset];
                string       ColName      = ASCIIEncoding.ASCII.GetString(Buffer, RecordOffset + COL_NAME_PTR, NameLen);
                CellAffinity ColType      = (CellAffinity)Buffer[RecordOffset + COL_AFFINITY];

                int  ColSize = (int)(BitConverter.ToInt16(Buffer, RecordOffset + COL_SIZE));
                bool ColNull = true;
                if (ColSize < 0)
                {
                    ColSize = -ColSize;
                    ColNull = false;
                }

                h.Columns.Add(ColName, ColType, ColSize, ColNull);
            }

            return(h);
        }
예제 #8
0
 // Clones //
 public static Table Clone(Table Element, string NewDirectory, string NewName)
 {
     Element.Host.TableStore.DropTable(TableHeader.DeriveV1Path(NewDirectory, NewName));
     return(new HeapTable(Element.Host, NewName, NewDirectory, Element.Columns, Element.PageSize));
 }
예제 #9
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="Host"></param>
 /// <param name="Path"></param>
 /// <param name="Columns"></param>
 /// <param name="PageSize"></param>
 public HeapTable(Host Host, string Path, Schema Columns, int PageSize)
     : this(Host, TableHeader.ExtractName(Path), TableHeader.ExtractDir(Path), Columns, Page.DEFAULT_SIZE)
 {
 }
예제 #10
0
 /// <summary>
 /// This method should be used for creating a table object from an existing table on disk
 /// </summary>
 /// <param name="Host"></param>
 /// <param name="Header"></param>
 /// <param name="ClusterKey"></param>
 public HeapTable(Host Host, TableHeader Header)
     : base(Host, Header)
 {
     this._Terminis  = this.GetPage(this._Header.TerminalPageID);
     this._TableType = "HEAP_SCRIBE";
 }
예제 #11
0
        /// <summary>
        /// Gets a table, either from memory or disk
        /// </summary>
        /// <param name="Key"></param>
        /// <returns></returns>
        public Table RequestTable(string Key)
        {
            // #DEBUG# //
            this._Host.DebugPrint("TableStore.RequestTable({0})", Key);
            this._Host.DebugDepth++;

            if (this.TableIsInMemory(Key))
            {
                // #DEBUG# //
                this._Host.DebugPrint("TableStore.RequestTable->Table in memory({0})", Key);

                return(this._TableStore[Key]);
            }
            else
            {
                // Get the header //
                TableHeader h = Buffer(Key);
                Table       t;

                // Create the actual table //
                if (h.RootPageID == -1)
                {
                    t = new HeapTable(this._Host, h);

                    // #DEBUG# //
                    this._Host.DebugPrint("TableStore.RequestTable->Table not in memory; buffering table as HEAP ({0})", Key);
                }
                else
                {
                    t = new TreeTable(this._Host, h);

                    // #DEBUG# //
                    this._Host.DebugPrint("TableStore.RequestTable->Table not in memory; buffering table as CLUSTER ({0})", Key);
                }

                // Add to the table store //
                this.PushTable(t);

                // Need to buffer a block of pages and make sure these pages are not in memory

                // Check to see how many pages we can buffer //
                int MaxPages = (int)(this.FreeMemory / h.PageSize);
                int Pages    = Math.Min(h.PageCount, MaxPages);

                // Buffer a block of pages //

                // #DEBUG# //
                this._Host.DebugPrint("TableStore.RequestTable->Buffering a block of pages ({0}); from {1} - {2} of {3}", Key, 0, Pages, h.PageCount);

                foreach (Page p in BufferBlock(h, 0, Pages))
                {
                    PageUID k = new PageUID(Key, p.PageID);
                    if (this._PageStore.ContainsKey(k))
                    {
                        this._PageStore[k] = p;
                    }
                    else
                    {
                        this._PageStore.Add(k, p);
                    }
                }
                this._Host.DebugDepth--;

                return(t);
            }
        }