Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

Tagged as

Go to top

Building an embedded database engine in C#

, 10 Jun 2009
DbfDotNet is a very fast and compact fully managed standalone database/entity framework, for the .Net Framework.
using System;
using System.Collections.Generic;
using System.Text;

namespace DbfDotNet.Core
{
    internal class RecordHolder
    {
        internal ClusteredFile mFile;
        private readonly UInt32 mRecordNo;
        private WeakReference mRecordWeakRef;
        private byte[] mReadBuffer;
        private byte[] mWriteBuffer;
        internal System.Threading.EventWaitHandle RecordFinalized;

        private object mHold;

        public RecordHolder(ClusteredFile file, UInt32 RecordNo, Record record)
        {
            RecordFinalized = new System.Threading.EventWaitHandle(false, 
                System.Threading.EventResetMode.ManualReset);
#if DUMP_FINALIZE
            System.Diagnostics.Trace.WriteLine(file.mOriginalFile + " New RecordHolder for #" + RecordNo);
            System.Diagnostics.Debug.Assert(record != null);
#endif

            mFile = file;
            mRecordNo = RecordNo;
            MakeWeakRef(record);
            mHold = record;
        }

        public UInt32 RecordNo
        {
            get { return mRecordNo; }
        }

        public bool Hold
        {
            get { return mHold != null; }
            set { mHold = (value ? Record : null); }
        }

        private void MakeWeakRef(Record record)
        {
            mRecordWeakRef = new WeakReference(record, false);
        }

        public Record Record
        {
            get
            {
                if (mRecordWeakRef == null) return null;
                var result = mRecordWeakRef.Target as Record;
                return result;
            }
            set
            {
                // We could be tempted to write
                // mRecordWeakRef.Target=value 
                // but this is not advisable as this property
                // could be call from a GC destructor.
                MakeWeakRef(value);
            }
        }
     
        internal void OnRecordFinalizing(Record record)
        {
            try
            {
                // first we write the buffer 
                mFile.InternalFillWriteBuffer(this, record);
            }
            finally
            {
                // This is one of the only place where we use Threading mechanism.
                // The mainthread might be waiting for it
                RecordFinalized.Set();
            }
        }

        internal byte[] GetCurrentBuffer(bool readIfNeeded)
        {
            if (mWriteBuffer!=null) return mWriteBuffer;
            if (mReadBuffer!=null) return mReadBuffer;

            if (readIfNeeded)
            {
                mReadBuffer = new byte[mFile.mRecordWidth];
                mFile.InternalReadRecordFromDisk(mRecordNo, mReadBuffer);
                return mReadBuffer;
            }
            else return null;
        }

        internal bool IsModified()
        {
            return (mWriteBuffer != null);
        }

        internal void SetNewBuffer(Byte[] newBuffer)
        {
            bool modified = false;
            if (mReadBuffer == null) modified = true;
            else
            {
                int len = mFile.mRecordWidth;
                for (int i = 0; i < len; i++)
                {
                    if (mReadBuffer[i] != newBuffer[i])
                    {
                        modified = true;
                        break;
                    }
                }
            }
            if (modified)
            {
                var currentBuffer = (mWriteBuffer != null ? mWriteBuffer : mReadBuffer);
                // we could clear the readBuffer here to save memory
                mFile.OnWriteBufferModified(mRecordNo, currentBuffer, newBuffer);
                mWriteBuffer = newBuffer;
            }

        }

        internal void Save()
        {
            if (mWriteBuffer != null)
            {
                mFile.InternalSaveRecordToDisk(mRecordNo, mWriteBuffer);
                mWriteBuffer = null;
            }
        }

        internal void SaveChanges(Record record)
        {
            mFile.InternalFillWriteBuffer(this, record);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Pascal Ganaye
Software Developer (Senior)
United Kingdom United Kingdom
I am a French programmer.
These days I spend most of my time with the .NET framework, JavaScript and html.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 10 Jun 2009
Article Copyright 2009 by Pascal Ganaye
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid