// commits a transaction private void aCommit(Transaction context) { lock (ManagerLock) { TransItem contextData = this.preparedContextMap.Remove(context); if (null == contextData) { // transaction must already have been commited or aborted // nothing to do return; } List <int> oldStorageContextPages = contextData.StoragePageList; StorageContext storageContext = contextData.TransactionData; if (null == storageContext) { storageContext = ReadStorageContext(contextData, out oldStorageContextPages); } // read in the DB root DBHdr dbRoot = this.ReadDBRoot(); if (null == dbRoot) { throw new InvalidDataException(); } // merge page table storageContext.PageTable.ReadPageTableData( this.dataFile, dbRoot.PageTable); storageContext.PageTable.ClearDirtyFlags(); // merge resource index storageContext.ResourceIndex.ReadIndexData( this.dataFile, dbRoot.ResourceIndex); storageContext.ResourceIndex.ClearDirtyFlags(); // merge reservation index storageContext.ReservationIndex.ReadIndexData( this.dataFile, dbRoot.ReservationIndex); storageContext.ReservationIndex.ClearDirtyFlags(); // write the page table List <int> oldPageTablePages = null; dbRoot.PageTable = storageContext.PageTable.WritePageTableData( this.dataFile, this.pageManager, out oldPageTablePages); // write the resource index List <int> oldResourceIndexPages = null; dbRoot.ResourceIndex = storageContext.ResourceIndex.WriteIndexData( this.dataFile, this.pageManager, out oldResourceIndexPages); // write the reservation index List <int> oldReservationIndexPages = null; dbRoot.ReservationIndex = storageContext.ReservationIndex.WriteIndexData( this.dataFile, this.pageManager, out oldReservationIndexPages); // write the updated prepared transaction list List <int> oldPrepedContextMapPages = null; dbRoot.PrepedTransactions = this.preparedContextMap.WriteTransactionTableData( this.dataFile, this.pageManager, out oldPrepedContextMapPages); // update the page manager this.pageManager.SetFreePages(oldStorageContextPages); this.pageManager.SetFreePages(oldPageTablePages); this.pageManager.SetFreePages(oldResourceIndexPages); this.pageManager.SetFreePages(oldReservationIndexPages); this.pageManager.SetFreePages(oldPrepedContextMapPages); this.pageManager.SetFreePages(storageContext.FreedPageList); dbRoot.PageManager = this.pageManager.WritePageManagerData( this.dataFile); this.WriteDBRoot(dbRoot); this.dataFile.Flush(true); } }
private StorageContext ReadStorageContext(TransItem contextData, out List <int> oldStorageContextPages) { // allocate the storage page list oldStorageContextPages = new List <int>(); // look for the context in the map StorageContext storageContext = new StorageContext(); // read in the page table if (TransItem.NotStored != contextData.PageTableStartPage) { storageContext.PageTable.ReadPageTableData( this.dataFile, contextData.PageTableStartPage); oldStorageContextPages.AddRange( storageContext.PageTable.GetStoragePages()); } // read in the resource index if (TransItem.NotStored != contextData.ResourceIndexStartPage) { storageContext.ResourceIndex.ReadIndexData( this.dataFile, contextData.ResourceIndexStartPage); oldStorageContextPages.AddRange( storageContext.ResourceIndex.GetStoragePages()); } // read in the reservation index if (TransItem.NotStored != contextData.ReservationIndexStartPage) { storageContext.ReservationIndex.ReadIndexData( this.dataFile, contextData.ReservationIndexStartPage); oldStorageContextPages.AddRange( storageContext.ReservationIndex.GetStoragePages()); } // read in the allocated page list if (TransItem.NotStored != contextData.AllocatedPageListStartPage) { List <int> usedPages = null; List <int> data = null; ListReader <int> reader = new ListReader <int>(); reader.ReadList(this.dataFile, contextData.AllocatedPageListStartPage, out data, out usedPages); storageContext.AllocatedPageList = data; oldStorageContextPages.AddRange(usedPages); } // read in the freed page list if (TransItem.NotStored != contextData.FreedPageListStartPage) { List <int> usedPages = null; List <int> data = null; ListReader <int> reader = new ListReader <int>(); reader.ReadList(this.dataFile, contextData.FreedPageListStartPage, out data, out usedPages); storageContext.FreedPageList = data; oldStorageContextPages.AddRange(usedPages); } return(storageContext); }
// writes a resource or reservation data item protected virtual bool Write <I, R>(Transaction context, StorageContext storageContext, StorageIndex <I> index, I rID, R data) { // look for the resource in the index IndexItem <I> address = index.GetResourceAddress(rID); if (null == address && null == data) { // nothing to do: // user probably wanted to delete an non-existing item return(true); } else if (null == address && null != data) { address = new IndexItem <I> { Page = storageContext.PageTable.GetLastLogicalPage(), Record = -1 }; } // Aquire a lock on the logical page address to ensure that we have access to the page this.LockPage(context, MyLM.LockMode.Write, address.Page); // find the physical page int fileAddress = storageContext.PageTable.GetPhysicalPage(address.Page); // get the page StoragePage page = new StoragePage(); if (0 <= fileAddress) { this.aReadPageData(page, fileAddress); } // write the record while (true) { try { if (0 > address.Record) { address.Record = page.AddRecord(data); } else { page.WriteRecord(address.Record, data); } } catch (StoragePage.InsuffcientSpaceException) { // did not fit on last page so allocate a new page page = new StoragePage(); address.Page = -1; fileAddress = -1; continue; } break; } // write the page fileAddress = this.aWritePageData(page, storageContext, fileAddress); // update the page table if (0 > address.Page) { address.Page = storageContext.PageTable.SetLogicalPage(fileAddress); } else { storageContext.PageTable.UpdatePage(address.Page, fileAddress); } // update the index if (null == data) { // handle deletes address = null; } index.SetResourceAddress(rID, address); return(true); }