Beispiel #1
0
        internal void SetHolderForNewRecord(Core.RecordHolder value)
        {
            System.Diagnostics.Debug.Assert(mmHolder == null, "mHolder can only be set once");
#if DUMP_FINALIZE
            System.Diagnostics.Trace.WriteLine(this.GetType().Name + " #" + value.mRecordNo);
#endif
            mmHolder = value;
        }
        /// <summary>
        /// Note that this method is called from flush and from the record destructor in the garbage collector thread.
        /// </summary>
        /// <param name="recordHolder"></param>
        internal void InternalFillWriteBuffer(RecordHolder recordHolder, Record record)
        {
            Debug.Assert(record != null, "InternalFillWriteBuffer : record must be not null.");
            var newBuffer = new Byte[mRecordWidth];

            if (OnFillWriteBuffer(record, newBuffer))
            {
                recordHolder.SetNewBuffer(newBuffer);
            }
        }
        private void SetLastUsed(LinkedListNode <RecordHolder> linkListNode)
        {
            if (linkListNode.List == mRecordsByLastUsed)
            {
                if (linkListNode != mRecordsByLastUsed.Last)
                {
                    mRecordsByLastUsed.Remove(linkListNode);
                    mRecordsByLastUsed.AddLast(linkListNode);
                }
            }
            else
            {
                mRecordsByLastUsed.AddLast(linkListNode);
            }

            // for every table we use PERCENT_CACHED_RECORDS
            int limit = (int)(PERCENT_CACHED_RECORDS * mRecordCount);

            if (limit < MIN_CACHED_RECORDS)
            {
                limit = MIN_CACHED_RECORDS;
            }
            else if (limit > MAX_CACHED_RECORDS)
            {
                limit = MAX_CACHED_RECORDS;
            }

            var node = mRecordsByLastUsed.First;

            while (node != null && mRecordsByLastUsed.Count > limit)
            {
                RecordHolder recordHolder = node.Value;
                var          nextNode     = node.Next;

                node.Value.Hold = false;
                mRecordsByLastUsed.Remove(node);
#if DUMP_FINALIZE
                System.Diagnostics.Trace.WriteLine(this.mOriginalFile + " Remove last used Record #" + recordHolder.mRecordNo);
#endif
                node = nextNode;
            }
        }
        internal void EmptyTable()
        {
            var node = mRecordsByLastUsed.First;

            while (node != null && mRecordsByLastUsed.Count > 0)
            {
                RecordHolder recordHolder = node.Value;
                var          nextNode     = node.Next;
                recordHolder.Save();
                node = nextNode;
            }
#if DUMP_FINALIZE
            System.Diagnostics.Trace.WriteLine(this.mOriginalFile + " Clear Records");
#endif

            mRecordsByRecordNo.Clear();
            mRecordsByLastUsed.Clear();
            mRecordCount = 0;
            mStream.SetLength(mHeaderWidth);
        }
        public virtual object NewRecord()
        {
            var recordNo = mRecordCount;

            mRecordCount += 1;
            var result = OnCreateNewRecord(/*isnew*/ true, recordNo);

            var holder         = new RecordHolder(this, recordNo, result);
            var linkedListNode = new LinkedListNode <RecordHolder>(holder);

            result.SetHolderForNewRecord(holder);

            mRecordsByRecordNo[recordNo] = linkedListNode;
            SetLastUsed(linkedListNode);
#if DUMP_FINALIZE
            System.Diagnostics.Trace.WriteLine(this.mOriginalFile + " Add Record #" + recordNo);
#endif


            return(result);
        }
        internal virtual protected Record InternalGetRecord(UInt32 recordNo, bool returnNullIfNotInCache)
        {
            Debug.Assert(recordNo < UInt32.MaxValue, "Invalid RecordNo");
            LinkedListNode <RecordHolder> linkListNode = null;
            RecordHolder holder = null;
            Record       record = null;

            if (mRecordsByRecordNo.TryGetValue(recordNo, out linkListNode))
            {
                holder = linkListNode.Value;
                record = holder.Record;
                if (record != null)
                {
                    SetLastUsed(linkListNode);
                    return(record);
                }
                else
                {
                    // we're going to add a new one in one sec
                    RemoveLastUsed(linkListNode);
                }
            }

            if (returnNullIfNotInCache)
            {
                return(null);
            }
            // we're here because the record was disposed or never created

            var newRecord = OnCreateNewRecord(/*isnew*/ false, recordNo);


            if (holder == null)
            {
                holder       = new RecordHolder(this, recordNo, newRecord);
                linkListNode = new LinkedListNode <RecordHolder>(holder);
                SetLastUsed(linkListNode);
                mRecordsByRecordNo[recordNo] = linkListNode;
#if DUMP_FINALIZE
                System.Diagnostics.Trace.WriteLine(this.mOriginalFile + " Save Record #" + recordNo);
#endif
            }
            else
            {
                // holder exist but object doesn't we expect that a finalized happened
                if (holder.RecordFinalized.WaitOne(10000))
                {
                    // we (re)connect the recordHolder to the new Record
                    holder.RecordFinalized.Reset();
                    holder.Record = newRecord;
                }
                else
                {
                    throw new Exception("Something very wrong happened.");
                }
            }
            newRecord.SetHolderForNewRecord(holder);

            Byte[] sourceBuffer = holder.GetCurrentBuffer(/*readIfNeeded*/ true);
            OnReadRecordBuffer(sourceBuffer, newRecord);

            return(newRecord);
        }