made pass over log documentation

This commit is contained in:
Sears Russell 2009-05-13 22:06:58 +00:00
parent a611775f8f
commit 3ff75ff568
11 changed files with 212 additions and 113 deletions

View file

@ -74,7 +74,7 @@ BRIEF_MEMBER_DESC = YES
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
REPEAT_BRIEF = NO
# This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string
@ -270,7 +270,7 @@ SUBGROUPING = YES
# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
TYPEDEF_HIDES_STRUCT = NO
TYPEDEF_HIDES_STRUCT = YES
# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
# determine which symbols to keep in memory and which to flush to disk.
@ -384,7 +384,7 @@ HIDE_SCOPE_NAMES = NO
# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
SHOW_INCLUDE_FILES = NO
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
@ -396,7 +396,7 @@ INLINE_INFO = YES
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
SORT_MEMBER_DOCS = NO
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
# brief documentation of file, namespace and class members alphabetically

View file

@ -3,17 +3,24 @@
*//**
@defgroup BUFFER_MANAGER
@ingroup LLADD_CORE
*//** @defgroup BUFFER_MANAGER_IMPLEMENTATIONS
@ingroup BUFFER_MANAGER
*//**
@defgroup BUFFER_MANAGER_IMPLEMENTATIONS
@ingroup BUFFER_MANAGER
*//**
@defgroup PAGE_EVICTION
@ingroup BUFFER_MANAGER
*//**
@defgroup LOGGER
@ingroup LLADD_CORE
*//**
@defgroup LOGGING_IMPLEMENTATIONS
@ingroup LOGGER
*//**
@defgroup LOGGING_INTERFACES
@ingroup LOGGER
*//**
@defgroup LOGGING_DISCIPLINES
@ingroup LOGGER
@ingroup LOGGER
*//**
@defgroup RECOVERY
@ingroup LLADD_CORE

View file

