예제 #1
0
        public override void Read(long pageNumber, byte[] buffer, int offset)
        {
            lock (journalMap) {
                if (!dataOpen)
                {
                    throw new IOException("Assertion failed: Data file is not open.");
                }
            }

            // The list of all journal entries on this page number
            var allJournalEntries = new List <JournalEntry>(4);

            try {
                // The map index.
                lock (journalMap) {
                    int          i     = ((int)(pageNumber & 0x0FFFFFFF) % journalMap.Length);
                    var          entry = journalMap[i];
                    JournalEntry prev  = null;

                    while (entry != null)
                    {
                        bool deletedHash = false;

                        JournalFile file = entry.File;
                        // Note that once we have a reference the journal file can not be
                        // deleted.
                        file.Reference();

                        // If the file is closed (or deleted)
                        if (file.IsDeleted)
                        {
                            deletedHash = true;
                            // Deleted so remove the reference to the journal
                            file.Dereference();
                            // Remove the journal entry from the chain.
                            if (prev == null)
                            {
                                journalMap[i] = entry.Next;
                            }
                            else
                            {
                                prev.Next = entry.Next;
                            }
                        }

                        // Else if not closed then is this entry the page number?
                        else if (entry.PageNumber == pageNumber)
                        {
                            allJournalEntries.Add(entry);
                        }
                        else
                        {
                            // Not the page we are looking for so remove the reference to the
                            // file.
                            file.Dereference();
                        }

                        // Only move prev is we have NOT deleted a hash entry
                        if (!deletedHash)
                        {
                            prev = entry;
                        }

                        entry = entry.Next;
                    }
                }

                // Read any data from the underlying file
                if (thereIsBackingData)
                {
                    long pagePosition = pageNumber * JournaledSystem.PageSize;
                    // First Read the page from the underlying store.
                    Data.Read(pagePosition, buffer, offset, JournaledSystem.PageSize);
                }
                else
                {
                    // Clear the buffer
                    for (int i = offset; i < (JournaledSystem.PageSize + offset); ++i)
                    {
                        buffer[i] = 0;
                    }
                }

                // Rebuild from the journal file(s)
                int sz = allJournalEntries.Count;
                for (int i = 0; i < sz; ++i)
                {
                    var  entry    = allJournalEntries[i];
                    var  file     = entry.File;
                    long position = entry.Position;
                    lock (file) {
                        file.BuildPage(pageNumber, position, buffer, offset);
                    }
                }
            } finally {
                // Make sure we remove the reference for all the journal files.
                int sz = allJournalEntries.Count;
                for (int i = 0; i < sz; ++i)
                {
                    var         entry = allJournalEntries[i];
                    JournalFile file  = entry.File;
                    file.Dereference();
                }
            }
        }
예제 #2
0
        public override void Write(long pageNumber, byte[] buffer, int offset, int count)
        {
            lock (journalMap) {
                if (!dataOpen)
                {
                    throw new IOException("Assertion failed: Data file is not open.");
                }

                // Make this modification input the log
                var journal = JournaledSystem.LogPageModification(Name, pageNumber, buffer, offset, count);

                // This adds the modification to the END of the hash list.  This means
                // when we reconstruct the page the journals will always be input the
                // correct order - from oldest to newest.

                // The map index.
                int i     = ((int)(pageNumber & 0x0FFFFFFF) % journalMap.Length);
                var entry = journalMap[i];

                // Make sure this entry is added to the END
                if (entry == null)
                {
                    // Add at the head if no first entry
                    journalMap[i] = journal;
                    journal.Next  = null;
                }
                else
                {
                    // Otherwise search to the end
                    // The number of journal entries input the linked list
                    int journalEntryCount = 0;
                    while (entry.Next != null)
                    {
                        entry = entry.Next;
                        ++journalEntryCount;
                    }

                    // and add to the end
                    entry.Next   = journal;
                    journal.Next = null;

                    // If there are over 35 journal entries, scan and remove all entries
                    // on journals that have persisted
                    if (journalEntryCount > 35)
                    {
                        entry = journalMap[i];
                        JournalEntry prev = null;

                        while (entry != null)
                        {
                            bool deletedHash = false;

                            JournalFile file = entry.File;
                            // Note that once we have a reference the journal file can not be
                            // deleted.
                            file.Reference();

                            // If the file is closed (or deleted)
                            if (file.IsDeleted)
                            {
                                deletedHash = true;

                                // Deleted so remove the reference to the journal
                                file.Dereference();

                                // Remove the journal entry from the chain.
                                if (prev == null)
                                {
                                    journalMap[i] = entry.Next;
                                }
                                else
                                {
                                    prev.Next = entry.Next;
                                }
                            }

                            // Remove the reference
                            file.Dereference();

                            // Only move prev is we have NOT deleted a hash entry
                            if (!deletedHash)
                            {
                                prev = entry;
                            }

                            entry = entry.Next;
                        }
                    }
                }
            }
        }