snapshot v4/p15; revert, reunite
This commit is contained in:
parent
5b9fc60730
commit
ae9ad6e9be
2 changed files with 32 additions and 34 deletions
|
@ -49,7 +49,6 @@ struct sample_node {
|
||||||
int key;
|
int key;
|
||||||
char *value;
|
char *value;
|
||||||
SKIPLIST_ENTRY(sample) entries;
|
SKIPLIST_ENTRY(sample) entries;
|
||||||
SKIPLIST_SNAPSHOT_ENTRY(sample) snaps;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -145,7 +144,7 @@ SKIPLIST_DECL_ACCESS(
|
||||||
*
|
*
|
||||||
* TODO
|
* TODO
|
||||||
*/
|
*/
|
||||||
SKIPLIST_DECL_SNAPSHOTS(sample, api_, entries, snaps)
|
SKIPLIST_DECL_SNAPSHOTS(sample, api_, entries)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Optional: Archive to/from bytes
|
* Optional: Archive to/from bytes
|
||||||
|
@ -249,7 +248,7 @@ main()
|
||||||
int rc;
|
int rc;
|
||||||
#ifdef SNAPSHOTS
|
#ifdef SNAPSHOTS
|
||||||
size_t snap_i = 0;
|
size_t snap_i = 0;
|
||||||
uint64_t snaps[2048];
|
uint64_t snap_ids[2048];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DOT
|
#ifdef DOT
|
||||||
|
@ -280,7 +279,7 @@ main()
|
||||||
|
|
||||||
#ifdef SNAPSHOTS
|
#ifdef SNAPSHOTS
|
||||||
/* Test creating a snapshot of an empty Skiplist */
|
/* Test creating a snapshot of an empty Skiplist */
|
||||||
snaps[snap_i++] = api_skip_snapshot_sample(list);
|
snap_ids[snap_i++] = api_skip_snapshot_sample(list);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Insert 7 key/value pairs into the list. */
|
/* Insert 7 key/value pairs into the list. */
|
||||||
|
@ -288,6 +287,7 @@ main()
|
||||||
char *numeral;
|
char *numeral;
|
||||||
#ifdef DOT
|
#ifdef DOT
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
|
memset(msg, 0, 1024);
|
||||||
#endif
|
#endif
|
||||||
int amt = TEST_ARRAY_SIZE, asz = (amt * 2) + 1;
|
int amt = TEST_ARRAY_SIZE, asz = (amt * 2) + 1;
|
||||||
int array[(TEST_ARRAY_SIZE * 2) + 1];
|
int array[(TEST_ARRAY_SIZE * 2) + 1];
|
||||||
|
@ -301,7 +301,7 @@ main()
|
||||||
CHECK;
|
CHECK;
|
||||||
#ifdef SNAPSHOTS
|
#ifdef SNAPSHOTS
|
||||||
if (i > TEST_ARRAY_SIZE + 1) {
|
if (i > TEST_ARRAY_SIZE + 1) {
|
||||||
snaps[snap_i++] = api_skip_snapshot_sample(list);
|
snap_ids[snap_i++] = api_skip_snapshot_sample(list);
|
||||||
CHECK;
|
CHECK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -355,8 +355,8 @@ main()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SNAPSHOTS
|
#ifdef SNAPSHOTS
|
||||||
api_skip_restore_snapshot_sample(list, snaps[snap_i - 1]);
|
// TODO api_skip_restore_snapshot_sample(list, snap_ids[snap_i - 1]);
|
||||||
api_skip_release_snapshots_sample(list);
|
// TODO api_skip_release_snapshots_sample(list);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(strcmp(api_skip_pos_sample(list, SKIP_GTE, -(TEST_ARRAY_SIZE)-1)->value, int_to_roman_numeral(-(TEST_ARRAY_SIZE))) == 0);
|
assert(strcmp(api_skip_pos_sample(list, SKIP_GTE, -(TEST_ARRAY_SIZE)-1)->value, int_to_roman_numeral(-(TEST_ARRAY_SIZE))) == 0);
|
||||||
|
|
52
include/sl.h
52
include/sl.h
|
@ -180,7 +180,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip List declarations.
|
* Skiplist declarations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SKIPLIST_MAX_HEIGHT
|
#ifndef SKIPLIST_MAX_HEIGHT
|
||||||
|
@ -188,7 +188,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A Skip List contains elements, a portion of which is used to manage those
|
* A Skiplist contains elements, a portion of which is used to manage those
|
||||||
* elements while the rest is defined by the use case for this declaration. The
|
* elements while the rest is defined by the use case for this declaration. The
|
||||||
* housekeeping portion is the SKIPLIST_ENTRY below. It maintains the array of
|
* housekeeping portion is the SKIPLIST_ENTRY below. It maintains the array of
|
||||||
* forward pointers to nodes and has a height (a zero-based count of levels, so
|
* forward pointers to nodes and has a height (a zero-based count of levels, so
|
||||||
|
@ -199,11 +199,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
struct __skiplist_##decl##_entry { \
|
struct __skiplist_##decl##_entry { \
|
||||||
struct decl##_node *sle_prev, **sle_next; \
|
struct decl##_node *sle_prev, **sle_next; \
|
||||||
size_t sle_height; \
|
size_t sle_height; \
|
||||||
}
|
size_t sle_era; \
|
||||||
|
|
||||||
#define SKIPLIST_SNAPSHOT_ENTRY(decl) \
|
|
||||||
struct __skiplist_##decl##_snaps { \
|
|
||||||
size_t snp_era; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIPLIST_FOREACH_H2T(decl, prefix, list, elm, iter) \
|
#define SKIPLIST_FOREACH_H2T(decl, prefix, list, elm, iter) \
|
||||||
|
@ -226,17 +222,17 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
#define __SKIP_IS_LAST_ENTRY_B2T() if (lvl + 1 == elm->field.sle_height)
|
#define __SKIP_IS_LAST_ENTRY_B2T() if (lvl + 1 == elm->field.sle_height)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip List declarations and access methods.
|
* Skiplist declarations and access methods.
|
||||||
*/
|
*/
|
||||||
#define SKIPLIST_DECL(decl, prefix, field, compare_entries_blk, free_entry_blk, update_entry_blk, archive_entry_blk, sizeof_entry_blk) \
|
#define SKIPLIST_DECL(decl, prefix, field, compare_entries_blk, free_entry_blk, update_entry_blk, archive_entry_blk, sizeof_entry_blk) \
|
||||||
\
|
\
|
||||||
/* Used when positioning a cursor within a Skip List. */ \
|
/* Used when positioning a cursor within a Skiplist. */ \
|
||||||
typedef enum { SKIP_EQ = 0, SKIP_LTE = -1, SKIP_LT = -2, SKIP_GTE = 1, SKIP_GT = 2 } skip_pos_##decl_t; \
|
typedef enum { SKIP_EQ = 0, SKIP_LTE = -1, SKIP_LT = -2, SKIP_GTE = 1, SKIP_GT = 2 } skip_pos_##decl_t; \
|
||||||
\
|
\
|
||||||
/* Skip List node type */ \
|
/* Skiplist node type */ \
|
||||||
typedef struct decl##_node decl##_node_t; \
|
typedef struct decl##_node decl##_node_t; \
|
||||||
\
|
\
|
||||||
/* Skip List structure and type */ \
|
/* Skiplist structure and type */ \
|
||||||
typedef struct decl { \
|
typedef struct decl { \
|
||||||
size_t slh_length, slh_height, slh_max_height; \
|
size_t slh_length, slh_height, slh_max_height; \
|
||||||
struct { \
|
struct { \
|
||||||
|
@ -349,7 +345,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
* -- __skip_toss_ \
|
* -- __skip_toss_ \
|
||||||
* \
|
* \
|
||||||
* A "coin toss" function that is critical to the proper operation of the \
|
* A "coin toss" function that is critical to the proper operation of the \
|
||||||
* Skip List. For example, when `max = 6` this function returns 0 with \
|
* Skiplist. For example, when `max = 6` this function returns 0 with \
|
||||||
* probability 0.5, 1 with 0.25, 2 with 0.125, etc. until 6 with 0.5^7. \
|
* probability 0.5, 1 with 0.25, 2 with 0.125, etc. until 6 with 0.5^7. \
|
||||||
*/ \
|
*/ \
|
||||||
static int __skip_toss_##decl(size_t max) \
|
static int __skip_toss_##decl(size_t max) \
|
||||||
|
@ -388,7 +384,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
/** \
|
/** \
|
||||||
* -- skip_init_ \
|
* -- skip_init_ \
|
||||||
* \
|
* \
|
||||||
* Initializes a Skip List to the deafault values, this must be called \
|
* Initializes a Skiplist to the deafault values, this must be called \
|
||||||
* before using the list. \
|
* before using the list. \
|
||||||
*/ \
|
*/ \
|
||||||
int prefix##skip_init_##decl(decl##_t *slist, int max) \
|
int prefix##skip_init_##decl(decl##_t *slist, int max) \
|
||||||
|
@ -967,9 +963,11 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
slist->slh_fns.update_entry(src); \
|
slist->slh_fns.update_entry(src); \
|
||||||
|
\
|
||||||
/* Record the era for this node to enable snapshots. */ \
|
/* Record the era for this node to enable snapshots. */ \
|
||||||
if (slist->slh_fns.snapshot_record_era) \
|
if (slist->slh_fns.snapshot_record_era) \
|
||||||
slist->slh_fns.snapshot_record_era(slist, src); \
|
slist->slh_fns.snapshot_record_era(slist, src); \
|
||||||
|
\
|
||||||
return rc; \
|
return rc; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
@ -1068,7 +1066,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
free(slist->slh_tail); \
|
free(slist->slh_tail); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIPLIST_DECL_SNAPSHOTS(decl, prefix, field, snf) \
|
#define SKIPLIST_DECL_SNAPSHOTS(decl, prefix, field) \
|
||||||
\
|
\
|
||||||
/** \
|
/** \
|
||||||
* -- __skip_snapshot_record_era_ \
|
* -- __skip_snapshot_record_era_ \
|
||||||
|
@ -1079,7 +1077,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
if (slist == NULL) \
|
if (slist == NULL) \
|
||||||
return; \
|
return; \
|
||||||
\
|
\
|
||||||
node->snf.snp_era = slist->slh_fns.snapshot_current_era(slist); \
|
node->field.sle_era = slist->slh_fns.snapshot_current_era(slist); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/** \
|
/** \
|
||||||
|
@ -1117,7 +1115,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
if (slist == NULL || src == NULL) \
|
if (slist == NULL || src == NULL) \
|
||||||
return 0; \
|
return 0; \
|
||||||
\
|
\
|
||||||
if (src->snf.snp_era > slist->slh_snap.era) \
|
if (src->field.sle_era > slist->slh_snap.era) \
|
||||||
return 0; \
|
return 0; \
|
||||||
\
|
\
|
||||||
/* (a) alloc, ... */ \
|
/* (a) alloc, ... */ \
|
||||||
|
@ -1176,7 +1174,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
/** \
|
/** \
|
||||||
* -- skip_snapshot_ \
|
* -- skip_snapshot_ \
|
||||||
* \
|
* \
|
||||||
* A snapshot is a read-only view of a Skip List at a point in time. Once \
|
* A snapshot is a read-only view of a Skiplist at a point in time. Once \
|
||||||
* taken, a snapshot must be restored or released. Any number of snapshots \
|
* taken, a snapshot must be restored or released. Any number of snapshots \
|
||||||
* can be created. \
|
* can be created. \
|
||||||
*/ \
|
*/ \
|
||||||
|
@ -1196,19 +1194,19 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
* \
|
* \
|
||||||
* ALGORITHM: \
|
* ALGORITHM: \
|
||||||
* iterate over the preserved nodes (slist->slh_pres) \
|
* iterate over the preserved nodes (slist->slh_pres) \
|
||||||
* a) remove/free nodes with node->gen > gen from slist \
|
* a) remove/free nodes with node->era > era from slist \
|
||||||
* b) remove/free nodes > gen from slh_pres \
|
* b) remove/free nodes > era from slh_pres \
|
||||||
* c) restore nodes == gen by... \
|
* c) restore nodes == era by... \
|
||||||
* i) remove node from slh_pres list \
|
* i) remove node from slh_pres list \
|
||||||
* ii) _insert(node) or \
|
* ii) _insert(node) or \
|
||||||
* _insert_dup() if node->field.sle_next[1] != 0 (clear that) \
|
* _insert_dup() if node->field.sle_next[1] != 0 (clear that) \
|
||||||
* d) set slist's gen to `gen` \
|
* d) set slist's era to `era` \
|
||||||
* \
|
* \
|
||||||
* NOTES: \
|
* NOTES: \
|
||||||
* - Starting with slh_pres, the `node->field.sle_next[0]` form a \
|
* - Starting with slh_pres, the `node->field.sle_next[0]` form a \
|
||||||
* singly-linked list. \
|
* singly-linked list. \
|
||||||
*/ \
|
*/ \
|
||||||
decl##_t *prefix##skip_restore_snapshot_##decl(decl##_t *slist, size_t gen) \
|
decl##_t *prefix##skip_restore_snapshot_##decl(decl##_t *slist, size_t era) \
|
||||||
{ \
|
{ \
|
||||||
size_t i, cur_era; \
|
size_t i, cur_era; \
|
||||||
decl##_node_t *node, *prev; \
|
decl##_node_t *node, *prev; \
|
||||||
|
@ -1216,7 +1214,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
if (slist == NULL) \
|
if (slist == NULL) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
\
|
\
|
||||||
if (gen >= slist->slh_snap.era || slist->slh_snap.pres == NULL) \
|
if (era >= slist->slh_snap.era || slist->slh_snap.pres == NULL) \
|
||||||
return slist; \
|
return slist; \
|
||||||
\
|
\
|
||||||
cur_era = slist->slh_fns.snapshot_current_era(slist); \
|
cur_era = slist->slh_fns.snapshot_current_era(slist); \
|
||||||
|
@ -1225,7 +1223,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
SKIPLIST_FOREACH_H2T(decl, prefix, slist, node, i) \
|
SKIPLIST_FOREACH_H2T(decl, prefix, slist, node, i) \
|
||||||
{ \
|
{ \
|
||||||
((void)i); \
|
((void)i); \
|
||||||
if (node->snf.snp_era > gen) \
|
if (node->field.sle_era > era) \
|
||||||
prefix##skip_remove_node_##decl(slist, node); \
|
prefix##skip_remove_node_##decl(slist, node); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
@ -1233,7 +1231,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
node = slist->slh_snap.pres; \
|
node = slist->slh_snap.pres; \
|
||||||
while (node) { \
|
while (node) { \
|
||||||
/* (b) */ \
|
/* (b) */ \
|
||||||
if (node->snf.snp_era > gen) { \
|
if (node->field.sle_era > era) { \
|
||||||
/* remove node from slh_snap.pres list */ \
|
/* remove node from slh_snap.pres list */ \
|
||||||
if (slist->slh_snap.pres == node) \
|
if (slist->slh_snap.pres == node) \
|
||||||
slist->slh_snap.pres = node->field.sle_next[0]; \
|
slist->slh_snap.pres = node->field.sle_next[0]; \
|
||||||
|
@ -1249,7 +1247,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
\
|
\
|
||||||
/* c */ \
|
/* c */ \
|
||||||
prev = NULL; \
|
prev = NULL; \
|
||||||
if (node->snf.snp_era == gen) { \
|
if (node->field.sle_era == era) { \
|
||||||
/* remove node from slh_snap.pres list */ \
|
/* remove node from slh_snap.pres list */ \
|
||||||
if (slist->slh_snap.pres == node) \
|
if (slist->slh_snap.pres == node) \
|
||||||
slist->slh_snap.pres = node->field.sle_next[0]; \
|
slist->slh_snap.pres = node->field.sle_next[0]; \
|
||||||
|
@ -1933,7 +1931,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
\
|
\
|
||||||
/* -- skip_dot_ \
|
/* -- skip_dot_ \
|
||||||
* Create a DOT file of the internal representation of the \
|
* Create a DOT file of the internal representation of the \
|
||||||
* Skip List on the provided file descriptor (default: STDOUT). \
|
* Skiplist on the provided file descriptor (default: STDOUT). \
|
||||||
* \
|
* \
|
||||||
* To view the output: \
|
* To view the output: \
|
||||||
* $ dot -Tps filename.dot -o outfile.ps \
|
* $ dot -Tps filename.dot -o outfile.ps \
|
||||||
|
|
Loading…
Reference in a new issue