示例#1
0
 static void walShmBarrier(Wal wal)
 {
     if (wal.ExclusiveMode_ != MODE.HEAPMEMORY)
     {
         wal.DBFile.ShmBarrier();
     }
 }
示例#2
0
        static RC walHashGet(Wal wal, Pid id, ht_slot[] hashOut, Pid[] idsOut, out uint zeroOut)
        {
            object ids;
            RC     rc = walIndexPage(wal, id, ref ids);

            Debug.Assert(rc == RC.OK || id > 0);

            if (rc == RC.OK)
            {
                Pid zero;
                var hash = (ht_slot)ids[HASHTABLE_NPAGE];
                if (id == 0)
                {
                    ids  = &ids[WALINDEX_HDR_SIZE / sizeof(Pid)];
                    zero = 0;
                }
                else
                {
                    zero = (uint)(HASHTABLE_NPAGE_ONE + (id - 1) * HASHTABLE_NPAGE);
                }

                idsOut  = &ids[-1];
                hashOut = hash;
                zeroOut = zero;
            }
            return(rc);
        }
示例#3
0
 static void walUnlockShared(Wal wal, int lockIdx)
 {
     if (wal.ExclusiveMode_ != MODE.NORMAL)
     {
         return;
     }
     wal.DBFile.ShmLock(lockIdx, 1, VFile.SHM.UNLOCK | VFile.SHM.SHARED);
     WALTRACE("WAL%p: release SHARED-%s\n", wal, walLockName(lockIdx));
 }
示例#4
0
 static void walUnlockExclusive(Wal wal, int lockIdx, int n)
 {
     if (wal.ExclusiveMode_ != MODE.NORMAL)
     {
         return;
     }
     wal.DBFile.ShmLock(lockIdx, n, VFile.SHM.UNLOCK | VFile.SHM.EXCLUSIVE);
     WALTRACE("WAL%p: release EXCLUSIVE-%s cnt=%d\n", wal, walLockName(lockIdx), n);
 }
示例#5
0
        static uint walFramePgno(Wal wal, uint frame)
        {
            int hash = walFramePage(frame);

            if (hash == 0)
            {
                return(wal.WiData[0][WALINDEX_HDR_SIZE / sizeof(uint) + frame - 1]);
            }
            return(wal.WiData[hash][(frame - 1 - HASHTABLE_NPAGE_ONE) % HASHTABLE_NPAGE]);
        }
示例#6
0
        static void walCleanupHash(Wal wal)
        {
            Debug.Assert(wal.WriteLock);

            if (wal.Header.MaxFrame == 0)
            {
                return;
            }

            // Obtain pointers to the hash-table and page-number array containing the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
            // that the page said hash-table and array reside on is already mapped.
            Debug.Assert(wal.WiData.Length > walFramePage(wal.Header.MaxFrame));
            Debug.Assert(wal.WiData[walFramePage(wal.Header.MaxFrame)] != 0);
            ht_slot[] hash = null; // Pointer to hash table to clear
            Pid[]     ids  = null; // Page number array for hash table
            int       zero = 0;    // frame == (aHash[x]+iZero)

            walHashGet(wal, walFramePage(wal.Header.MaxFrame), ref hash, ref ids, ref zero);

            // Zero all hash-table entries that correspond to frame numbers greater than pWal->hdr.mxFrame.
            int limit = wal.Header.MaxFrame - zero; // Zero values greater than this

            Debug.Assert(limit > 0);
            for (int i = 0; i < HASHTABLE_NSLOT; i++)
            {
                if (hash[i] > limit)
                {
                    hash[i] = 0;
                }
            }

            // Zero the entries in the aPgno array that correspond to frames with frame numbers greater than pWal->hdr.mxFrame.
            int bytes = (int)((char *)hash - (char *)&ids[limit + 1]); // Number of bytes to zero in aPgno[]

            _memset((void *)&ids[limit + 1], 0, bytes);

#if ENABLE_EXPENSIVE_ASSERT
            // Verify that the every entry in the mapping region is still reachable via the hash table even after the cleanup.
            int key;     // Hash key
            if (limit)
            {
                for (int i = 1; i <= limit; i++)
                {
                    for (key = walHash(ids[i]); hash[key]; key = walNextHash(key))
                    {
                        if (hash[key] == i)
                        {
                            break;
                        }
                    }
                    _assert(hash[key] == i);
                }
            }
#endif
        }
