|
enum | m0_be_emap_optype {
M0_BEO_CREATE,
M0_BEO_DESTROY,
M0_BEO_INSERT,
M0_BEO_DELETE,
M0_BEO_UPDATE,
M0_BEO_MERGE,
M0_BEO_SPLIT,
M0_BEO_PASTE
} |
|
enum | m0_be_emap_key_format_version { M0_BE_EMAP_KEY_FORMAT_VERSION_1 = 1,
M0_BE_EMAP_KEY_FORMAT_VERSION = M0_BE_EMAP_KEY_FORMAT_VERSION_1
} |
|
enum | m0_be_emap_rec_format_version { M0_BE_EMAP_REC_FORMAT_VERSION_1 = 1,
M0_BE_EMAP_REC_FORMAT_VERSION = M0_BE_EMAP_REC_FORMAT_VERSION_1
} |
|
enum | m0_be_emap_format_version { M0_BE_EMAP_FORMAT_VERSION_1 = 1,
M0_BE_EMAP_FORMAT_VERSION = M0_BE_EMAP_FORMAT_VERSION_1
} |
|
|
static int | be_emap_cmp (const void *key0, const void *key1) |
|
static m0_bcount_t | be_emap_ksize (const void *k) |
|
static m0_bcount_t | be_emap_vsize (const void *d) |
|
static int | emap_it_pack (struct m0_be_emap_cursor *it, void(*btree_func)(struct m0_be_btree *btree, struct m0_be_tx *tx, struct m0_be_op *op, const struct m0_buf *key, const struct m0_buf *val), struct m0_be_tx *tx) |
|
static bool | emap_it_prefix_ok (const struct m0_be_emap_cursor *it) |
|
static int | emap_it_open (struct m0_be_emap_cursor *it) |
|
static void | emap_it_init (struct m0_be_emap_cursor *it, const struct m0_uint128 *prefix, m0_bindex_t offset, struct m0_be_emap *map) |
|
static void | be_emap_close (struct m0_be_emap_cursor *it) |
|
static int | emap_it_get (struct m0_be_emap_cursor *it) |
|
static int | be_emap_lookup (struct m0_be_emap *map, const struct m0_uint128 *prefix, m0_bindex_t offset, struct m0_be_emap_cursor *it) |
|
static int | be_emap_next (struct m0_be_emap_cursor *it) |
|
static int | be_emap_prev (struct m0_be_emap_cursor *it) |
|
static bool | be_emap_invariant (struct m0_be_emap_cursor *it) |
|
static int | emap_extent_update (struct m0_be_emap_cursor *it, struct m0_be_tx *tx, const struct m0_be_emap_seg *es) |
|
static int | be_emap_split (struct m0_be_emap_cursor *it, struct m0_be_tx *tx, struct m0_indexvec *vec, m0_bindex_t scan, struct m0_buf *cksum) |
|
static bool | be_emap_caret_invariant (const struct m0_be_emap_caret *car) |
|
static struct m0_rwlock * | emap_rwlock (struct m0_be_emap *emap) |
|
static void | emap_dump (struct m0_be_emap_cursor *it) |
|
static void | emap_key_init (struct m0_be_emap_key *key) |
|
static void | emap_rec_init (struct m0_be_emap_rec *rec) |
|
M0_INTERNAL int | m0_be_emap_dump (struct m0_be_emap *map) |
|
static void | delete_wrapper (struct m0_be_btree *btree, struct m0_be_tx *tx, struct m0_be_op *op, const struct m0_buf *key, const struct m0_buf *val) |
|
M0_INTERNAL void | m0_be_emap_init (struct m0_be_emap *map, struct m0_be_seg *db) |
|
M0_INTERNAL void | m0_be_emap_fini (struct m0_be_emap *map) |
|
M0_INTERNAL void | m0_be_emap_create (struct m0_be_emap *map, struct m0_be_tx *tx, struct m0_be_op *op, const struct m0_fid *fid) |
|
M0_INTERNAL void | m0_be_emap_destroy (struct m0_be_emap *map, struct m0_be_tx *tx, struct m0_be_op *op) |
|
M0_INTERNAL struct m0_be_emap_seg * | m0_be_emap_seg_get (struct m0_be_emap_cursor *it) |
|
M0_INTERNAL bool | m0_be_emap_ext_is_last (const struct m0_ext *ext) |
|
M0_INTERNAL bool | m0_be_emap_ext_is_first (const struct m0_ext *ext) |
|
M0_INTERNAL struct m0_be_op * | m0_be_emap_op (struct m0_be_emap_cursor *it) |
|
M0_INTERNAL int | m0_be_emap_op_rc (const struct m0_be_emap_cursor *it) |
|
M0_INTERNAL struct m0_be_domain * | m0_be_emap_seg_domain (const struct m0_be_emap *map) |
|
M0_INTERNAL void | m0_be_emap_lookup (struct m0_be_emap *map, const struct m0_uint128 *prefix, m0_bindex_t offset, struct m0_be_emap_cursor *it) |
|
M0_INTERNAL void | m0_be_emap_close (struct m0_be_emap_cursor *it) |
|
static bool | be_emap_changed (struct m0_be_emap_cursor *it, m0_bindex_t off) |
|
M0_INTERNAL void | m0_be_emap_next (struct m0_be_emap_cursor *it) |
|
M0_INTERNAL void | m0_be_emap_prev (struct m0_be_emap_cursor *it) |
|
M0_INTERNAL void | m0_be_emap_extent_update (struct m0_be_emap_cursor *it, struct m0_be_tx *tx, const struct m0_be_emap_seg *es) |
|
static int | update_next_segment (struct m0_be_emap_cursor *it, struct m0_be_tx *tx, m0_bindex_t delta, bool get_next) |
|
M0_INTERNAL void | m0_be_emap_merge (struct m0_be_emap_cursor *it, struct m0_be_tx *tx, m0_bindex_t delta) |
|
M0_INTERNAL void | m0_be_emap_split (struct m0_be_emap_cursor *it, struct m0_be_tx *tx, struct m0_indexvec *vec, struct m0_buf *cksum) |
|
M0_INTERNAL void | m0_be_emap_paste (struct m0_be_emap_cursor *it, struct m0_be_tx *tx, struct m0_ext *ext, uint64_t val, void(*del)(struct m0_be_emap_seg *), void(*cut_left)(struct m0_be_emap_seg *, struct m0_ext *, uint64_t), void(*cut_right)(struct m0_be_emap_seg *, struct m0_ext *, uint64_t)) |
|
M0_INTERNAL int | m0_be_emap_count (struct m0_be_emap_cursor *it, m0_bcount_t *segs) |
|
M0_INTERNAL void | m0_be_emap_obj_insert (struct m0_be_emap *map, struct m0_be_tx *tx, struct m0_be_op *op, const struct m0_uint128 *prefix, uint64_t val) |
|
M0_INTERNAL void | m0_be_emap_obj_delete (struct m0_be_emap *map, struct m0_be_tx *tx, struct m0_be_op *op, const struct m0_uint128 *prefix) |
|
M0_INTERNAL void | m0_be_emap_caret_init (struct m0_be_emap_caret *car, struct m0_be_emap_cursor *it, m0_bindex_t index) |
|
M0_INTERNAL void | m0_be_emap_caret_fini (struct m0_be_emap_caret *car) |
|
M0_INTERNAL m0_bcount_t | m0_be_emap_caret_step (const struct m0_be_emap_caret *car) |
|
M0_INTERNAL int | m0_be_emap_caret_move (struct m0_be_emap_caret *car, m0_bcount_t count) |
|
M0_INTERNAL int | m0_be_emap_caret_move_sync (struct m0_be_emap_caret *car, m0_bcount_t count) |
|
M0_INTERNAL void | m0_be_emap_credit (struct m0_be_emap *map, enum m0_be_emap_optype optype, m0_bcount_t nr, struct m0_be_tx_credit *accum) |
|
static bool | be_emap_invariant_check (struct m0_be_emap_cursor *it) |
|
struct m0_be_emap_seg | M0_XCA_DOMAIN (be) |
|
Extent map is a persistent transactional collection of extents in an abstract numerical name-space with a numerical value associated to each extent.
The name-space is a set of all 64-bit unsigned numbers from 0 to M0_BINDEX_MAX. An extent of the name-space consisting of numbers from A (inclusive) to B (exclusive) is denoted [A, B).
A segment is an extent together with a 64-bit value associated with it, denoted as ([A, B), V).
An extent map is a collection of segments whose extents are non-empty and form a partition of the name-space.
That is, an extent map is something like
Note that extents cover the whole name-space from 0 to M0_BINDEX_MAX without holes.
Possible applications of extent map include:
- allocation data for a data object. In this case an extent in the name-space is interpreted as an extent in the logical offset space of data object. A value associated with the extent is a starting block of a physical extent allocated to the logical extent. In addition to allocated extents, a map might contain "holes" and "not-allocated" extents, tagged with special otherwise impossible values;
- various resource identifier distribution maps: file identifiers, container identifiers, layout identifiers, recording state of resource name-spaces: allocated to a certain node, free, etc.
Extent map interface is based on a notion of map cursor (m0_be_emap_cursor): an object recording a position within a map (i.e., a segment reached by the iteration).
A cursor can be positioned at the segment including a given point in the name-space (m0_be_emap_lookup()) and moved through the segments (m0_be_emap_next() and m0_be_emap_prev()).
An extent map can be modified by the following functions:
- m0_be_emap_split(): split a segment into a collection of segments with given lengths and values, provided that their total length is the same as the length of the original segment;
- m0_be_emap_merge(): merge part of a segment into the next segment. The current segment is shrunk (or deleted if it would become empty) and the next segment is expanded downward;
- m0_be_emap_paste() handles more complicated cases.
It's easy to see that these operations preserve extent map invariant that extents are non-empty and form the name-space partition.
- Note
- The asymmetry between split and merge interfaces (i.e., the fact that a segment can be split into multiple segments at once, but only two segments can be merged) is because a user usually wants to inspect a segment before merging it with another one. For example, data object truncate goes through the allocation data segments downward until the target offset of reached. Each segment is analyzed, data-blocks are freed is necessary and the segment is merged with the next one.
-
Currently the length and ordering of prefix and value is fixed by the implementation. Should the need arise, prefixes and values of arbitrary size and ordering could be easily implemented at the expense of dynamic memory allocation during cursor initialization. Prefix comparison function could be supplied as m0_be_emap constructor parameter.
Extent map implementation details.
- See also
- extmap_internal.h
Few notes:
- after internal state has changed it is "opened" by emap_it_open() which updates external stats to match changes;
- similarly when external state has changed, it is "packed" into internal one by emap_it_pack().
- be_emap_invariant() checks implementation invariant: an extent map is an collection of segments with non-empty extents forming the partition of the name-space and ordered by their starting offsets. This creates a separate cursor within the same transaction as the cursor it is called against.
- A segment ([A, B), V) is stored as a record (A, V) with a key (prefix, B). Note, that the high extent end is used as a key. This way, m0_be_btree_cursor_get() can be used to position a cursor on a segment containing a given offset. Also note, that there is some redundancy in the persistent state: two consecutive segments ([A, B), V) and ([B, C), U) are stored as records (A, V) and (B, U) with keys (prefix, B) and (prefix, C) respectively. B is stored twice. Generally, starting offset of a segment extent can always be deduced from the key of previous segment (and for the first segment it's 0), so some slight economy of storage could be achieved at the expense of increased complexity and occasional extra storage traffic.
- Note
- be_emap_invariant() is potentially expensive. Consider turning it off conditionally.
Extent map implementation.
Extent map collection (m0_be_emap) is a table. 128-bit prefix is used to store multiple extent maps in the same table.
◆ m0_be_emap_format_version
Enumerator |
---|
M0_BE_EMAP_FORMAT_VERSION_1 | |
M0_BE_EMAP_FORMAT_VERSION | Current version, should point to the latest version present
|
Definition at line 124 of file extmap_internal.h.
◆ m0_be_emap_key_format_version
Enumerator |
---|
M0_BE_EMAP_KEY_FORMAT_VERSION_1 | |
M0_BE_EMAP_KEY_FORMAT_VERSION | Current version, should point to the latest version present
|
Definition at line 46 of file extmap_internal.h.
◆ m0_be_emap_optype
Possible persistent operations over the tree. Enumeration items are being reused to define transaction credit types also.
Definition at line 415 of file extmap.h.
◆ m0_be_emap_rec_format_version
Enumerator |
---|
M0_BE_EMAP_REC_FORMAT_VERSION_1 | |
M0_BE_EMAP_REC_FORMAT_VERSION | Current version, should point to the latest version present
|
Definition at line 80 of file extmap_internal.h.
◆ be_emap_caret_invariant()
◆ be_emap_changed()
◆ be_emap_close()
◆ be_emap_cmp()
static int be_emap_cmp |
( |
const void * |
key0, |
|
|
const void * |
key1 |
|
) |
| |
|
static |
◆ be_emap_invariant()
◆ be_emap_invariant_check()
◆ be_emap_ksize()
◆ be_emap_lookup()
◆ be_emap_next()
◆ be_emap_prev()
◆ be_emap_split()
◆ be_emap_vsize()
◆ delete_wrapper()
◆ emap_dump()
◆ emap_extent_update()
◆ emap_it_get()
◆ emap_it_init()
◆ emap_it_open()
◆ emap_it_pack()
◆ emap_it_prefix_ok()
◆ emap_key_init()
◆ emap_rec_init()
cksum of size cksum_nob will be present just before footer, update the same in emap header.
Definition at line 184 of file extmap.c.
◆ emap_rwlock()
◆ m0_be_emap_caret_fini()
◆ m0_be_emap_caret_init()
◆ m0_be_emap_caret_move()
Move the caret.
Asynchronous operation, get status via m0_be_emap_op(car->ct_it)->bo_sm.sm_rc.
Definition at line 840 of file extmap.c.
◆ m0_be_emap_caret_move_sync()
◆ m0_be_emap_caret_step()
Returns how far is the end of extent.
Definition at line 834 of file extmap.c.
◆ m0_be_emap_close()
Release the resources associated with the cursor.
Definition at line 360 of file extmap.c.
◆ m0_be_emap_count()
Returns number of segments in the map.
Definition at line 713 of file extmap.c.
◆ m0_be_emap_create()
◆ m0_be_emap_credit()
Calculates how many internal resources of tx_engine, described by m0_be_tx_credit, is needed to perform an operation over the . Function updates structure which is an input for m0_be_tx_prep().
- Parameters
-
optype | operation type over the . |
nr | number of operations. |
- Note
- in case of M0_BEO_SPLIT is the number of split parts.
Definition at line 886 of file extmap.c.
◆ m0_be_emap_destroy()
Destroy maps collection.
Definition at line 300 of file extmap.c.
◆ m0_be_emap_dump()
M0_INTERNAL int m0_be_emap_dump |
( |
struct m0_be_emap * |
map | ) |
|
◆ m0_be_emap_ext_is_first()
M0_INTERNAL bool m0_be_emap_ext_is_first |
( |
const struct m0_ext * |
ext | ) |
|
True iff the extent is the first one in a map.
Definition at line 323 of file extmap.c.
◆ m0_be_emap_ext_is_last()
M0_INTERNAL bool m0_be_emap_ext_is_last |
( |
const struct m0_ext * |
ext | ) |
|
True iff the extent is the last one in a map.
Definition at line 318 of file extmap.c.
◆ m0_be_emap_extent_update()
Updates the segment at the current cursor with the given segment having same prefix.
- Precondition
- m0_uint128_eq(&it->ec_seg.ee_pre, &es->ee_pre) == true
Definition at line 405 of file extmap.c.
◆ m0_be_emap_fini()
M0_INTERNAL void m0_be_emap_fini |
( |
struct m0_be_emap * |
map | ) |
|
Release the resources associated with the collection.
Definition at line 276 of file extmap.c.
◆ m0_be_emap_init()
Initialize maps collection.
- Parameters
-
db | - data-base environment used for persistency and transactional support. |
- Return values
-
-ENOENT | mapname is not found in the segment dictionary. |
Definition at line 258 of file extmap.c.
◆ m0_be_emap_lookup()
Initialises extent map cursor to point to the segment containing given offset in a map with a given prefix in a given collection.
All operations done through this cursor are executed in the context of given transaction.
Asynchronous operation, get status via m0_be_emap_op(it)->bo_sm.sm_rc.
- Precondition
- offset <= M0_BINDEX_MAX
- Return values
-
-ESRCH | no matching segment is found. The cursor is non-functional, but m0_be_emap_seg_get() contains information about the first segment of the next map (in prefix lexicographical order); |
-ENOENT | no matching segment is found and there is no map following requested one. |
Definition at line 344 of file extmap.c.
◆ m0_be_emap_merge()
Merge a part of the segment the cursor is currently positioned at with the next segment in the map.
Current segment's extent is shrunk by delta. If this would make it empty, the current segment is deleted. The next segment is expanded by delta downwards.
Asynchronous operation, get status via m0_be_emap_op(it)->bo_sm.sm_rc.
- Precondition
- !m0_be_emap_ext_is_last(m0_be_emap_seg_get(it))
-
delta <= m0_ext_length(m0_be_emap_seg_get(it));
Definition at line 432 of file extmap.c.
◆ m0_be_emap_next()
Move cursor to the next segment in its map.
Asynchronous operation, get status via m0_be_emap_op(it)->bo_sm.sm_rc.
- Precondition
- !m0_be_emap_ext_is_last(m0_be_emap_seg_get(it))
Definition at line 377 of file extmap.c.
◆ m0_be_emap_obj_delete()
Remove a map with the given prefix from the collection.
- Precondition
- the map must be in initial state: consists of a single extent, covering the whole name-space.
Definition at line 774 of file extmap.c.
◆ m0_be_emap_obj_insert()
Insert a new map with the given prefix into the collection.
Initially new map consists of a single extent:
Definition at line 744 of file extmap.c.
◆ m0_be_emap_op()
Returns the back-end operation of emap cursor
Definition at line 328 of file extmap.c.
◆ m0_be_emap_op_rc()
◆ m0_be_emap_paste()
M0_INTERNAL void m0_be_emap_paste |
( |
struct m0_be_emap_cursor * |
it, |
|
|
struct m0_be_tx * |
tx, |
|
|
struct m0_ext * |
ext, |
|
|
uint64_t |
val, |
|
|
void(*)(struct m0_be_emap_seg *) |
del, |
|
|
void(*)(struct m0_be_emap_seg *, struct m0_ext *, uint64_t) |
cut_left, |
|
|
void(*)(struct m0_be_emap_seg *, struct m0_ext *, uint64_t) |
cut_right |
|
) |
| |
Paste segment (ext, val) into the map, deleting or truncating overlapping segments as necessary.
Asynchronous operation, get status via m0_be_emap_op(it)->bo_sm.sm_rc.
- Parameters
-
del | - this call-back is called when an existing segment is completely covered by a new one and has to be deleted. The segment to be deleted is supplied as the call-back argument; |
cut_left | - this call-back is called when an existing segment has to be cut to give place to a new one and some non-empty left part of the existing segment remains in the map. m0_ext call-back argument is the extent being cut from the existing segment. The last argument is the value associated with the existing segment. The call-back must set seg->ee_val to the new value associated with the remaining left part of the segment; |
cut_right | - similar to cut_left, this call-back is called when some non-empty right part of an existing segment survives the paste operation. |
- Note
- It is possible that both left and right cut call-backs are called against the same segment (in the case where new segment fits completely into existing one).
-
Map invariant is temporarily violated during paste operation. No calls against the map should be made from the call-backs or, more generally, from the same transaction, while paste is running.
-
Call-backs are called in the order of cursor iteration, but this is not a part of official function contract.
Definition at line 517 of file extmap.c.
◆ m0_be_emap_prev()
Move cursor to the previous segment in its map.
Asynchronous operation, get status via m0_be_emap_op(it)->bo_sm.sm_rc.
- Precondition
- !m0_be_emap_ext_is_first(m0_be_emap_seg_get(it))
Definition at line 391 of file extmap.c.
◆ m0_be_emap_seg_domain()
◆ m0_be_emap_seg_get()
Returns an extent at the current cursor position.
Definition at line 313 of file extmap.c.
◆ m0_be_emap_split()
Split the segment the cursor is current positioned at into a collection of segments given by the vector.
Iterator is moved to the next segment after original one automatically.
- Parameters
-
vec | - a vector describing the collection of segments. vec->ov_vec.v_count[] array contains lengths of the extents and vec->ov_index[] array contains values associated with the corresponding extents. |
Empty segments from vec are skipped. On successful completion, the cursor is positioned on the last created segment.
Asynchronous operation, get status via m0_be_emap_op(it)->bo_sm.sm_rc.
- Precondition
- m0_vec_count(&vec->ov_vec) == m0_ext_length(m0_be_emap_seg_get(it))
Definition at line 464 of file extmap.c.
◆ M0_XCA_DOMAIN()
◆ update_next_segment()
◆ be_emap_ops
Initial value:= {
}
static m0_bcount_t be_emap_ksize(const void *k)
static m0_bcount_t be_emap_vsize(const void *d)
static int be_emap_cmp(const void *key0, const void *key1)
Definition at line 127 of file extmap.c.
◆ M0_XCA_DOMAIN [1/2]
◆ M0_XCA_DOMAIN [2/2]