Example #1
0
        unsafe private int AllocateRecord(long size, int blockId)
        {
            if (size < 1 || blockId < 0)
            {
                return(-1);
            }

            //通过页面管理器获取指定块所在的页面,该方法内部确保始终能返回其所在的存储页面对象,注意:该方法始终进行线程同步。
            using (var page = _pageManager.GetPage(blockId))
            {
                int temp         = 0;
                var blocks       = (int)Math.Ceiling((double)size / this.BlockSize);
                var recordCount  = this.BlockSize / AllocationRecord.Length;
                var recordBuffer = new byte[AllocationRecord.Length];

                //获取指定存储块所在缓存页的流,该方法内部确保将返回的流指针定位到对应的块起始位置并加上指定的偏移量。
                var stream = page.GetPageStream(blockId, 0, ref temp);

                for (int i = 0; i < recordCount; i++)
                {
                    if (stream.Read(recordBuffer, 0, recordBuffer.Length) != recordBuffer.Length)
                    {
                        continue;
                    }

                    var flags = BitConverter.ToInt32(recordBuffer, 12);

                    if (flags == AllocationRecord.Unallocated)
                    {
                        var head = this.AllocateBlocks(blocks);

                        if (head > 0)
                        {
                            fixed(byte *pRecord = recordBuffer)
                            {
                                *(int *)pRecord        = head;
                                *(uint *)(pRecord + 4) = (uint)size;
                                *(uint *)(pRecord + 8) = BufferUtility.GetTimestamp();
                                *(int *)(pRecord + 12) = AllocationRecord.Allocated;
                            }

                            //在写入之前要先调整回读入前的位置
                            stream.Position -= recordBuffer.Length;
                            //将记录缓存数据写入流中
                            stream.Write(recordBuffer, 0, recordBuffer.Length);

                            //累加已经分配的缓存项数量
                            Interlocked.Increment(ref _count);
                        }

                        return(i);
                    }
                }
            }

            return(-1);
        }
Example #2
0
        unsafe private int AllocateRecord(long size, byte[] recordBuffer)
        {
            if (recordBuffer == null || recordBuffer.Length == 0)
            {
                throw new ArgumentNullException("recordBuffer");
            }

            if (size < 1 || recordBuffer.Length < AllocationRecord.Length)
            {
                return(-1);
            }

            var blocks      = (int)Math.Ceiling((double)size / this.BlockSize);
            var recordCount = recordBuffer.Length / AllocationRecord.Length;

            fixed(byte *pBuffer = recordBuffer)
            {
                byte *pRecord;

                for (int i = 0; i < recordCount; i++)
                {
                    pRecord = pBuffer + (i * AllocationRecord.Length);

                    int flags = Interlocked.CompareExchange(ref *(int *)(pRecord + AllocationRecord.Length - 4), AllocationRecord.Allocated, AllocationRecord.Unallocated);

                    if (flags == AllocationRecord.Unallocated)
                    {
                        var head = this.AllocateBlocks(blocks);

                        if (head > 0)
                        {
                            *(int *)pRecord        = head;
                            *(uint *)(pRecord + 4) = (uint)size;
                            *(uint *)(pRecord + 8) = BufferUtility.GetTimestamp();

                            //累加已经分配的缓存项数量
                            Interlocked.Increment(ref _count);
                        }
                        else
                        {
                            *(int *)(pRecord + 12) = AllocationRecord.Unallocated;
                        }

                        return(i);
                    }
                }
            }

            return(-1);
        }