示例#7
0
        static RC walLockExclusive(Wal wal, int lockIdx, int n)
        {
            if (wal.ExclusiveMode_ != MODE.NORMAL)
            {
                return(RC.OK);
            }
            RC rc = wal.DBFile.ShmLock(lockIdx, n, VFile.SHM.LOCK | VFile.SHM.EXCLUSIVE);

            WALTRACE("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", wal, walLockName(lockIdx), n, rc != 0 ? "failed" : "ok");
            return(rc);
        }
示例#8
0
        static RC walLockShared(Wal wal, int lockIdx)
        {
            if (wal.ExclusiveMode_ != MODE.NORMAL)
            {
                return(RC.OK);
            }
            RC rc = wal.DBFile.ShmLock(lockIdx, 1, VFile.SHM.LOCK | VFile.SHM.SHARED);

            WALTRACE("WAL%p: acquire SHARED-%s %s\n", wal, walLockName(lockIdx), rc != 0 ? "failed" : "ok");
            return(rc);
        }
示例#9
0
        static void walIndexWriteHdr(Wal wal)
        {
            var header = walIndexHeader(wal, 0);

            Debug.Assert(wal.WriteLock != 0);
            wal.Header.IsInit  = true;
            wal.Header.Version = WALINDEX_MAX_VERSION;
            walChecksumBytes(true, wal.Header, null, wal.Header.Checksum);
            wal.Header = header[1].copy();
            walShmBarrier(wal);
            wal.Header = header[0].copy();
        }
示例#10
0
        static void walEncodeFrame(Wal wal, Pid id, uint truncate, byte[] data, byte[] frame)
        {
            var checksum = wal.Header.FrameChecksum;

            Debug.Assert(WAL_FRAME_HDRSIZE == 24);
            ConvertEx.Put4(frame, 0, id);
            ConvertEx.Put4(frame, 4, truncate);
            Buffer.BlockCopy(frame, 8, wal.Header.Salt, 0, 8);

            bool nativeChecksum = true; // (wal.Header.BigEndianChecksum == TYPE_BIGENDIAN); // True for native byte-order checksums

            walChecksumBytes(nativeChecksum, frame, 8, checksum, checksum);
            walChecksumBytes(nativeChecksum, data, (int)wal.SizePage, checksum, checksum);

            ConvertEx.Put4(frame, 16, checksum[0]);
            ConvertEx.Put4(frame, 20, checksum[1]);
        }
示例#11
0
        static RC walIndexPage(Wal wal, Pid id, ref object idOut)
        {
            // Enlarge the pWal->apWiData[] array if required
            if (wal.WiData.Length <= id)
            {
                var bytes     = (int)(1 * (id + 1));
                var newWiData = SysEx.Realloc <object>(1, wal.WiData, bytes);
                if (newWiData != null)
                {
                    idOut = null;
                    return(RC.NOMEM);
                }
                Array.Clear(newWiData, wal.WiData.Length, (int)(id + 1 - wal.WiData.Length));
                wal.WiData = newWiData;
            }

            // Request a pointer to the required page from the VFS
            var rc = RC.OK;

            if (wal.WiData[id] == null)
            {
                if (wal.ExclusiveMode_ == Wal.MODE.HEAPMEMORY)
                {
                    wal.WiData[id] = C._alloc <Pid>(4, WALINDEX_PGSZ, true);
                    if (wal.WiData[id] != null)
                    {
                        rc = RC.NOMEM;
                    }
                }
                else
                {
                    rc = wal.DBFile.ShmMap((int)id, WALINDEX_PGSZ, (int)wal.WriteLock, wal.WiData, (int)id);
                    if (rc == RC.READONLY)
                    {
                        wal.ReadOnly_ |= READONLY.SHM_RDONLY;
                        rc             = RC.OK;
                    }
                }
            }

            idOut = wal.WiData[id];
            Debug.Assert(id == 0 || idOut != null || rc != RC.OK);
            return(rc);
        }
