⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 database.cs

📁 Perst开源实时数据库
💻 CS
📖 第 1 页 / 共 2 页
字号:
#if !USE_GENERICS

namespace Perst
{
    using System;
    using System.Collections;
    using Perst.Impl;

    /// <summary>
    /// This class emulates relational database on top of Perst storage
    /// It maintain class extends, associated indices, prepare queries.
    /// </summary>
    public class Database 
    { 
        /// <summary> 
        /// Constructor of database. This method initialize database if it not initialized yet.
        /// </summary>
        /// <param name="storage">opened storage. Storage should be either empty (non-initialized, either
        /// previously initialized by the this method. It is not possible to open storage with 
        /// root object other than table index created by this constructor.
        /// </param>
        /// <param name="multithreaded"><code>true</code> if database should support concurrent access
        /// to the data from multiple threads</param>
        public Database(Storage storage, bool multithreaded) 
        { 
            this.storage = storage;
            this.multithreaded = multithreaded;
            metadata = (Index)storage.Root;
            if (metadata == null) 
            { 
                metadata = storage.CreateIndex(typeof(string), true);
                storage.Root = metadata;
            }
            tables = new Hashtable();
            IDictionaryEnumerator e = metadata.GetDictionaryEnumerator();
            while (e.MoveNext())
            {
                Type table = ClassDescriptor.lookup(storage, (string)e.Key);
                tables[table] = (Table)e.Value;
            }                
        }
        
        /// <summary> 
        /// Constructor of single threaded database. This method initialize database if it not initialized yet.
        /// </summary>
        /// <param name="storage">opened storage. Storage should be either empty (non-initialized, either
        /// previously initialized by the this method. It is not possible to open storage with 
        /// root object other than table index created by this constructor.
        /// </param>
        public Database(Storage storage) 
        : this(storage, false)
        {
        }

        /// <summary>
        /// Create table for the specified class.
        /// This function does nothing if table for such class already exists
        /// </summary>
        /// <param name="table">class corresponding to the table
        /// </param>
        /// <returns> <code>true</code> if table is created, <code>false</code> if table 
        /// alreay exists
        /// </returns>
        public bool CreateTable(Type table) 
        { 
            if (multithreaded) 
            { 
                metadata.ExclusiveLock();
            }
            if (!tables.ContainsKey(table)) 
            { 
                Table t = new Table();
                t.extent = storage.CreateSet();
                t.indices = storage.CreateLink();
                t.indicesMap = new Hashtable();
                tables[table] = t;
                metadata[table.FullName] = t;
                return true;
            }
            return false;
        }
               
        /// <summary>
        /// Drop table associated with this class. Do nothing if there is no such table in the database.
        /// </summary>
        /// <param name="table">class corresponding to the table
        /// </param>
        /// <returns> <code>true</code> if table is deleted, <code>false</code> if table 
        /// is not found
        /// </returns>
        public bool DropTable(Type table) 
        { 
            if (multithreaded) 
            { 
                metadata.ExclusiveLock();
            }
            if (tables.ContainsKey(table)) 
            { 
                tables.Remove(table);
                metadata.Remove(table.FullName);
                return true;
            }
            return false;
        }
        
        /// <summary>
        /// Add new record to the table. Record is inserted in table corresponding to the class of the object.
        /// Record will be automatically added to all indices existed for this table.
        /// If there is not table associated with class of this object, then 
        /// database will search for table associated with superclass and so on...
        /// </summary>
        /// <param name="record">object to be inserted in the table</param>
        /// <returns> <code>true</code> if record was successfully added to the table, <code>false</code>
        /// if there is already such record (object with the same ID) in the table
        /// </returns>
        /// <exception cref="StorageError"> StorageError(CLASS_NOT_FOUND) exception is thrown if there is no table corresponding to 
        /// record class
        /// </exception>
        public bool AddRecord(IPersistent record) 
        { 
            return AddRecord(record.GetType(), record);        
        }

        private Table locateTable(Type cls, bool exclusive) 
        { 
            Table table = null;
            if (multithreaded) 
            { 
                metadata.SharedLock();
            }
            for (Type c = cls; c != null && (table = (Table)tables[c]) == null; c = c.BaseType);
            if (table == null) 
            { 
                throw new StorageError(StorageError.ErrorCode.CLASS_NOT_FOUND, cls.FullName);
            }
            if (exclusive)
            {
                table.extent.ExclusiveLock();
            }
            else 
            {
                table.extent.SharedLock();
            }            
            return table;
        }

