18 using System.Collections.Generic;
30 private readonly
object commitLock =
new object();
39 private const string StateStorePostfix =
"_sf";
41 public const string ObjectStoreName =
"lob_store";
47 objectStates =
new List<TransactionObjectState>();
49 StateStoreName = String.Format(
"{0}{1}", database.
Name, StateStorePostfix);
68 public int CurrentCommitId {
get;
private set; }
70 private bool IsReadOnly {
74 private bool IsClosed {
75 get {
return tableSources == null; }
80 private string StateStoreName {
get; set; }
86 var tables = StateStore.GetVisibleList();
89 foreach (var resource
in tables) {
90 var tableId = resource.TableId;
91 var sourceName = resource.SourceName;
96 var source = LoadTableSource(tableId, sourceName);
99 throw new InvalidOperationException(String.Format(
"Table {0} was not found.", sourceName));
103 tableSources.Add(tableId, source);
111 var tables = StateStore.GetDeleteList();
114 foreach (var resource
in tables) {
115 int tableId =resource.TableId;
116 string tableName = resource.SourceName;
119 var source = LoadTableSource(tableId, tableName);
122 if (source == null) {
123 StateStore.RemoveDeleteResource(tableName);
128 tableSources.Add(tableId, source);
137 var source =
new TableSource(
this, StoreSystem, LargeObjectStore, tableId, tableName);
138 if (!source.Exists())
145 var masterTable = GetTableSource(tableId);
174 if (lobStore != null)
176 if (stateStore != null)
177 stateStore.Dispose();
179 if (tempStoreSystem != null)
180 tempStoreSystem.Dispose();
182 tempStoreSystem = null;
189 GC.SuppressFinalize(
this);
195 tableSources =
new Dictionary<int, TableSource>();
201 bool blobStoreExists = StoreSystem.StoreExists(ObjectStoreName);
204 if (!blobStoreExists && IsReadOnly) {
209 if (blobStoreExists) {
210 lobStore = StoreSystem.OpenStore(ObjectStoreName);
212 lobStore = StoreSystem.CreateStore(ObjectStoreName);
222 var fixedArea = lobStore.
GetArea(-1,
false);
224 if (!blobStoreExists) {
225 long headerP = LargeObjectStore.Create();
226 fixedArea.WriteInt8(headerP);
230 long headerP = fixedArea.ReadInt8();
231 LargeObjectStore.Open(headerP);
245 var deleteList = StateStore.GetDeleteList().ToArray();
246 if (deleteList.Length > 0) {
249 for (
int i = deleteList.Length - 1; i >= 0; --i) {
250 var tableName = deleteList[i].SourceName;
251 CloseTable(tableName,
true);
254 for (
int i = deleteList.Length - 1; i >= 0; --i) {
255 string tableName = deleteList[i].SourceName;
256 bool dropped = CloseAndDropTable(tableName);
259 StateStore.RemoveDeleteResource(tableName);
275 foreach (var source
in tableSources.Values) {
276 if (source.StoreIdentity.Equals(tableFileName)) {
277 if (source.IsRootLocked)
283 tableId = source.TableId;
288 tableSources.Remove(tableId.Value);
293 private void CloseTable(
string sourceName,
bool pendingDrop) {
295 foreach (var source
in tableSources.Values) {
296 if (source.SourceName.Equals(sourceName)) {
297 if (source.IsRootLocked)
300 source.Close(pendingDrop);
307 return StoreSystem.StoreExists(StateStoreName);
312 throw new IOException(
"Table composite does not exist");
317 StoreSystem.Lock(StateStoreName);
321 stateStore = StoreSystem.OpenStore(StateStoreName);
325 var fixedArea = stateStore.
GetArea(-1);
326 long headP = fixedArea.ReadInt8();
327 StateStore.Open(headP);
353 transaction.Commit();
354 }
catch (Exception ex) {
355 throw new InvalidOperationException(
"Transaction Exception initializing tables.", ex);
362 throw new IOException(
"Composite already exists");
367 StoreSystem.Lock(StateStoreName);
371 stateStore = StoreSystem.CreateStore(StateStoreName);
376 long headP = StateStore.Create();
378 var fixedArea = stateStore.
GetArea(-1);
379 fixedArea.WriteInt8(headP);
391 CreateSystemSchema();
400 transaction.CreateSystemSchema();
406 throw new InvalidOperationException(
"Transaction Exception creating composite.", e);
408 if (transaction != null)
417 StoreSystem.SetCheckPoint();
420 foreach (var source
in tableSources.Values) {
425 StoreSystem.CloseStore(stateStore);
431 StoreSystem.Unlock(StateStoreName);
433 if (LargeObjectStore != null)
434 StoreSystem.CloseStore(lobStore);
443 foreach (var source
in tableSources.Values)
448 StoreSystem.CloseStore(stateStore);
449 StoreSystem.DeleteStore(stateStore);
452 if (LargeObjectStore != null) {
453 StoreSystem.CloseStore(lobStore);
454 StoreSystem.DeleteStore(lobStore);
461 StoreSystem.Unlock(StateStoreName);
465 return CreateTableSource(tableInfo, temporary);
471 int tableId = NextTableId();
474 var storeSystem = StoreSystem;
476 storeSystem = tempStoreSystem;
479 source.Create(tableInfo);
481 tableSources.Add(tableId, source);
484 MarkUncommitted(tableId);
491 }
catch (IOException e) {
492 throw new InvalidOperationException(String.Format(
"Unable to create source for table '{0}'.", tableInfo.
TableName), e);
499 if (tableSources == null)
503 if (!tableSources.TryGetValue(tableId, out source))
505 String.Format(
"Could not find any source for table with id {0} in this composite.", tableId));
512 return StateStore.NextTableId();
520 IEnumerable<ITableSource> selectedFromTables,
521 IEnumerable<IMutableTable> touchedTables,
TransactionRegistry journal, Action<TableCommitInfo> commitActions) {
523 var state =
new TransactionWork(
this, transaction, selectedFromTables, touchedTables, journal);
526 if (!state.HasChanges) {
527 CloseTransaction(state.Transaction);
532 var changedTablesList = state.Commit(objectStates, commitActions);
537 foreach (var master
in changedTablesList) {
538 master.MergeChanges(minCommitId);
540 int nsjsz = objectStates.Count;
541 for (
int i = nsjsz - 1; i >= 0; --i) {
542 var namespaceJournal = objectStates[i];
545 if (namespaceJournal.CommitId < minCommitId) {
546 objectStates.RemoveAt(i);
552 StoreSystem.SetCheckPoint();
563 var journalList =
new List<TableEventRegistry>();
564 for (
int i = 0; i < touchedTables.Count; ++i) {
565 var tableJournal = touchedTables[i].EventRegistry;
566 if (tableJournal.EventCount > 0)
567 journalList.Add(tableJournal);
570 var changedTables = journalList.ToArray();
575 foreach (var changeJournal
in changedTables) {
577 int tableId = changeJournal.TableId;
579 var master = GetTableSource(tableId);
581 master.RollbackTransactionChange(changeJournal);
585 CloseTransaction(transaction);
591 return CopySourceTable((
TableSource) tableSource, indexSet);
598 int tableId = NextTableId();
602 var masterTable =
new TableSource(
this, StoreSystem, LargeObjectStore, tableId, sourceName);
604 masterTable.CopyFrom(tableId, tableSource, indexSet);
607 tableSources.Add(tableId, masterTable);
610 MarkUncommitted(tableId);
617 }
catch (IOException e) {
618 throw new Exception(String.Format(
"Unable to copy source table '{0}' because of an error.", tableSource.
TableInfo.
TableName), e);
624 var thisCommittedTables =
new List<TableSource>();
628 int thisCommitId = CurrentCommitId;
629 var committedTableList = StateStore.GetVisibleList();
630 thisCommittedTables.AddRange(committedTableList.Select(resource => GetTableSource(resource.TableId)));
633 var indexInfo = (thisCommittedTables.Select(mtable => mtable.CreateIndexSet())).ToList();
639 return new Transaction(context,
Database, thisCommitId, isolation, thisCommittedTables, indexInfo);
646 if (tableCommitCallback == null) {
647 tableCommitCallback = action;
649 tableCommitCallback = (Action<TableCommitInfo>) Delegate.Combine(tableCommitCallback, action);
654 tableCommitCallback = Delegate.Remove(tableCommitCallback, action) as Action<TableCommitInfo>;
658 bool lastTransaction;
669 if (lastTransaction) {
672 }
catch (IOException) {
678 internal void CommitToTables(IEnumerable<int> createdTables, IEnumerable<int> droppedTables) {
680 foreach (
int createdTable
in createdTables) {
683 var t = GetTableSource(createdTable);
685 StateStore.AddVisibleResource(resource);
686 StateStore.RemoveDeleteResource(resource.SourceName);
690 foreach (
int droppedTable
in droppedTables) {
693 var t = GetTableSource(droppedTable);
695 StateStore.AddDeleteResource(resource);
696 StateStore.RemoveVisibleResource(resource.SourceName);
701 }
catch (IOException e) {
702 throw new InvalidOperationException(
"IO Error: " + e.Message, e);
707 return StateStore.ContainsVisibleResource(resourceId);
void Commit(Transaction transaction, IList< ITableSource > visibleTables, IEnumerable< ITableSource > selectedFromTables, IEnumerable< IMutableTable > touchedTables, TransactionRegistry journal, Action< TableCommitInfo > commitActions)
void MarkUncommitted(int tableId)
TableSource GetTableSource(int tableId)
static void Setup(ITransaction transaction)
void CloseTable(string sourceName, bool pendingDrop)
The context of a single database within a system.
The system implementation of a transaction model that handles isolated operations within a database c...
Defines the contract for stores that handle lrge objects within a database system.
Dictionary< int, TableSource > tableSources
Action< TableCommitInfo > tableCommitCallback
List< TransactionObjectState > objectStates
void Lock()
This method is called before the start of a sequence of Write commands between consistant states of s...
An object that creates and manages the IStore objects that the database engine uses to represent itse...
void CommitToTables(IEnumerable< int > createdTables, IEnumerable< int > droppedTables)
The default implementation of a database in a system.
ITransaction CreateTransaction(IsolationLevel isolation)
TableSource LoadTableSource(int tableId, string tableName)
Describes the name of an object within a database.
IContext IEventSource. Context
ITableSource CreateTableSource(TableInfo tableInfo, bool temporary)
ObjectName TableName
Gets the fully qualified name of the table that is ensured to be unique within the system...
void CreateSystemSchema()
void UnregisterOnCommit(Action< TableCommitInfo > action)
bool CloseAndDropTable(string tableFileName)
void OnCommitModification(ObjectName objName, IEnumerable< int > addedRows, IEnumerable< int > removedRows)
void RemoveTransaction(ITransaction transaction)
void Rollback(Transaction transaction, IList< IMutableTable > touchedTables, TransactionRegistry journal)
void Rollback()
Rollback any write operations done during the lifetime of this transaction and invalidates it...
void RegisterOnCommit(Action< TableCommitInfo > action)
ITransactionFactory TransactionFactory
Gets an object that is used to create new transactions to this database
Provides utilities and properties for handling the SYSTEN schema of a database.
string FullName
Gets the full reference name formatted.
An object that access to a set of indexes.
void Commit()
Commits all write operation done during the lifetime of this transaction and invalidates it...
void Unlock()
This method is called after the end of a sequence of Write commands between consistant states of some...
void CloseTransaction(ITransaction transaction)
ITableSource CopySourceTable(ITableSource tableSource, IIndexSet indexSet)
IStoreSystem tempStoreSystem
IArea GetArea(long id, bool readOnly)
Returns an object that allows for the contents of an area (represented by the id parameter) to be Re...
TableSource CreateTableSource(TableInfo tableInfo, bool temporary)
ITransactionContext IDatabaseContext. CreateTransactionContext()
Creates a context to handle services and variables in the scope of a transaction. ...
The simplest implementation of a transaction.
void Dispose(bool disposing)
Defines the metadata properties of a table existing within a database.
TableSourceComposite(Database database)
string Name
Gets the database name, as configured in the parent context.
A store is a resource where areas can be allocated and freed to store information (a memory allocator...
bool ContainsVisibleResource(int resourceId)
long MinimumCommitId(ITransaction transaction)
TransactionCollection OpenTransactions
Gets the collection of currently open transactions.
TableSource CopySourceTable(TableSource tableSource, IIndexSet indexSet)