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

📄 storageimpl.cs

📁 Perst开源实时数据库
💻 CS
📖 第 1 页 / 共 5 页
字号:
namespace Perst.Impl    
{
    using System;
    using System.Collections;
    using System.Reflection;
    using System.Threading;
    using System.Diagnostics;
    using System.Text;
    using System.IO;
    using Perst;
#if USE_GENERICS
    using System.Collections.Generic;
#endif
	
    public class StorageImpl:Storage
    {
        public const int DEFAULT_PAGE_POOL_SIZE = 4*1024*1024;

#if COMPACT_NET_FRAMEWORK
        static StorageImpl() 
        {
            assemblies = new System.Collections.ArrayList();
        }
        public StorageImpl(Assembly callingAssembly) 
        {
            if (!assemblies.Contains(callingAssembly))
            {
                assemblies.Add(callingAssembly);
            }

            if (!assemblies.Contains(Assembly.GetExecutingAssembly()))
            {
                assemblies.Add(Assembly.GetExecutingAssembly());
            }
#if FRAMEWORK_2
            Assembly mscorlib = Assembly.GetAssembly(typeof(System.String));
            if (!assemblies.Contains(mscorlib))
            {
                assemblies.Add(mscorlib);
            }
#endif
        }
#endif

        public IPersistent Root
        {
            get
            {
                lock(this)
                {
                    if (!opened)
                    {
                        throw new StorageError(StorageError.ErrorCode.STORAGE_NOT_OPENED);
                    }
                    int rootOid = header.root[1 - currIndex].rootObject;
                    return (rootOid == 0) ? null : lookupObject(rootOid, null);
                }
            }
			
            set
            {
                lock(this)
                {
                    if (!opened)
                    {
                        throw new StorageError(StorageError.ErrorCode.STORAGE_NOT_OPENED);
                    }
                    if (value == null) 
                    {
                        header.root[1 - currIndex].rootObject = 0;
                    }
                    else 
                    {
                        if (!value.IsPersistent())
                        {
                            storeObject0(value, false);
                        }
                        header.root[1 - currIndex].rootObject = value.Oid;
                    }
                    modified = true;
                }
            }
			
        }
 
        /// <summary> Initialial database index size - increasing it reduce number of inde reallocation but increase
        /// initial database size. Should be set before openning connection.
        /// </summary>
        const int dbDefaultInitIndexSize = 1024;
		
        /// <summary> Initial capacity of object hash
        /// </summary>
        const int dbDefaultObjectCacheInitSize = 1319;
		
        /// <summary> Database extension quantum. Memory is allocate by scanning bitmap. If there is no
        /// large enough hole, then database is extended by the value of dbDefaultExtensionQuantum 
        /// This parameter should not be smaller than dbFirstUserId
        /// </summary>
        static long dbDefaultExtensionQuantum = 1024 * 1024;

        const long dbDefaultPagePoolLruLimit = 1L << 60;

        const int dbDatabaseOffsetBits = 32; // up to 4 gigabyte
        const int dbLargeDatabaseOffsetBits = 40; // up to 1 terabyte
		
        internal const int dbAllocationQuantumBits = 5;
        internal const int dbAllocationQuantum = 1 << dbAllocationQuantumBits;

        const int dbBitmapSegmentBits = Page.pageSizeLog + 3 + dbAllocationQuantumBits;
        const int dbBitmapSegmentSize = 1 << dbBitmapSegmentBits;
        const int dbBitmapPages = 1 << (dbDatabaseOffsetBits - dbBitmapSegmentBits);
        const int dbLargeBitmapPages = 1 << (dbLargeDatabaseOffsetBits - dbBitmapSegmentBits);
        const int dbHandlesPerPageBits = Page.pageSizeLog - 3;
        const int dbHandlesPerPage = 1 << dbHandlesPerPageBits;
        const int dbDirtyPageBitmapSize = 1 << (32 - dbHandlesPerPageBits - 3);
		
        const int dbInvalidId = 0;
        const int dbBitmapId = 1;
        const int dbFirstUserId = dbBitmapId + dbBitmapPages;
		
        internal const int dbPageObjectFlag = 1;
        internal const int dbModifiedFlag = 2;
        internal const int dbFreeHandleFlag = 4;
        internal const int dbFlagsMask = 7;
        internal const int dbFlagsBits = 3;
		
         
        int getBitmapPageId(int i) 
        { 
            return i < dbBitmapPages ? dbBitmapId + i : header.root[1-currIndex].bitmapExtent + i;
        }

        internal long getPos(int oid)
        {
            lock (objectCache) 
            {
                if (oid == 0 || oid >= currIndexSize)
                {
                    throw new StorageError(StorageError.ErrorCode.INVALID_OID);
                }
                Page pg = pool.getPage(header.root[1 - currIndex].index + ((long)(oid >> dbHandlesPerPageBits) << Page.pageSizeLog));
                long pos = Bytes.unpack8(pg.data, (oid & (dbHandlesPerPage - 1)) << 3);
                pool.unfix(pg);
                return pos;
            }
        }
		