@ -2,6 +2,13 @@
#include <stasis/latches.h>
#include <string.h>
#include <assert.h>
/**
* @file
*
* A non-durable Stasis log implementation stores log entries in RAM.
*
* @ingroup LOGGING_IMPLEMENTATIONS
*/
typedef struct {
rwl * flushedLSN_lock;

View file

@ -39,6 +39,8 @@ authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.
---*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
@ -58,6 +60,16 @@ terms specified in this license.
#include <stasis/logger/logWriterUtils.h>
#include <stasis/logger/logHandle.h>
/**
* @file
*
* A Stasis log implementation that uses safe writes (copy tail, force, rename) to perform truncation.
*
* @todo The safeWrites log implementation is not optimized for reading old entries.
*
* @ingroup LOGGING_IMPLEMENTATIONS
*/
/**
Latch order: truncate_mutex, write_mutex, read_mutex
*/
@ -478,11 +490,7 @@ static int close_LogWriter(stasis_log_t* log) {
return 0;
}
void stasis_log_safe_writes_delete(const char* log_filename) {
remove(log_filename);
}
const LogEntry * readLSNEntry_LogWriter(stasis_log_t * log, const lsn_t LSN) {
static const LogEntry * readLSNEntry_LogWriter(stasis_log_t * log, const lsn_t LSN) {
stasis_log_safe_writes_state* sw = log->impl;
LogEntry * ret;
@ -549,7 +557,7 @@ const LogEntry * readLSNEntry_LogWriter(stasis_log_t * log, const lsn_t LSN) {
Perform the move, and release the latch.
*/
int truncateLog_LogWriter(stasis_log_t* log, lsn_t LSN) {
static int truncateLog_LogWriter(stasis_log_t* log, lsn_t LSN) {
stasis_log_safe_writes_state* sw = log->impl;
FILE *tmpLog;
@ -734,7 +742,7 @@ int truncateLog_LogWriter(stasis_log_t* log, lsn_t LSN) {
}
lsn_t firstLogEntry_LogWriter(stasis_log_t* log) {
static lsn_t firstLogEntry_LogWriter(stasis_log_t* log) {
stasis_log_safe_writes_state* sw = log->impl;
assert(sw->fp);
@ -890,3 +898,7 @@ stasis_log_t* stasis_log_safe_writes_open(const char * filename,
return log;
}
void stasis_log_safe_writes_delete(const char* log_filename) {
remove(log_filename);
}

View file

@ -8,32 +8,32 @@
#include <stasis/redblack.h>
#include <stasis/replacementPolicy.h>
typedef struct entry {
typedef struct stasis_replacement_policy_lru_entry {
void * value;
uint64_t clock;
} entry;
} stasis_replacement_policy_lru_entry;
typedef struct lru {
typedef struct stasis_replacement_policy_lru_t {
uint64_t now;
struct LH_ENTRY(table) * hash;
struct RB_ENTRY(tree) * lru;
void * (*getNode)(void * page, void * conf);
void (*setNode)(void * page, void * n, void * conf);
void * conf;
} lru;
} stasis_replacement_policy_lru_t;
int cmp(const void * ap, const void * bp, const void * ignored) {
const entry * a = ap;
const entry * b = bp;
static int stasis_replacement_policy_lru_entry_cmp(const void * ap, const void * bp, const void * ignored) {
const stasis_replacement_policy_lru_entry * a = ap;
const stasis_replacement_policy_lru_entry * b = bp;
return a->clock < b->clock ? -1
: a->clock == b->clock ? 0
return a->clock < b->clock ? -1
: a->clock == b->clock ? 0
: 1;
}
static void lruDeinit(replacementPolicy* r) {
static void stasis_replacement_policy_lru_deinit(replacementPolicy* r) {
//XXX free other stuff
lru * l = r->impl;
stasis_replacement_policy_lru_t * l = r->impl;
LH_ENTRY(destroy)(l->hash);
RB_ENTRY(destroy)(l->lru);
@ -43,56 +43,56 @@ static void lruDeinit(replacementPolicy* r) {
/** @todo handle clock wraps properly! */
static void lruHit(replacementPolicy* r, void * p) {
lru * l = r->impl;
entry * e = l->getNode(p, l->conf);
static void stasis_replacement_policy_lru_hit(replacementPolicy* r, void * p) {
stasis_replacement_policy_lru_t * l = r->impl;
stasis_replacement_policy_lru_entry * e = l->getNode(p, l->conf);
assert(e);
entry * old = (entry * ) RB_ENTRY(delete)(e, l->lru);
stasis_replacement_policy_lru_entry * old = (stasis_replacement_policy_lru_entry * ) RB_ENTRY(delete)(e, l->lru);
assert(e == old);
e->clock = l->now;
l->now++;
old = (entry *)RB_ENTRY(search)(e, l->lru);
l->now++;
old = (stasis_replacement_policy_lru_entry *)RB_ENTRY(search)(e, l->lru);
assert(e == old);
}
static void * lruGetStale(replacementPolicy* r) {
lru * l = r->impl;
entry * e = (entry * ) RB_ENTRY(min)(l->lru);
static void * stasis_replacement_policy_lru_get_stale(replacementPolicy* r) {
stasis_replacement_policy_lru_t * l = r->impl;
stasis_replacement_policy_lru_entry * e = (stasis_replacement_policy_lru_entry * ) RB_ENTRY(min)(l->lru);
return e ? e->value : 0;
}
static void* lruRemove(replacementPolicy* r, void * p) {
lru * l = r->impl;
entry * e = l->getNode(p, l->conf);
static void* stasis_replacement_policy_lru_remove(replacementPolicy* r, void * p) {
stasis_replacement_policy_lru_t * l = r->impl;
stasis_replacement_policy_lru_entry * e = l->getNode(p, l->conf);
assert(e);
entry * old = (entry *) RB_ENTRY(delete)(e, l->lru);
stasis_replacement_policy_lru_entry * old = (stasis_replacement_policy_lru_entry *) RB_ENTRY(delete)(e, l->lru);
assert(old == e);
void * ret = e->value;
free(e);
return ret;
}
static void lruInsert(replacementPolicy* r, void * p) {
lru * l = r->impl;
entry * e = malloc(sizeof(entry));
static void stasis_replacement_policy_lru_insert(replacementPolicy* r, void * p) {
stasis_replacement_policy_lru_t * l = r->impl;
stasis_replacement_policy_lru_entry * e = malloc(sizeof(stasis_replacement_policy_lru_entry));
e->value = p;
e->clock = l->now;
l->now++;
l->setNode(p, l->conf, e);
entry * old = (entry *) RB_ENTRY(search)(e, l->lru);
stasis_replacement_policy_lru_entry * old = (stasis_replacement_policy_lru_entry *) RB_ENTRY(search)(e, l->lru);
assert(e == old);
}
replacementPolicy * lruInit() {
replacementPolicy * stasis_replacement_policy_lru_init() {
replacementPolicy * ret = malloc(sizeof(replacementPolicy));
lru * l = malloc(sizeof(lru));
stasis_replacement_policy_lru_t * l = malloc(sizeof(stasis_replacement_policy_lru_t));
l->now = 0;
l->hash = LH_ENTRY(create)(10);
// l->lru = RB_ENTRY(init)((int(*)(const void*,const void*,const void*))cmp, 0);
l->lru = RB_ENTRY(init)(cmp, 0);
ret->init = lruInit;
ret->deinit = lruDeinit;
ret->hit = lruHit;
ret->getStale = lruGetStale;
ret->remove = lruRemove;
ret->insert = lruInsert;
l->lru = RB_ENTRY(init)(stasis_replacement_policy_lru_entry_cmp, 0);
ret->init = stasis_replacement_policy_lru_init;
ret->deinit = stasis_replacement_policy_lru_deinit;
ret->hit = stasis_replacement_policy_lru_hit;
ret->getStale = stasis_replacement_policy_lru_get_stale;
ret->remove = stasis_replacement_policy_lru_remove;
ret->insert = stasis_replacement_policy_lru_insert;
ret->impl = l;
return ret;
}

View file

@ -2,7 +2,9 @@
#define __INMEMORYLOG
#include <stasis/logger/logger2.h>
/**
* Allocate a new non-persistent Stasis log.
*/
stasis_log_t* stasis_log_impl_in_memory_open();
#endif

View file

@ -123,6 +123,7 @@ LogEntry * allocCLRLogEntry(const LogEntry * e);
void freeLogEntry(const LogEntry * e);
/**
@param lh The log handle the entry will be stored in. (Needed because some log entries are of type INTERNALLOG) May be NULL if e is not of type INTERNALLOG.
@param e A log entry of any type.
@return the length, in bytes, of e.
*/
lsn_t sizeofLogEntry(stasis_log_t * lh, const LogEntry * e);

View file

@ -43,21 +43,18 @@ terms specified in this license.
/**
* @file
*
* Interface to Stasis' log file.
*
* @ingroup LOGGING_DISCIPLINE
*
* $Id$
* Transaction-level log manipulation routines (commit, update, etc...) that maintain consistency with the transaction tables.
*
* @ingroup LOGGING_INTERFACES
*/
#ifndef __LOGGER2_H__
#define __LOGGER2_H__
#include <stasis/common.h>
typedef struct stasis_log_t stasis_log_t;
typedef struct stasis_log_group_force_t stasis_log_group_force_t;
typedef enum {
@ -94,77 +91,162 @@ typedef int (guard_fcn_t)(const LogEntry *, void *);
*/
extern TransactionLog stasis_transaction_table[MAX_TRANSACTIONS];
/**
* Interface provided by Stasis log implementations.
*
* This struct defines the interface provided by Stasis log
* implementations. New log implementations should provide a
* method that populates a stasis_log_t with appropriate function
* pointers and runtime state.
*
* @see safeWrites.c, inMemoryLog.c for example implementations.
*
* @ingroup LOGGING_IMPLEMENTATIONS
*/
struct stasis_log_t {
/**
Needed by sizeofLogEntry
Return the size of an implementation-specific log entry.
Log implementations may store extra information in "internal entries".
These entries will be ignored by higher-level code. In order to
facilitate memory management, Stasis' sizeofLogEntry() method supports
internal entries by calling this method.
@param log "this" log object
@param e A log entry with type INTERNALLOG
@return the length of e, in bytes.
*/
lsn_t (*sizeof_internal_entry)(struct stasis_log_t* log, const LogEntry * e);
/**
Append a log entry to the end of the log.
@param e This call sets e->LSN to entry's offset.
Append a log entry to the end of the log.
@param log "this" log object
@param e The entry to be written to log. After the call returns, e->LSN will be the new entry's offset.
@return 0 on success
*/
int (*write_entry)(struct stasis_log_t* log, LogEntry * e);
/**
Read a log entry, given its LSN.
@param lsn The lsn of the log entry to be read.
Read a log entry, given its LSN.
@param log "this" log object
@param lsn The LSN of the log entry to be read. This must be the LSN of a valid log entry.
@return The LogEntry of interest. Should be freed with freeLogEntry().
*/
const LogEntry* (*read_entry)(struct stasis_log_t* log, lsn_t lsn);
/**
Given a log entry, return the LSN of the next entry.
This method returns the LSN of the log entry that will succeed the
given entry. Since the meaning of the LSN field is defined by the
underlying log implementation, this could return the offset into some
underlying file, or simply e->LSN + 1.
@param log "this" log object
@param e A LogEntry that has already been stored in this log.
@return the LSN of the next entry. Since LSN's must define an order
over the log, this must be greater than e->LSN.
*/
lsn_t (*next_entry)(struct stasis_log_t* log, const LogEntry * e);
/**
This function returns the LSN of the most recent
log entry that has not been flushed to disk. If the entire log
is flushed, this function returns the LSN of the entry that will
be allocated the next time the log is appended to.
Return the LSN of the earliest log entry that may not survive a crash.
@param log The log file, which may or may not support durability.
Return the LSN of the earliest log entry that may not survive a crash.
If the entire log is stable, or the log does not support durability,
this function returns the LSN of the entry that will be allocated
the next time the log is appended to.
@param log "this" log object, which may or may not support durability.
@param mode The mode in which the log entries must have been forced.
*/
lsn_t (*first_unstable_lsn)(struct stasis_log_t* log,
stasis_log_force_mode_t mode);
/**
This function returns the LSN of the next log entry passed to
write_entry. This shouldn't be used to determine which entry a
particular call will assign; rather it is used to provide a lower
bound on the LSN of newly-loaded LSN-free pages.
Return the LSN that will be assigned to the next entry written to this log.
This function returns the LSN that will be assigned to the next entry
written to log. Because multiple threads may be accessing the same
stasis_log_t object, this method should not be used to determine which
LSN will actually be assigned; rather it is used to compute a valid
lower bound of the LSN of newly-loaded LSN-free pages.
@param log "this" log object
*/
lsn_t (*next_available_lsn)(struct stasis_log_t* log);
/**
Force any enqueued, unwritten entries to disk
Force any enqueued, unwritten entries to disk.
Once this method returns, any log entries written before the call began
should survive subsequent crashes. If the underlying log implementation
is not durable, then this method has no effect.
This method should not attempt to amortize the cost of multiple
concurrent calls; stasis_log_t::group_force provides takes care of this.
If group_force is non-null, callers should invoke methods on it rather
than call this method directly.
@param log "this" log object, which may or may not support durability.
@param mode The reason the log tail should be forced; in certain
environments, force writes that maintain the write-ahead invariant are
treated differently than those for transaction commit.
*/
void (*force_tail)(struct stasis_log_t* log, stasis_log_force_mode_t mode);
/**
@param lsn The first lsn that will be available after truncation.
@return 0 on success
Delete a prefix of the log.
This method allows the log to "forget" about old log entries. Its
behavior is implementation defined. A call to truncate amounts to a
promise that subsequent calls to stasis_log_t::read_entry will not
request entries before the truncation point.
@param log "this" log object.
@param lsn The truncation point; the first lsn that will be available after truncation.
@return 0 on success
*/
int (*truncate)(struct stasis_log_t* log, lsn_t lsn);
/**
Returns the LSN of the first entry of the log. If the log is
empty, return the LSN that will be assigned to the next log
entry that is appended to the log.
Return the LSN of the first entry of the log.
This function returns the LSN of the earliest entry in the log, which
must be less than or equal to the highest value ever passed into
stasis_log_t::truncate(). If the log is empty, this function returns
the same value as stasis_log_t::next_available_lsn().
@param log "this" log object
@return A valid LSN that may be passed into stasis_log_t::read_entry().
*/
lsn_t (*truncation_point)(struct stasis_log_t* log);
/**
Ensure that the tail of the log is durable, and free any associated resources.
Ensure that the tail of the log is durable, and free any associated resources.
@return 0 on success
*/
int (*close)(struct stasis_log_t* log);
/**
* Determine whether or not this log provides durability.
*
* @return true if this log implementation is durable, zero otherwise.
*/
int (*is_durable)(struct stasis_log_t* log);
/**
* @see groupForce.c
*/
stasis_log_group_force_t * group_force;
/**
* Implementation-specific state.
*/
void* impl;
};

View file

@ -43,40 +43,13 @@ permission to use and distribute the software in accordance with the
terms specified in this license.
---*/
/**
* @file
*
* New version of logstreamer; designed to work with logEntry, and has
* a simplified API.
*
* logstreamer is the implementation of writing the log tail
* It must be bufferred -- in that when something is written to the log tail it
* is not immediately written to disk, but rather just to memory. But
* logstreamer must be able to force flush to disk, which will be done when a
* commit log entry is written to the log tail
*
* Note: using the stdio FILEs for this, and by default it is "fully" buffered.
* The log tail may be flushed to disk without an explicit call to fflush (when
* the program terminates, the file closes), but this is acceptable because it
* never hurts to have more flushes to disk, as long as it doesn't hurt
* performance.
*
* @todo Everything in this file cores on failure (no error handling yet)
* @todo logWriter is optimized for forward operation, scanning backwards
* (as in abort()) is very slow. Perhaps we should maintian a
* 'write behind' buffer?
*
* $Id$
*
*/
#include <stasis/common.h>
#include <stasis/logger/logger2.h>
BEGIN_C_DECLS
/**
Start a new log stream by opening the log file for reading. This
is stasis's default log implementation, and uses safe writes to
is Stasis's default log implementation, and uses safe writes to
perform truncation.
@return NULL on error

View file

@ -32,7 +32,7 @@ typedef struct replacementPolicy {
void * impl;
} replacementPolicy;
replacementPolicy * lruInit();
replacementPolicy * stasis_replacement_policy_lru_init();
replacementPolicy * lruFastInit(
struct LL_ENTRY(node_t) * (*getNode)(void * page, void * conf),
void (*setNode)(void * page,

View file

@ -472,11 +472,26 @@ terms specified in this license.
* @todo Write a brief howto to explain the implementation of new operations.
*
*/
/**
* @defgroup LOGGER Log
*
* Stasis' log API consists of three components.
*/
/**
* @defgroup LOGGING_IMPLEMENTATIONS Log implementations
*
* Stasis provides a number of default log formats, and supports third-party
* implementations.
*
*/
/**
* @defgroup LOGGING_INTERFACES High-level log interfaces
*/
/**
* @defgroup LOGGING_DISCIPLINES Logging Disciplines
*
* Stasis' log API provides a number of methods that directly
* manipulate the log.
* Transactional data-structures must choose one of Stasis' recovery modes,
* and interact with the log accordingly.
*
* @section SNF STEAL/NO-FORCE recovery
* Stasis includes a function, Tupdate(), that
@ -489,10 +504,10 @@ terms specified in this license.
* during commit. Recovery works by "repeating history"; all actions
* are redone up to some point in time after the last successful
* transaction committed, but before the crash. Conceptually, any
* partially commited transactions are then rolled back using
* partially committed transactions are then rolled back using
* Tabort(), as they would be during normal operation. For more
* information about STEAL/NO-FORCE recovery strategies, see the ARIES
* paper (XXX cite aries properly)
* paper (XXX cite Aries properly)
*
*
* @section SF STEAL/FORCE and bulk-logged recovery