示例#12
0
        static bool walDecodeFrame(Wal wal, Pid idOut, uint truncateOut, byte[] data, byte[] frame)
        {
            var checksum = wal.Header.FrameChecksum;

            Debug.Assert(WAL_FRAME_HDRSIZE == 24);

            // A frame is only valid if the salt values in the frame-header match the salt values in the wal-header.
            var testFrame = new byte[8];

            Buffer.BlockCopy(frame, 8, testFrame, 0, 8);
            if (Enumerable.SequenceEqual(wal.Header.Salt, testFrame))
            {
                return(false);
            }

            // A frame is only valid if the page number is creater than zero.
            Pid id = ConvertEx.Get4(frame, 0); // Page number of the frame

            if (id == 0)
            {
                return(false);
            }

            // A frame is only valid if a checksum of the WAL header, all prior frams, the first 16 bytes of this frame-header,
            // and the frame-data matches the checksum in the last 8 bytes of this frame-header.
            bool nativeChecksum = true; // (wal.Header.BigEndianChecksum == TYPE_BIGENDIAN); // True for native byte-order checksums

            walChecksumBytes(nativeChecksum, frame, 8, checksum, checksum);
            walChecksumBytes(nativeChecksum, data, (int)wal.SizePage, checksum, checksum);
            if (checksum[0] != ConvertEx.Get4(frame, 16) || checksum[1] != ConvertEx.Get4(frame, 20)) // Checksum failed.
            {
                return(false);
            }

            // If we reach this point, the frame is valid.  Return the page number and the new database size.
            idOut       = id;
            truncateOut = ConvertEx.Get4(frame, 4);
            return(true);
        }
示例#13
0
文件: Wal.cs 项目: BclEx/GpuData
 static void walShmBarrier(Wal wal)
 {
     if (wal.ExclusiveMode_ != MODE.HEAPMEMORY)
         wal.DBFile.ShmBarrier();
 }
示例#14
0
文件: Wal.cs 项目: BclEx/GpuData
 static RC walLockShared(Wal wal, int lockIdx)
 {
     if (wal.ExclusiveMode_ != MODE.NORMAL) return RC.OK;
     RC rc = wal.DBFile.ShmLock(lockIdx, 1, VFile.SHM.LOCK | VFile.SHM.SHARED);
     WALTRACE("WAL%p: acquire SHARED-%s %s\n", wal, walLockName(lockIdx), rc != 0 ? "failed" : "ok");
     return rc;
 }
示例#15
0
文件: Wal.cs 项目: BclEx/GpuData
 static RC walLockExclusive(Wal wal, int lockIdx, int n)
 {
     if (wal.ExclusiveMode_ != MODE.NORMAL) return RC.OK;
     RC rc = wal.DBFile.ShmLock(lockIdx, n, VFile.SHM.LOCK | VFile.SHM.EXCLUSIVE);
     WALTRACE("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", wal, walLockName(lockIdx), n, rc != 0 ? "failed" : "ok");
     return rc;
 }
示例#16
0
文件: Wal.cs 项目: BclEx/GpuData
        static void walIndexWriteHdr(Wal wal)
        {
            var header = walIndexHeader(wal, 0);

            Debug.Assert(wal.WriteLock != 0);
            wal.Header.IsInit = true;
            wal.Header.Version = WALINDEX_MAX_VERSION;
            walChecksumBytes(true, wal.Header, null, wal.Header.Checksum);
            wal.Header = header[1].copy();
            walShmBarrier(wal);
            wal.Header = header[0].copy();
        }
示例#17
0
文件: Wal.cs 项目: BclEx/GpuData
        static RC walIndexPage(Wal wal, Pid id, ref object idOut)
        {
            // Enlarge the pWal->apWiData[] array if required
            if (wal.WiData.Length <= id)
            {
                var bytes = (int)(1 * (id + 1));
                var newWiData = SysEx.Realloc<object>(1, wal.WiData, bytes);
                if (newWiData != null)
                {
                    idOut = null;
                    return RC.NOMEM;
                }
                Array.Clear(newWiData, wal.WiData.Length, (int)(id + 1 - wal.WiData.Length));
                wal.WiData = newWiData;
            }

            // Request a pointer to the required page from the VFS
            var rc = RC.OK;
            if (wal.WiData[id] == null)
            {
                if (wal.ExclusiveMode_ == Wal.MODE.HEAPMEMORY)
                {
                    wal.WiData[id] = SysEx.Alloc<Pid>(4, WALINDEX_PGSZ, true);
                    if (wal.WiData[id] != null) rc = RC.NOMEM;
                }
                else
                {
                    rc = wal.DBFile.ShmMap((int)id, WALINDEX_PGSZ, (int)wal.WriteLock, wal.WiData, (int)id);
                    if (rc == RC.READONLY)
                    {
                        wal.ReadOnly_ |= READONLY.SHM_RDONLY;
                        rc = RC.OK;
                    }
                }
            }

            idOut = wal.WiData[id];
            Debug.Assert(id == 0 || idOut != null || rc != RC.OK);
            return rc;
        }
