stasis-aries-wal/stasis/operations/regions.h
Sears Russell 5ffd1110e9 Added concept of "transaction fingerprints"
The region allocator marks freed regions "Condemned" before actually freeing them.  Condemned regions are associated 
with a transaction; before they can be reused / coalesced the transaction that condemned them must complete.

The region allocator used "TisActiveTransaction(xid)" to determine whether a given transaction had completed.  The 
problem is that Stasis now reuses transaction id's, and condemned regions were never reclaimed in practice.  A transaction
fingerprint is a unique identifier (currently transaction id, rec_lsn) that can be used to distinguish transactions that
did not execute concurrently.

I considered an alternative design based upon end-of-transaction actions.  This would have worked as well, but would 
have been a more invasive change.
2010-02-18 19:12:46 +00:00

74 lines
3.1 KiB
C

#ifndef STASIS_OPERATIONS_REGIONS_H
#define STASIS_OPERATIONS_REGIONS_H
#include <stasis/operations.h>
/**
Allocates and deallocates regions of pages. The page before each
region is of type BOUNDARY_TAG. All regions except the last one in
the page file have a BOUNDARY_TAG page immediately after the end of
the region.
Each region is managed by an allocation manager, which manages the
allocation of pages within a region. The contents of pages within
a newly allocated region are undefined.
*/
typedef struct boundary_tag {
pageid_t size;
pageid_t prev_size;
int status;
stasis_transaction_fingerprint_t region_xid_fp;
int allocation_manager;
} boundary_tag;
#define REGION_BASE (123)
#define REGION_VACANT (REGION_BASE + 0)
#define REGION_ZONED (REGION_BASE + 1)
#define REGION_OCCUPIED (REGION_BASE + 2)
#define REGION_CONDEMNED (REGION_BASE + 3)
void regionsInit(stasis_log_t *log);
pageid_t TregionAlloc(int xid, pageid_t pageCount, int allocaionManager);
void TregionDealloc(int xid, pageid_t firstPage);
pageid_t TregionSize(int xid, pageid_t firstPage);
void TregionForce(int xid, pageid_t pid);
/** Currently, this function is O(n) in the number of regions, so be careful! */
void TregionFindNthActive(int xid, pageid_t n, pageid_t * firstPage, pageid_t * size);
/**
* Read the active boundary tag that follows the given region.
* Inactive boundary tags (ones that are locked by ongoing transactions, or that point
* to free space) will be skipped.
*
* @param xid The transaction reading the boundary tag
* @param pid A pointer to the current pageid.
* @param tag A pointer to a buffer that will hold the next boundary tag.
* @param allocationManager The allocation manager whose tags should be returned, or 0 if all active tags should be returned.
* @return 0 on failure, true on success
*/
int TregionNextBoundaryTag(int xid, pageid_t*pid, boundary_tag *tag, int allocationManager);
/** Read the boundary tag marking the first page of some region. If pid = ROOT_RECORD.page, this will return the first boundary tag.
*
* @param xid The transaction examining the boundary tag
* @param pid The first page in the region (ie: the one returned by TregionAlloc(). In the current implementation, the boundary tag lives on the page before this one.
* @param tag A buffer that the tag will be read into.
*/
int TregionReadBoundaryTag(int xid, pageid_t pid, boundary_tag *tag);
stasis_operation_impl stasis_op_impl_boundary_tag_alloc();
stasis_operation_impl stasis_op_impl_region_alloc();
stasis_operation_impl stasis_op_impl_region_alloc_inverse();
stasis_operation_impl stasis_op_impl_region_dealloc();
stasis_operation_impl stasis_op_impl_region_dealloc_inverse();
/** This function checks the regions in the page file for consistency.
It makes sure that the doublly linked list is consistent (eg
this->next->prev == this), and it makes sure that all boundary
tags pages (that are marked REGION_ZONED) occur somewhere in the
linked list. */
void fsckRegions(int xid);
// XXX need callbacks to handle transaction commit/abort.
#endif