/// <summary> /// Creates a checkpoint for a given sequence point. /// </summary> public Task <BoolResult> CreateCheckpointAsync(OperationContext context, EventSequencePoint sequencePoint) { context = context.CreateNested(); return(context.PerformOperationAsync( _tracer, async() => { bool successfullyUpdatedIncrementalState = false; try { // Creating a working temporary directory using (new DisposableDirectory(_fileSystem, _checkpointStagingDirectory)) { // Saving checkpoint for the database into the temporary folder _database.SaveCheckpoint(context, _checkpointStagingDirectory).ThrowIfFailure(); if (_configuration.UseIncrementalCheckpointing) { successfullyUpdatedIncrementalState = await CreateCheckpointIncrementalAsync(context, sequencePoint, successfullyUpdatedIncrementalState); } else { await CreateFullCheckpointAsync(context, sequencePoint); } return BoolResult.Success; } } finally { ClearIncrementalCheckpointStateIfNeeded(successfullyUpdatedIncrementalState); } })); }
/// <summary> /// Creates a checkpoint for a given sequence point. /// </summary> public Task <BoolResult> CreateCheckpointAsync(OperationContext context, EventSequencePoint sequencePoint) { context = context.CreateNested(); string checkpointId = "Unknown"; long checkpointSize = 0; return(context.PerformOperationAsync( _tracer, async() => { bool successfullyUpdatedIncrementalState = false; try { // Creating a working temporary directory using (new DisposableDirectory(_fileSystem, _checkpointStagingDirectory)) { // NOTE(jubayard): this needs to be done previous to checkpointing, because we always // fetch the latest version's size in this way. This implies there may be some difference // between the reported value and the actual size on disk: updates will get in in-between. // The better alternative is to actually open the checkpoint and ask, but it seems like too // much. checkpointSize = _database.GetContentDatabaseSizeBytes().GetValueOrDefault(-1); // Saving checkpoint for the database into the temporary folder _database.SaveCheckpoint(context, _checkpointStagingDirectory).ThrowIfFailure(); if (_configuration.UseIncrementalCheckpointing) { checkpointId = await CreateCheckpointIncrementalAsync(context, sequencePoint); successfullyUpdatedIncrementalState = true; } else { checkpointId = await CreateFullCheckpointAsync(context, sequencePoint); } return BoolResult.Success; } } finally { ClearIncrementalCheckpointStateIfNeeded(context, successfullyUpdatedIncrementalState); } }, extraStartMessage: $"SequencePoint=[{sequencePoint}]", extraEndMessage: result => $"SequencePoint=[{sequencePoint}] Id=[{checkpointId}] SizeMb=[{(checkpointSize < 0 ? checkpointSize:checkpointSize*1e-6)}]")); }
/// <summary> /// Creates a checkpoint for a given sequence point. /// </summary> public Task <BoolResult> CreateCheckpointAsync(OperationContext context, EventSequencePoint sequencePoint) { context = context.CreateNested(nameof(CheckpointManager)); string checkpointId = "Unknown"; double contentColumnFamilySizeMb = -1; double contentDataSizeMb = -1; double metadataColumnFamilySizeMb = -1; double metadataDataSizeMb = -1; double sizeOnDiskMb = -1; return(context.PerformOperationAsync( _tracer, async() => { bool successfullyUpdatedIncrementalState = false; try { // Creating a working temporary directory using (new DisposableDirectory(_fileSystem, _checkpointStagingDirectory)) { // Write out the time this checkpoint was generated to the database. This will be used by // the workers in order to determine whether they should restore or not after restart. The // checkpoint id is generated inside the upload methods, so we only generate the guid here. // Since this is only used for reporting purposes, there's no harm in it. var checkpointGuid = Guid.NewGuid(); DatabaseWriteCheckpointCreationTime(context, checkpointGuid.ToString(), DateTime.UtcNow); // NOTE(jubayard): this needs to be done previous to checkpointing, because we always // fetch the latest version's size in this way. This implies there may be some difference // between the reported value and the actual size on disk: updates will get in in-between. // The better alternative is to actually open the checkpoint and ask, but it seems like too // much. if (_database is RocksDbContentLocationDatabase rocksDb) { contentColumnFamilySizeMb = rocksDb.GetLongProperty( RocksDbContentLocationDatabase.LongProperty.LiveFilesSizeBytes, RocksDbContentLocationDatabase.Entity.ContentTracking).Select(x => x * 1e-6).GetValueOrDefault(-1); contentDataSizeMb = rocksDb.GetLongProperty( RocksDbContentLocationDatabase.LongProperty.LiveDataSizeBytes, RocksDbContentLocationDatabase.Entity.ContentTracking).Select(x => x * 1e-6).GetValueOrDefault(-1); metadataColumnFamilySizeMb = rocksDb.GetLongProperty( RocksDbContentLocationDatabase.LongProperty.LiveFilesSizeBytes, RocksDbContentLocationDatabase.Entity.Metadata).Select(x => x * 1e-6).GetValueOrDefault(-1); metadataDataSizeMb = rocksDb.GetLongProperty( RocksDbContentLocationDatabase.LongProperty.LiveDataSizeBytes, RocksDbContentLocationDatabase.Entity.Metadata).Select(x => x * 1e-6).GetValueOrDefault(-1); } // Saving checkpoint for the database into the temporary folder _database.SaveCheckpoint(context, _checkpointStagingDirectory).ThrowIfFailure(); try { sizeOnDiskMb = _fileSystem .EnumerateFiles(_checkpointStagingDirectory, EnumerateOptions.Recurse) .Sum(fileInfo => fileInfo.Length) * 1e-6; } catch (IOException e) { _tracer.Error(context, $"Error counting size of checkpoint's staging directory `{_checkpointStagingDirectory}`: {e}"); } if (_configuration.UseIncrementalCheckpointing) { checkpointId = await CreateCheckpointIncrementalAsync(context, sequencePoint, checkpointGuid); successfullyUpdatedIncrementalState = true; } else { checkpointId = await CreateFullCheckpointAsync(context, sequencePoint, checkpointGuid); } return BoolResult.Success; } } finally { ClearIncrementalCheckpointStateIfNeeded(context, successfullyUpdatedIncrementalState); } },