示例#18
0
文件: Wal.cs 项目: BclEx/GpuData
 static WalIndexHeader[] walIndexHeader(Wal wal, int idx)
 {
     Debug.Assert(wal.WiData.Length > 0 && wal.WiData[0] != null);
     return (WalIndexHeader[])wal.WiData[0];
 }
示例#19
0
文件: Wal.cs 项目: BclEx/GpuData
        static RC walHashGet(Wal wal, Pid id, ht_slot[] hashOut, Pid[] idsOut, out uint zeroOut)
        {
            object ids;
            RC rc = walIndexPage(wal, id, ref ids);
            Debug.Assert(rc == RC.OK || id > 0);

            if (rc == RC.OK)
            {
                Pid zero;
                var hash = (ht_slot)ids[HASHTABLE_NPAGE];
                if (id == 0)
                {
                    ids = &ids[WALINDEX_HDR_SIZE / sizeof(Pid)];
                    zero = 0;
                }
                else
                    zero = (uint)(HASHTABLE_NPAGE_ONE + (id - 1) * HASHTABLE_NPAGE);

                idsOut = &ids[-1];
                hashOut = hash;
                zeroOut = zero;
            }
            return rc;
        }
示例#20
0
文件: Wal.cs 项目: BclEx/GpuData
 static uint walFramePgno(Wal wal, uint frame)
 {
     int hash = walFramePage(frame);
     if (hash == 0)
         return wal.WiData[0][WALINDEX_HDR_SIZE / sizeof(uint) + frame - 1];
     return wal.WiData[hash][(frame - 1 - HASHTABLE_NPAGE_ONE) % HASHTABLE_NPAGE];
 }
示例#21
0
文件: Wal.cs 项目: BclEx/GpuData
        static void walEncodeFrame(Wal wal, Pid id, uint truncate, byte[] data, byte[] frame)
        {
            var checksum = wal.Header.FrameChecksum;
            Debug.Assert(WAL_FRAME_HDRSIZE == 24);
            ConvertEx.Put4(frame, 0, id);
            ConvertEx.Put4(frame, 4, truncate);
            Buffer.BlockCopy(frame, 8, wal.Header.Salt, 0, 8);

            bool nativeChecksum = true; // (wal.Header.BigEndianChecksum == TYPE_BIGENDIAN); // True for native byte-order checksums
            walChecksumBytes(nativeChecksum, frame, 8, checksum, checksum);
            walChecksumBytes(nativeChecksum, data, (int)wal.SizePage, checksum, checksum);

            ConvertEx.Put4(frame, 16, checksum[0]);
            ConvertEx.Put4(frame, 20, checksum[1]);
        }
示例#22
0
文件: Wal.cs 项目: BclEx/GpuData
        static bool walDecodeFrame(Wal wal, Pid idOut, uint truncateOut, byte[] data, byte[] frame)
        {
            var checksum = wal.Header.FrameChecksum;
            Debug.Assert(WAL_FRAME_HDRSIZE == 24);

            // A frame is only valid if the salt values in the frame-header match the salt values in the wal-header.
            var testFrame = new byte[8];
            Buffer.BlockCopy(frame, 8, testFrame, 0, 8);
            if (Enumerable.SequenceEqual(wal.Header.Salt, testFrame))
                return false;

            // A frame is only valid if the page number is creater than zero.
            Pid id = ConvertEx.Get4(frame, 0); // Page number of the frame
            if (id == 0)
                return false;

            // A frame is only valid if a checksum of the WAL header, all prior frams, the first 16 bytes of this frame-header,
            // and the frame-data matches the checksum in the last 8 bytes of this frame-header.
            bool nativeChecksum = true; // (wal.Header.BigEndianChecksum == TYPE_BIGENDIAN); // True for native byte-order checksums
            walChecksumBytes(nativeChecksum, frame, 8, checksum, checksum);
            walChecksumBytes(nativeChecksum, data, (int)wal.SizePage, checksum, checksum);
            if (checksum[0] != ConvertEx.Get4(frame, 16) || checksum[1] != ConvertEx.Get4(frame, 20)) // Checksum failed.
                return false;

            // If we reach this point, the frame is valid.  Return the page number and the new database size.
            idOut = id;
            truncateOut = ConvertEx.Get4(frame, 4);
            return true;
        }
