Fully materialize an ObjectLoader before returning it from ObjectDatabase
By forcing the ObjectLoader to fully reconstruct the requested object
and store it under getCachedBytes() before we return the ObjectLoader
to the caller we can ensure that the underlying PackFile remains valid
throughout the entire load.
If memory pressure causes the PackFile's windows to be evicted, and
the pack closes, and is replaced underneath of us, we can correctly
catch and handle the PackMismatchException or IOException by closing
the pack, rescanning the ObjectDirectory, and starting our search all
over again. Doing so is expensive, as we may have already unpacked
a large part of the object's delta chain before finding the pack was
modified, but its better than failing outright due to a race condition.
Note that this does not resolve the concurrent access problems in
PackWriter, as the cached PackedObjectLoaders are referenced very
late, and go back to the original PackFile, not the cached store.
Because we fully access the pack data up front during materialize()
we no longer need to hold the WindowCursor inside of the individual
loader instance.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>