public StreamBlockProxy TryRentIndexedStreamBlockProxy(StreamLog streamLog, StreamBlockRecord record) { StreamBlockProxy p = null; while (p == null) { var blockKey = new BlockKey(streamLog.Slid, record.Version); // ReSharper disable once InconsistentlySynchronizedField if (_blocks.TryGetValue(blockKey, out var handle)) { p = handle.Target as StreamBlockProxy; } else { // CD.GetOrAdd factory is not atomic, lock manually. // Lock on SL, not a global object. This also helps // to avoid a capturing lambda and the risk of collecting // an object held only by a weak reference during that lambda return. lock (streamLog) { if (_blocks.TryGetValue(blockKey, out handle)) { p = handle.Target as StreamBlockProxy; } else { p = StreamBlockProxy.Create(blockKey, this); var sb = streamLog.GetBlockFromRecord(record); // Could set directly without SetStreamBlock p.Block = sb; handle = GCHandle.Alloc(p, GCHandleType.Weak); if (!_blocks.TryAdd(blockKey, handle)) { // this should never happen unless there are different streamLog instances for the same slid, // which in turn should never happen because SLs are stored in SLM dictionary. ThrowHelper.FailFast("Cannot add newly created StreamBlockProxy to cache from inside a lock."); } } } } // will be null if cannot retain, then will start over p = p?.TryRetain(); } return(p); }
public bool GetIsCompleted(StreamLogId streamLogId) { var streamId = (long)streamLogId; using (var txn = Environment.BeginReadOnlyTransaction()) using (var c = _blocksDb.OpenReadOnlyCursor(txn)) { StreamBlockRecord value = default; if (c.TryGet(ref streamId, ref value, CursorGetOption.Set) && c.TryGet(ref streamId, ref value, CursorGetOption.LastDuplicate)) { return(value.Version == CompletedVersion); } return(false); } }
internal StreamBlock GetBlockFromRecord(StreamBlockRecord record) { StreamBlock block; // we cannot touch a block when it is stored if (record.BufferRef != default) { #pragma warning disable 618 block = StreamLogManager.BlockIndex.TryRentIndexedStreamBlock(this, record.BufferRef); #pragma warning restore 618 if (block.IsValid || record.Version == StreamBlockIndex.ReadyBlockVersion) { return(block); } // TODO (!) review why this was needed, sometimes we get "cannot get block that should exists", probably this is the fix //if (_streamLog.StreamLogManager.BlockIndex.TryGetValue(StreamLogId, record.Version, out record) // && record.BufferRef != default && !record.BufferRef.Flag //) //{ // FailCannotGetChunk(record); //} } // throw new NotImplementedException(); // TODO Storage block = StreamLogManager .BlockIndex .BlockStorage .TryGetStreamBlock((long)Slid, record.Version); if (block.IsValid) { return(block); } FailCannotGetBlock(); return(default);