示例#23
0
文件: Wal.cs 项目: BclEx/GpuData
        static void walCleanupHash(Wal wal)
        {
            Debug.Assert(wal.WriteLock);

            if (wal.Header.MaxFrame == 0) return;

            // Obtain pointers to the hash-table and page-number array containing the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
            // that the page said hash-table and array reside on is already mapped.
            Debug.Assert(wal.WiData.Length > walFramePage(wal.Header.MaxFrame));
            Debug.Assert(wal.WiData[walFramePage(wal.Header.MaxFrame)] != 0);
            ht_slot[] hash = null; // Pointer to hash table to clear
            Pid[] ids = null; // Page number array for hash table
            int zero = 0; // frame == (aHash[x]+iZero)
            walHashGet(wal, walFramePage(wal.Header.MaxFrame), ref hash, ref ids, ref zero);

            // Zero all hash-table entries that correspond to frame numbers greater than pWal->hdr.mxFrame.
            int limit = wal.Header.MaxFrame - zero; // Zero values greater than this
            Debug.Assert(limit > 0);
            for (int i = 0; i < HASHTABLE_NSLOT; i++)
                if (hash[i] > limit)
                    hash[i] = 0;

            // Zero the entries in the aPgno array that correspond to frames with frame numbers greater than pWal->hdr.mxFrame.
            int bytes = (int)((char*)hash - (char*)&ids[limit + 1]); // Number of bytes to zero in aPgno[]
            _memset((void*)&ids[limit + 1], 0, bytes);

            #if ENABLE_EXPENSIVE_ASSERT
            // Verify that the every entry in the mapping region is still reachable via the hash table even after the cleanup.
            int key; // Hash key
            if (limit)
            for (int i = 1; i <= limit; i++)
            {
                for (key = walHash(ids[i]); hash[key]; key = walNextHash(key))
                    if (hash[key] == i) break;
                _assert(hash[key] == i);
            }
            #endif
        }
示例#24
0
 static WalCheckpointInfo walCkptInfo(Wal wal, int idx)
 {
     Debug.Assert(wal.WiData.Length > 0 && wal.WiData[0] != null);
     return((WalCheckpointInfo)wal.WiData[0]);
 }
示例#25
0
文件: Wal.cs 项目: BclEx/GpuData
 static void walUnlockExclusive(Wal wal, int lockIdx, int n)
 {
     if (wal.ExclusiveMode_ != MODE.NORMAL) return;
     wal.DBFile.ShmLock(lockIdx, n, VFile.SHM.UNLOCK | VFile.SHM.EXCLUSIVE);
     WALTRACE("WAL%p: release EXCLUSIVE-%s cnt=%d\n", wal, walLockName(lockIdx), n);
 }
示例#26
0
 static WalIndexHeader[] walIndexHeader(Wal wal, int idx)
 {
     Debug.Assert(wal.WiData.Length > 0 && wal.WiData[0] != null);
     return((WalIndexHeader[])wal.WiData[0]);
 }
示例#27
0
文件: Wal.cs 项目: BclEx/GpuData
 static void walUnlockShared(Wal wal, int lockIdx)
 {
     if (wal.ExclusiveMode_ != MODE.NORMAL) return;
     wal.DBFile.ShmLock(lockIdx, 1, VFile.SHM.UNLOCK | VFile.SHM.SHARED);
     WALTRACE("WAL%p: release SHARED-%s\n", wal, walLockName(lockIdx));
 }
示例#28
0
文件: Wal.cs 项目: BclEx/GpuData
 static WalCheckpointInfo walCkptInfo(Wal wal, int idx)
 {
     Debug.Assert(wal.WiData.Length > 0 && wal.WiData[0] != null);
     return (WalCheckpointInfo)wal.WiData[0];
 }