2008-02-28 06:25:17 +01:00
|
|
|
#ifndef PACK_REVINDEX_H
|
|
|
|
#define PACK_REVINDEX_H
|
|
|
|
|
pack-revindex: introduce a new API
In the next several patches, we will prepare for loading a reverse index
either in memory (mapping the inverse of the .idx's contents in-core),
or directly from a yet-to-be-introduced on-disk format. To prepare for
that, we'll introduce an API that avoids the caller explicitly indexing
the revindex pointer in the packed_git structure.
There are four ways to interact with the reverse index. Accordingly,
four functions will be exported from 'pack-revindex.h' by the time that
the existing API is removed. A caller may:
1. Load the pack's reverse index. This involves opening up the index,
generating an array, and then sorting it. Since opening the index
can fail, this function ('load_pack_revindex()') returns an int.
Accordingly, it takes only a single argument: the 'struct
packed_git' the caller wants to build a reverse index for.
This function is well-suited for both the current and new API.
Callers will have to continue to open the reverse index explicitly,
but this function will eventually learn how to detect and load a
reverse index from the on-disk format, if one exists. Otherwise, it
will fallback to generating one in memory from scratch.
2. Convert a pack position into an offset. This operation is now
called `pack_pos_to_offset()`. It takes a pack and a position, and
returns the corresponding off_t.
Any error simply calls BUG(), since the callers are not well-suited
to handle a failure and keep going.
3. Convert a pack position into an index position. Same as above; this
takes a pack and a position, and returns a uint32_t. This operation
is known as `pack_pos_to_index()`. The same thinking about error
conditions applies here as well.
4. Find the pack position for a given offset. This operation is now
known as `offset_to_pack_pos()`. It takes a pack, an offset, and a
pointer to a uint32_t where the position is written, if an object
exists at that offset. Otherwise, -1 is returned to indicate
failure.
Unlike some of the callers that used to access '->offset' and '->nr'
directly, the error checking around this call is somewhat more
robust. This is important since callers should always pass an offset
which points at the boundary of two objects. The API, unlike direct
access, enforces that that is the case.
This will become important in a subsequent patch where a caller
which does not but could check the return value treats the signed
`-1` from `find_revindex_position()` as an index into the 'revindex'
array.
Two design warts are carried over into the new API:
- Asking for the index position of an out-of-bounds object will result
in a BUG() (since no such object exists), but asking for the offset
of the non-existent object at the end of the pack returns the total
size of the pack.
This makes it convenient for callers who always want to take the
difference of two adjacent object's offsets (to compute the on-disk
size) but don't want to worry about boundaries at the end of the
pack.
- offset_to_pack_pos() lazily loads the reverse index, but
pack_pos_to_index() doesn't (callers of the former are well-suited
to handle errors, but callers of the latter are not).
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-01-13 23:23:31 +01:00
|
|
|
/**
|
|
|
|
* A revindex allows converting efficiently between three properties
|
|
|
|
* of an object within a pack:
|
|
|
|
*
|
|
|
|
* - index position: the numeric position within the list of sorted object ids
|
|
|
|
* found in the .idx file
|
|
|
|
*
|
|
|
|
* - pack position: the numeric position within the list of objects in their
|
|
|
|
* order within the actual .pack file (i.e., 0 is the first object in the
|
|
|
|
* .pack, 1 is the second, and so on)
|
|
|
|
*
|
|
|
|
* - offset: the byte offset within the .pack file at which the object contents
|
|
|
|
* can be found
|
|
|
|
*/
|
|
|
|
|
2015-12-21 07:20:33 +01:00
|
|
|
struct packed_git;
|
|
|
|
|
pack-revindex: introduce a new API
In the next several patches, we will prepare for loading a reverse index
either in memory (mapping the inverse of the .idx's contents in-core),
or directly from a yet-to-be-introduced on-disk format. To prepare for
that, we'll introduce an API that avoids the caller explicitly indexing
the revindex pointer in the packed_git structure.
There are four ways to interact with the reverse index. Accordingly,
four functions will be exported from 'pack-revindex.h' by the time that
the existing API is removed. A caller may:
1. Load the pack's reverse index. This involves opening up the index,
generating an array, and then sorting it. Since opening the index
can fail, this function ('load_pack_revindex()') returns an int.
Accordingly, it takes only a single argument: the 'struct
packed_git' the caller wants to build a reverse index for.
This function is well-suited for both the current and new API.
Callers will have to continue to open the reverse index explicitly,
but this function will eventually learn how to detect and load a
reverse index from the on-disk format, if one exists. Otherwise, it
will fallback to generating one in memory from scratch.
2. Convert a pack position into an offset. This operation is now
called `pack_pos_to_offset()`. It takes a pack and a position, and
returns the corresponding off_t.
Any error simply calls BUG(), since the callers are not well-suited
to handle a failure and keep going.
3. Convert a pack position into an index position. Same as above; this
takes a pack and a position, and returns a uint32_t. This operation
is known as `pack_pos_to_index()`. The same thinking about error
conditions applies here as well.
4. Find the pack position for a given offset. This operation is now
known as `offset_to_pack_pos()`. It takes a pack, an offset, and a
pointer to a uint32_t where the position is written, if an object
exists at that offset. Otherwise, -1 is returned to indicate
failure.
Unlike some of the callers that used to access '->offset' and '->nr'
directly, the error checking around this call is somewhat more
robust. This is important since callers should always pass an offset
which points at the boundary of two objects. The API, unlike direct
access, enforces that that is the case.
This will become important in a subsequent patch where a caller
which does not but could check the return value treats the signed
`-1` from `find_revindex_position()` as an index into the 'revindex'
array.
Two design warts are carried over into the new API:
- Asking for the index position of an out-of-bounds object will result
in a BUG() (since no such object exists), but asking for the offset
of the non-existent object at the end of the pack returns the total
size of the pack.
This makes it convenient for callers who always want to take the
difference of two adjacent object's offsets (to compute the on-disk
size) but don't want to worry about boundaries at the end of the
pack.
- offset_to_pack_pos() lazily loads the reverse index, but
pack_pos_to_index() doesn't (callers of the former are well-suited
to handle errors, but callers of the latter are not).
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-01-13 23:23:31 +01:00
|
|
|
/*
|
|
|
|
* load_pack_revindex populates the revindex's internal data-structures for the
|
|
|
|
* given pack, returning zero on success and a negative value otherwise.
|
|
|
|
*/
|
2019-04-05 20:04:24 +02:00
|
|
|
int load_pack_revindex(struct packed_git *p);
|
2013-10-24 20:00:36 +02:00
|
|
|
|
pack-revindex: introduce a new API
In the next several patches, we will prepare for loading a reverse index
either in memory (mapping the inverse of the .idx's contents in-core),
or directly from a yet-to-be-introduced on-disk format. To prepare for
that, we'll introduce an API that avoids the caller explicitly indexing
the revindex pointer in the packed_git structure.
There are four ways to interact with the reverse index. Accordingly,
four functions will be exported from 'pack-revindex.h' by the time that
the existing API is removed. A caller may:
1. Load the pack's reverse index. This involves opening up the index,
generating an array, and then sorting it. Since opening the index
can fail, this function ('load_pack_revindex()') returns an int.
Accordingly, it takes only a single argument: the 'struct
packed_git' the caller wants to build a reverse index for.
This function is well-suited for both the current and new API.
Callers will have to continue to open the reverse index explicitly,
but this function will eventually learn how to detect and load a
reverse index from the on-disk format, if one exists. Otherwise, it
will fallback to generating one in memory from scratch.
2. Convert a pack position into an offset. This operation is now
called `pack_pos_to_offset()`. It takes a pack and a position, and
returns the corresponding off_t.
Any error simply calls BUG(), since the callers are not well-suited
to handle a failure and keep going.
3. Convert a pack position into an index position. Same as above; this
takes a pack and a position, and returns a uint32_t. This operation
is known as `pack_pos_to_index()`. The same thinking about error
conditions applies here as well.
4. Find the pack position for a given offset. This operation is now
known as `offset_to_pack_pos()`. It takes a pack, an offset, and a
pointer to a uint32_t where the position is written, if an object
exists at that offset. Otherwise, -1 is returned to indicate
failure.
Unlike some of the callers that used to access '->offset' and '->nr'
directly, the error checking around this call is somewhat more
robust. This is important since callers should always pass an offset
which points at the boundary of two objects. The API, unlike direct
access, enforces that that is the case.
This will become important in a subsequent patch where a caller
which does not but could check the return value treats the signed
`-1` from `find_revindex_position()` as an index into the 'revindex'
array.
Two design warts are carried over into the new API:
- Asking for the index position of an out-of-bounds object will result
in a BUG() (since no such object exists), but asking for the offset
of the non-existent object at the end of the pack returns the total
size of the pack.
This makes it convenient for callers who always want to take the
difference of two adjacent object's offsets (to compute the on-disk
size) but don't want to worry about boundaries at the end of the
pack.
- offset_to_pack_pos() lazily loads the reverse index, but
pack_pos_to_index() doesn't (callers of the former are well-suited
to handle errors, but callers of the latter are not).
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-01-13 23:23:31 +01:00
|
|
|
/*
|
|
|
|
* offset_to_pack_pos converts an object offset to a pack position. This
|
|
|
|
* function returns zero on success, and a negative number otherwise. The
|
|
|
|
* parameter 'pos' is usable only on success.
|
|
|
|
*
|
|
|
|
* If the reverse index has not yet been loaded, this function loads it lazily,
|
|
|
|
* and returns an negative number if an error was encountered.
|
|
|
|
*
|
|
|
|
* This function runs in time O(log N) with the number of objects in the pack.
|
|
|
|
*/
|
|
|
|
int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* pack_pos_to_index converts the given pack-relative position 'pos' by
|
|
|
|
* returning an index-relative position.
|
|
|
|
*
|
|
|
|
* If the reverse index has not yet been loaded, or the position is out of
|
|
|
|
* bounds, this function aborts.
|
|
|
|
*
|
|
|
|
* This function runs in constant time.
|
|
|
|
*/
|
|
|
|
uint32_t pack_pos_to_index(struct packed_git *p, uint32_t pos);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* pack_pos_to_offset converts the given pack-relative position 'pos' into a
|
|
|
|
* pack offset. For a pack with 'N' objects, asking for position 'N' will return
|
|
|
|
* the total size (in bytes) of the pack.
|
|
|
|
*
|
|
|
|
* If the reverse index has not yet been loaded, or the position is out of
|
|
|
|
* bounds, this function aborts.
|
|
|
|
*
|
|
|
|
* This function runs in constant time.
|
|
|
|
*/
|
|
|
|
off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos);
|
|
|
|
|
2008-02-28 06:25:17 +01:00
|
|
|
#endif
|