2
This code is derived from jgit (http://eclipse.org/jgit).
3
Copyright owners are documented in jgit's IP log.
5
This program and the accompanying materials are made available
6
under the terms of the Eclipse Distribution License v1.0 which
7
accompanies this distribution, is reproduced below, and is
8
available at http://www.eclipse.org/org/documents/edl-v10.php
12
Redistribution and use in source and binary forms, with or
13
without modification, are permitted provided that the following
16
- Redistributions of source code must retain the above copyright
17
notice, this list of conditions and the following disclaimer.
19
- Redistributions in binary form must reproduce the above
20
copyright notice, this list of conditions and the following
21
disclaimer in the documentation and/or other materials provided
22
with the distribution.
24
- Neither the name of the Eclipse Foundation, Inc. nor the
25
names of its contributors may be used to endorse or promote
26
products derived from this software without specific prior
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
using System.Collections.Generic;
47
using NGit.Storage.File;
48
using NGit.Storage.Pack;
52
namespace NGit.Storage.File
55
/// The cached instance of an
56
/// <see cref="ObjectDirectory">ObjectDirectory</see>
59
/// This class caches the list of loose objects in memory, so the file system is
60
/// not queried with stat calls.
62
internal class CachedObjectDirectory : FileObjectDatabase
65
/// The set that contains unpacked objects identifiers, it is created when
66
/// the cached instance is created.
69
/// The set that contains unpacked objects identifiers, it is created when
70
/// the cached instance is created.
72
private readonly ObjectIdOwnerMap<CachedObjectDirectory.UnpackedObjectId> unpackedObjects
73
= new ObjectIdOwnerMap<CachedObjectDirectory.UnpackedObjectId>();
75
private readonly ObjectDirectory wrapped;
77
private FileObjectDatabase.AlternateHandle[] alts;
79
/// <summary>The constructor</summary>
80
/// <param name="wrapped">the wrapped database</param>
81
internal CachedObjectDirectory(ObjectDirectory wrapped)
83
this.wrapped = wrapped;
84
FilePath objects = wrapped.GetDirectory();
85
string[] fanout = objects.List();
88
fanout = new string[0];
90
foreach (string d in fanout)
96
string[] entries = new FilePath(objects, d).List();
101
foreach (string e in entries)
103
if (e.Length != Constants.OBJECT_ID_STRING_LENGTH - 2)
109
ObjectId id = ObjectId.FromString(d + e);
110
unpackedObjects.Add(new CachedObjectDirectory.UnpackedObjectId(id));
112
catch (ArgumentException)
119
// ignoring the file that does not represent loose object
120
public override void Close()
124
// Don't close anything.
125
public override ObjectDatabase NewCachedDatabase()
130
internal override FileObjectDatabase NewCachedFileObjectDatabase()
135
internal override FilePath GetDirectory()
137
return wrapped.GetDirectory();
140
internal override Config GetConfig()
142
return wrapped.GetConfig();
145
internal override FS GetFS()
147
return wrapped.GetFS();
150
/// <exception cref="System.IO.IOException"></exception>
151
internal override ICollection<CachedPack> GetCachedPacks()
153
return wrapped.GetCachedPacks();
156
internal override FileObjectDatabase.AlternateHandle[] MyAlternates()
160
FileObjectDatabase.AlternateHandle[] src = wrapped.MyAlternates();
161
alts = new FileObjectDatabase.AlternateHandle[src.Length];
162
for (int i = 0; i < alts.Length; i++)
164
FileObjectDatabase s = src[i].db;
165
alts[i] = new FileObjectDatabase.AlternateHandle(s.NewCachedFileObjectDatabase());
171
/// <exception cref="System.IO.IOException"></exception>
172
internal override void Resolve(ICollection<ObjectId> matches, AbbreviatedObjectId
175
// In theory we could accelerate the loose object scan using our
176
// unpackedObjects map, but its not worth the huge code complexity.
177
// Scanning a single loose directory is fast enough, and this is
178
// unlikely to be called anyway.
180
wrapped.Resolve(matches, id);
183
internal override bool TryAgain1()
185
return wrapped.TryAgain1();
188
public override bool Has(AnyObjectId objectId)
190
return HasObjectImpl1(objectId);
193
internal override bool HasObject1(AnyObjectId objectId)
195
return unpackedObjects.Contains(objectId) || wrapped.HasObject1(objectId);
198
/// <exception cref="System.IO.IOException"></exception>
199
internal override ObjectLoader OpenObject(WindowCursor curs, AnyObjectId objectId
202
return OpenObjectImpl1(curs, objectId);
205
/// <exception cref="System.IO.IOException"></exception>
206
internal override ObjectLoader OpenObject1(WindowCursor curs, AnyObjectId objectId
209
if (unpackedObjects.Contains(objectId))
211
return wrapped.OpenObject2(curs, objectId.Name, objectId);
213
return wrapped.OpenObject1(curs, objectId);
216
internal override bool HasObject2(string objectId)
218
return unpackedObjects.Contains(ObjectId.FromString(objectId));
221
/// <exception cref="System.IO.IOException"></exception>
222
internal override ObjectLoader OpenObject2(WindowCursor curs, string objectName,
223
AnyObjectId objectId)
225
if (unpackedObjects.Contains(objectId))
227
return wrapped.OpenObject2(curs, objectName, objectId);
232
/// <exception cref="System.IO.IOException"></exception>
233
internal override long GetObjectSize1(WindowCursor curs, AnyObjectId objectId)
235
if (unpackedObjects.Contains(objectId))
237
return wrapped.GetObjectSize2(curs, objectId.Name, objectId);
239
return wrapped.GetObjectSize1(curs, objectId);
242
/// <exception cref="System.IO.IOException"></exception>
243
internal override long GetObjectSize2(WindowCursor curs, string objectName, AnyObjectId
246
if (unpackedObjects.Contains(objectId))
248
return wrapped.GetObjectSize2(curs, objectName, objectId);
253
/// <exception cref="System.IO.IOException"></exception>
254
internal override FileObjectDatabase.InsertLooseObjectResult InsertUnpackedObject
255
(FilePath tmp, ObjectId objectId, bool createDuplicate)
257
FileObjectDatabase.InsertLooseObjectResult result = wrapped.InsertUnpackedObject(
258
tmp, objectId, createDuplicate);
261
case FileObjectDatabase.InsertLooseObjectResult.INSERTED:
262
case FileObjectDatabase.InsertLooseObjectResult.EXISTS_LOOSE:
264
unpackedObjects.AddIfAbsent(new CachedObjectDirectory.UnpackedObjectId(objectId));
268
case FileObjectDatabase.InsertLooseObjectResult.EXISTS_PACKED:
269
case FileObjectDatabase.InsertLooseObjectResult.FAILURE:
277
/// <exception cref="System.IO.IOException"></exception>
278
internal override PackFile OpenPack(FilePath pack, FilePath idx)
280
return wrapped.OpenPack(pack, idx);
283
/// <exception cref="System.IO.IOException"></exception>
284
internal override void SelectObjectRepresentation(PackWriter packer, ObjectToPack
285
otp, WindowCursor curs)
287
wrapped.SelectObjectRepresentation(packer, otp, curs);
290
[System.Serializable]
291
private class UnpackedObjectId : ObjectIdOwnerMap.Entry
293
protected internal UnpackedObjectId(AnyObjectId id) : base(id)