        /// <summary>
        /// Add new record to the specified table. Record is inserted in table corresponding to the specified class.
        /// Record will be automatically added to all indices existed for this table.
        /// </summary>
        /// <param name="table">class corresponding to the table
        /// </param>
        /// <param name="record">object to be inserted in the table
        /// </param>
        /// <returns> <code>true</code> if record was successfully added to the table, <code>false</code>
        /// if there is already such record (object with the same ID) in the table
        /// </returns>
        /// <exception cref="StorageError">StorageError(CLASS_NOT_FOUND) exception is thrown if there is no table corresponding to 
        /// record class
        /// </exception>
        public bool AddRecord(Type table, IPersistent record) 
        { 
            bool added = false;
            bool found = false;
            if (multithreaded) 
            { 
                metadata.SharedLock();
            }
            for (Type c = table; c != null; c = c.BaseType) 
            { 
                Table t = (Table)tables[c];
                if (t != null) 
                { 
                    found = true;
                    if (multithreaded) 
                    { 
                        t.extent.ExclusiveLock();
                    }
                    if (!t.extent.Contains(record)) 
                    { 
                        t.extent.Add(record);
                        foreach (FieldIndex index in t.indicesMap.Values) 
                        {
                            index.Put(record);
                        }
                        added = true;
                    }
                }
            }
            if (!found) 
            { 
                throw new StorageError(StorageError.ErrorCode.CLASS_NOT_FOUND, table.FullName);
            }            
            return added;
        }

        
        /// <summary> 
        /// Delete record from the table. Record is removed from the table corresponding to the class 
        /// of the object. Record will be automatically added to all indices existed for this table.
        /// If there is not table associated with class of this object, then 
        /// database will search for table associated with superclass and so on...
        /// Object represented the record will be also deleted from the storage.
        /// </summary>
        /// <param name="record">object to be deleted from the table
        /// </param>
        /// <returns> <code>true</code> if record was successfully deleted from the table, <code>false</code>
        /// if there is not such record (object with the same ID) in the table
        /// </returns>
        /// <exception cref="StorageError">StorageError(CLASS_NOT_FOUND) exception is thrown if there is no table corresponding to 
        /// record class
        /// </exception>
        public bool DeleteRecord(IPersistent record) 
        { 
            return DeleteRecord(record.GetType(), record);
        }

        /// <summary> 
        /// Delete record from the specified table. Record is removed from the table corresponding to the 
        /// specified class. Record will be automatically added to all indices existed for this table.
        /// Object represented the record will be also deleted from the storage.
        /// </summary>
        /// <param name="table">class corresponding to the table
        /// </param>
        /// <param name="record">object to be deleted from the table
        /// </param>
        /// <returns> <code>true</code> if record was successfully deleted from the table, <code>false</code>
        /// if there is not such record (object with the same ID) in the table
        /// </returns>
        /// <exception cref="StorageError">StorageError(CLASS_NOT_FOUND) exception is thrown if there is no table corresponding to 
        /// specified class
        /// </exception>
        public bool DeleteRecord(Type table, IPersistent record) 
        { 
            bool removed = false;
            bool found = false;
            if (multithreaded) 
            { 
                metadata.SharedLock();
            }
            for (Type c = table; c != null; c = c.BaseType) 
            { 
                Table t = (Table)tables[c];
                if (t != null) 
                { 
                    found = true;
                    if (t.extent.Contains(record)) 
                    { 
                        if (multithreaded) 
                        { 
                            t.extent.ExclusiveLock();
                        }
                        t.extent.Remove(record);
                        foreach (FieldIndex index in t.indicesMap.Values) 
                        {
                            index.Remove(record);
                        }
                        removed = true;
                    }
                }
            }
            if (!found) 
            { 
                throw new StorageError(StorageError.ErrorCode.CLASS_NOT_FOUND, table.FullName);
            }            
            if (removed) 
            {
                record.Deallocate();
            }
            return removed;
        }
    
        /// <summary>
        /// Add new index to the table. If such index already exists this method does nothing.
        /// </summary>
        /// <param name="table">class corresponding to the table
        /// </param>
        /// <param name="key">field of the class to be indexed
        /// </param>
        /// <param name="unique">if index is unique or not
        /// </param>
        /// <exception cref="StorageError">StorageError(CLASS_NOT_FOUND) exception is thrown if there is no table corresponding to 
        /// the specified class
        /// </exception>
        /// <returns> <code>true</code> if index is created, <code>false</code> if index
        /// already exists
        /// </returns>
        public bool CreateIndex(Type table, string key, bool unique) 
        { 
            Table t = locateTable(table, true);
            if (!t.indicesMap.ContainsKey(key)) 
            { 
                FieldIndex index = storage.CreateFieldIndex(table, key, unique);
                t.indicesMap[key] = index;
                t.indices.Add(index);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Drop index for the specified table and key.
        /// Does nothing if there is no such index.
        /// </summary>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -