Skip to content

Commit fafa498

Browse files
committed
Move objectType to GitPackCache's value
Otherwise, we would have I/O operations for every request for a wrong objectType. By having it as part of the value we can use the cache and aquire the information that the objectType does not match from the cache.
1 parent d0aa014 commit fafa498

File tree

5 files changed

+24
-18
lines changed

5 files changed

+24
-18
lines changed

src/NerdBank.GitVersioning/ManagedGit/GitPack.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,14 @@ public Stream GetObject(long offset, string objectType)
178178
}
179179
#endif
180180

181-
if (this.cache.TryOpen(offset, objectType, out Stream? stream))
181+
if (this.cache.TryOpen(offset, out (Stream ContentStream, string ObjectType)? hit))
182182
{
183-
return stream!;
183+
if (hit.Value.ObjectType != objectType)
184+
{
185+
throw new GitException($"An object of type {objectType} could not be located at offset {offset}.") { ErrorCode = GitException.ErrorCodes.ObjectNotFound };
186+
}
187+
188+
return hit.Value.ContentStream;
184189
}
185190

186191
GitPackObjectType packObjectType;

src/NerdBank.GitVersioning/ManagedGit/GitPackCache.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,14 @@ public abstract class GitPackCache : IDisposable
2222
/// <param name="offset">
2323
/// The offset of the Git object in the Git pack.
2424
/// </param>
25-
/// <param name="objectType">The object type of the object to retrieve.</param>
26-
/// <param name="stream">
27-
/// A <see cref="Stream"/> which will be set to the cached Git object.
25+
/// <param name="hit">
26+
/// A (<see cref="Stream"/>, ContentType) tuple which will be set to the cached data if found.
2827
/// </param>
2928
/// <returns>
3029
/// <see langword="true"/> if the object was found in cache; otherwise,
3130
/// <see langword="false"/>.
3231
/// </returns>
33-
public abstract bool TryOpen(long offset, string objectType, [NotNullWhen(true)] out Stream? stream);
32+
public abstract bool TryOpen(long offset, [NotNullWhen(true)] out (Stream ContentStream, string ObjectType)? hit);
3433

3534
/// <summary>
3635
/// Gets statistics about the cache usage.

src/NerdBank.GitVersioning/ManagedGit/GitPackMemoryCache.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,33 @@ namespace Nerdbank.GitVersioning.ManagedGit;
2121
/// twice, it is read from the <see cref="MemoryStream"/>, rather than the underlying <see cref="Stream"/>.
2222
/// </para>
2323
/// <para>
24-
/// <see cref="Add(long, string, Stream)"/> and <see cref="TryOpen(long, string, out Stream?)"/> return <see cref="Stream"/>
24+
/// <see cref="Add(long, string, Stream)"/> and <see cref="TryOpen(long, out ValueTuple{Stream, string}?)"/> return <see cref="Stream"/>
2525
/// objects which may operate on the same underlying <see cref="Stream"/>, but independently maintain
2626
/// their state.
2727
/// </para>
2828
/// </summary>
2929
public class GitPackMemoryCache : GitPackCache
3030
{
31-
private readonly Dictionary<(long, string), GitPackMemoryCacheStream> cache = new Dictionary<(long, string), GitPackMemoryCacheStream>();
31+
private readonly Dictionary<long, (GitPackMemoryCacheStream, string)> cache = new();
3232

3333
/// <inheritdoc/>
3434
public override Stream Add(long offset, string objectType, Stream stream)
3535
{
3636
var cacheStream = new GitPackMemoryCacheStream(stream);
37-
this.cache.Add((offset, objectType), cacheStream);
37+
this.cache.Add(offset, (cacheStream, objectType));
3838
return new GitPackMemoryCacheViewStream(cacheStream);
3939
}
4040

4141
/// <inheritdoc/>
42-
public override bool TryOpen(long offset, string objectType, [NotNullWhen(true)] out Stream? stream)
42+
public override bool TryOpen(long offset, [NotNullWhen(true)] out (Stream ContentStream, string ObjectType)? hit)
4343
{
44-
if (this.cache.TryGetValue((offset, objectType), out GitPackMemoryCacheStream? cacheStream))
44+
if (this.cache.TryGetValue(offset, out (GitPackMemoryCacheStream Stream, string ObjectType) tuple))
4545
{
46-
stream = new GitPackMemoryCacheViewStream(cacheStream!);
46+
hit = (new GitPackMemoryCacheViewStream(tuple.Stream), tuple.ObjectType);
4747
return true;
4848
}
4949

50-
stream = null;
50+
hit = null;
5151
return false;
5252
}
5353

@@ -65,7 +65,7 @@ protected override void Dispose(bool disposing)
6565
while (this.cache.Count > 0)
6666
{
6767
var key = this.cache.Keys.First();
68-
GitPackMemoryCacheStream? stream = this.cache[key];
68+
(GitPackMemoryCacheStream? stream, _) = this.cache[key];
6969
stream.Dispose();
7070
this.cache.Remove(key);
7171
}

src/NerdBank.GitVersioning/ManagedGit/GitPackNullCache.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ public override Stream Add(long offset, string objectType, Stream stream)
2525
}
2626

2727
/// <inheritdoc/>
28-
public override bool TryOpen(long offset, string objectType, [NotNullWhen(true)] out Stream? stream)
28+
public override bool TryOpen(long offset, [NotNullWhen(true)] out (Stream ContentStream, string ObjectType)? hit)
2929
{
30-
stream = null;
30+
hit = null;
3131
return false;
3232
}
3333

test/Nerdbank.GitVersioning.Tests/ManagedGit/GitPackMemoryCacheTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ public void StreamsAreIndependent()
2121
var cache = new GitPackMemoryCache();
2222

2323
Stream stream1 = cache.Add(0, "anObjectType", stream);
24-
Assert.True(cache.TryOpen(0, "anObjectType", out Stream stream2));
24+
Assert.True(cache.TryOpen(0, out (Stream ContentStream, string ObjectType)? hit));
25+
Assert.True(hit.HasValue);
26+
Assert.Equal("anObjectType", hit.Value.ObjectType);
2527

2628
using (stream1)
27-
using (stream2)
29+
using (Stream stream2 = hit.Value.ContentStream)
2830
{
2931
stream1.Seek(5, SeekOrigin.Begin);
3032
Assert.Equal(5, stream1.Position);

0 commit comments

Comments
 (0)