Basically, its an stripped-down xcache without rm_entries, lru queues and
evictions. As a result, we expect that the locking scheme will be much
simpler.
Moreover, we have queued to rewrite xcache in order to be based on xindex.
Entry states
An entry during its lifetime will pass from the following states:
- XINDEX_NODE_FREE, when the node is unclaimed.
- XINDEX_NODE_CLAIMED, when the node is claimed, initialized and is pending
insertion.
- XINDEX_NODE_ACTIVE, when the entry is inserted in the hash table.
- XINDEX_NODE_REMOVED, when the entry is removed from the hash table (but is
still claimed).
After an entry is removed, its next state is XINDEX_NODE_FREE and the cycle
starts again. We name this cycle an epoch, and we define that a new entry
epoch begins once it is removed from xindex.
Xindex handler
The new xindex handler is a step forward from the xcache handler, which was a
typedef of xqindex and pointed directly to the internal node.
In this iteration, we have separated the bits of the xindex_hanlder in two
fields:
- The rightmost bits are used to store the xqindex of the entry. These bits
will be at most 32, since the index size is a uint32_t.
- The rest leftmost bits are used to keep the epoch of the handler.
The handler’s epoch is not always the same as the entry’s epoch. It is a
snapshot of the entry’s epoch when the handler was claimed by the user.
Effectively, this means that if an entry gets removed, all previous handlers
become invalid.
Epoch overflow
On a long enough time line, the epoch of every entry drops to zero. The soonest
this will happen is after 2^32 (or 4 billion) insertion/removal pairs. The side effect of this
is that a handler that was previously invalid may become valid again.
This may sound severe, but should only affect peers that:
- keep a copy of an xindex handler somewhere without updating the entry’s
refcount and
- may consult that handler only after the entry has been inserted and removed at least
4 billion times.
Probably, there is no such peer but if there is, it can plug a function
on the on_recycle_handler hook, so that it can get notified and resort to
the appropriate actions.
Xindex entry contents
The entry contents are kept in a priv pointer in the xindex_entry struct. The
only way a peer can access the contents is through the xindex handler. Note
that if the entry has changed epoch, previous handlers become invalid.
This way, we can find bugs more easily, since early removal of an entry is now
detected if later on someone tries to get the entry’s contents.