        internal void  setPos(int oid, long pos)
        {
            lock (objectCache) 
            {
                dirtyPagesMap[oid >> (dbHandlesPerPageBits + 5)] |= 1 << ((oid >> dbHandlesPerPageBits) & 31);
                Page pg = pool.putPage(header.root[1 - currIndex].index + ((long)(oid >> dbHandlesPerPageBits) << Page.pageSizeLog));
                Bytes.pack8(pg.data, (oid & (dbHandlesPerPage - 1)) << 3, pos);
                pool.unfix(pg);
            }
        }
		
        internal byte[] get(int oid)
        {
            long pos = getPos(oid);
            if ((pos & (dbFreeHandleFlag | dbPageObjectFlag)) != 0)
            {
                throw new StorageError(StorageError.ErrorCode.INVALID_OID);
            }
            return pool.get(pos & ~ dbFlagsMask);
        }
		
        internal Page getPage(int oid)
        {
            long pos = getPos(oid);
            if ((pos & (dbFreeHandleFlag | dbPageObjectFlag)) != dbPageObjectFlag)
            {
                throw new StorageError(StorageError.ErrorCode.DELETED_OBJECT);
            }
            return pool.getPage(pos & ~ dbFlagsMask);
        }
		
        internal Page putPage(int oid)
        {
            lock (objectCache) 
            {
                long pos = getPos(oid);
                if ((pos & (dbFreeHandleFlag | dbPageObjectFlag)) != dbPageObjectFlag)
                {
                    throw new StorageError(StorageError.ErrorCode.DELETED_OBJECT);
                }
                if ((pos & dbModifiedFlag) == 0)
                {
                    dirtyPagesMap[oid >> (dbHandlesPerPageBits + 5)] |= 1 << ((oid >> dbHandlesPerPageBits) & 31);
                    allocate(Page.pageSize, oid);
                    cloneBitmap(pos & ~ dbFlagsMask, Page.pageSize);
                    pos = getPos(oid);
                }
                modified = true;
                return pool.putPage(pos & ~ dbFlagsMask);
            }
        }
		
		
        internal int allocatePage()
        {
            int oid = allocateId();
            setPos(oid, allocate(Page.pageSize, 0) | dbPageObjectFlag | dbModifiedFlag);
            return oid;
        }
		
        public void  deallocateObject(IPersistent obj)
        {
            lock(this)
            {
                lock (objectCache) 
                { 
                    if ( obj.Oid == 0) 
                    { 
                        return;
                    }       
                    if (useSerializableTransactions) 
                    { 
                        ThreadTransactionContext ctx = TransactionContext;
                        if (ctx.nested != 0) 
                        { // serializable transaction
                            ctx.deleted.Add(obj);  
                            return;
                        }
                    }
                    deallocateObject0(obj);
                }
            }
        }
    

        private void deallocateObject0(IPersistent obj)
        {                    
            int oid = obj.Oid;
            long pos = getPos(oid);
            objectCache.remove(oid);
            int offs = (int) pos & (Page.pageSize - 1);
            if ((offs & (dbFreeHandleFlag | dbPageObjectFlag)) != 0)
            {
                throw new StorageError(StorageError.ErrorCode.DELETED_OBJECT);
            }
            Page pg = pool.getPage(pos - offs);
            offs &= ~ dbFlagsMask;
            int size = ObjectHeader.getSize(pg.data, offs);
            pool.unfix(pg);
            freeId(oid);
            CustomAllocator allocator = (customAllocatorMap != null) 
                ? getCustomAllocator(obj.GetType()) : null;
            if (allocator != null) 
            { 
                allocator.Free(pos & ~dbFlagsMask, size);
            } 
            else 
            { 
                if ((pos & dbModifiedFlag) != 0) 
                {
                    free(pos & ~ dbFlagsMask, size);
                }
                else
                {
                    cloneBitmap(pos, size);
                }
            }
            obj.AssignOid(null, 0, false);
        }
    		
        internal void  freePage(int oid)
        {
            long pos = getPos(oid);
            Debug.Assert((pos & (dbFreeHandleFlag | dbPageObjectFlag)) == dbPageObjectFlag);
            if ((pos & dbModifiedFlag) != 0)
            {
                free(pos & ~ dbFlagsMask, Page.pageSize);
            }
            else
            {
                cloneBitmap(pos & ~ dbFlagsMask, Page.pageSize);
            }
            freeId(oid);
        }
		
        virtual protected bool isDirty()
        { 
            return header.dirty;
        } 	


        internal void setDirty() 
        {
            modified = true;
            if (!header.dirty) 
            { 
                header.dirty = true;
                Page pg = pool.putPage(0);

⌨️ 快捷键说明

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