internal void AddVisibleTable(ITableSource source, IRowIndexSet indexSet) { var tableName = source.TableInfo.TableName; visibleTables[tableName] = source; tableIndices[tableName] = indexSet; }
public void UpdateVisibleTable(ITableSource table, IRowIndexSet indexSet) { // TODO: verify if the transaction is read-only RemoveVisibleTable(table); AddVisibleTable(table, indexSet); }
internal void CommitTransactionChange(long commitId, ITableEventRegistry change, IRowIndexSet indexSet) { lock (this) { // ASSERT: Can't do this if source is Read only. if (IsReadOnly) { throw new InvalidOperationException("Can't commit transaction journal, table is Read only."); } // CHECK! // TODO: change.CommitId = commitId; try { // Add this registry to the multi version table indices log Registries.AddRegistry(change); // Write the modified index set to the index store // (Updates the index file) CommitIndexSet(indexSet); // Update the state of the committed added data to the file system. // (Updates data to the allocation file) // // ISSUE: This can add up to a lot of changes to the allocation file and // the runtime could potentially be terminated in the middle of // the update. If an interruption happens the allocation information // may be incorrectly flagged. The type of corruption this would // result in would be; // + From an 'update' the updated record may disappear. // + From a 'delete' the deleted record may not delete. // + From an 'insert' the inserted record may not insert. // // Note, the possibility of this type of corruption occuring has been // minimized as best as possible given the current architecture. // Also note that is not possible for a table file to become corrupted // beyond recovery from this issue. foreach (var entry in change) { if (entry is TableRowEvent) { var rowEvent = (TableRowEvent)entry; var rowIndex = rowEvent.RowNumber; if (rowEvent.EventType == TableRowEventType.Add) { // Record commit added var oldType = WriteRecordState(rowIndex, RecordState.CommittedAdded); // Check the record was in an uncommitted state before we changed // it. if (oldType != RecordState.Uncommitted) { WriteRecordState(rowIndex, oldType); throw new InvalidOperationException($"Record {rowIndex} of table {TableName} was not in an uncommitted state!"); } } else if (rowEvent.EventType == TableRowEventType.Remove) { // Record commit removed var oldType = WriteRecordState(rowIndex, RecordState.CommittedRemoved); // Check the record was in an added state before we removed it. if (oldType != RecordState.CommittedAdded) { WriteRecordState(rowIndex, oldType); throw new InvalidOperationException($"Record {rowIndex} of table {TableName} was not in an added state!"); } // Notify collector that this row has been marked as deleted. GC.DeleteRow(rowIndex); } } } } catch (IOException e) { throw new InvalidOperationException("IO Error: " + e.Message, e); } } }
private void CommitIndexSet(IRowIndexSet indexSet) { indexSetStore.CommitIndexSet(indexSet); indexSet.Dispose(); }
internal bool TryGetRowIndexSet(ObjectName tableName, out IRowIndexSet indexSet) => tableIndices.TryGetValue(tableName, out indexSet);
public void CommitIndexSet(IRowIndexSet indexSet) { var removedBlocks = new List <IndexBlock>(); lock (this) { var sIndexSet = (SnapshotIndexSet)indexSet; try { try { Store.Lock(); // For each Index in the index set, foreach (Index index in sIndexSet) { int indexNum = index.IndexNumber; // The IndexBlock we are changing var curIndexBlock = indexBlocks[indexNum]; // Get all the blocks in the list var blocks = index.AllBlocks.ToList(); // Make up a new block list for this index set. long blockP; using (var area = Store.CreateArea(16 + (blocks.Count * 28))) { blockP = area.Id; area.Write(1); // version area.Write(0); // reserved area.Write((long)blocks.Count); // block count foreach (var block in blocks) { var mappedBlock = (IMappedBlock)block; long bottomInt = 0; long topInt = 0; var blockSize = mappedBlock.Count; if (blockSize > 0) { bottomInt = mappedBlock.Bottom; topInt = mappedBlock.Top; } long blockPointer = mappedBlock.BlockPointer; // Is the block new or was it changed? if (blockPointer == -1 || mappedBlock.HasChanged) { // If this isn't -1 then write this sector on the list of // sectors to delete during GC. if (blockPointer != -1) { curIndexBlock.AddDeletedArea(blockPointer); } // This is a new block or a block that's been changed // Write the block to the file system blockPointer = mappedBlock.Flush(); } area.Write(bottomInt); area.Write(topInt); area.Write(blockPointer); area.Write((int)(blockSize | ((mappedBlock.CompactType) << 24))); } // Finish initializing the area area.Flush(); } // Add the deleted blocks var deletedBlocks = index.DeletedBlocks.ToArray(); for (int i = 0; i < deletedBlocks.Length; ++i) { long delBlockP = deletedBlocks[i].BlockPointer; if (delBlockP != -1) { curIndexBlock.AddDeletedArea(delBlockP); } } // Mark the current block as deleted curIndexBlock.MarkAsDeleted(); // Now create a new IndexBlock object var newIndexBlock = new IndexBlock(this, indexNum, curIndexBlock.BlockSize, blockP); newIndexBlock.Parent = curIndexBlock; // Add reference to the new one newIndexBlock.AddReference(); // Update the index_blocks list indexBlocks[indexNum] = newIndexBlock; // We remove this later. removedBlocks.Add(curIndexBlock); } // Commit the new index header (index_blocks) CommitIndexHeader(); } finally { Store.Unlock(); } // Commit finished. } catch (IOException e) { throw new InvalidOperationException("Error while committing index changed", e); } } // Remove all the references for the changed blocks, foreach (var block in removedBlocks) { block.RemoveReference(); } }