transactional.h now @includes the example programs. Cleaned up the example programs for inclusion in documentation.

This commit is contained in:
Sears Russell 2007-05-25 22:01:44 +00:00
parent 3feebd8fde
commit f15d7dbdf1
3 changed files with 78 additions and 120 deletions

View file

@ -1,23 +1,27 @@
#include <lladd/transactional.h>
int main (int argc, char ** argv) {
int main (int argc, char ** argv) {
Tinit();
int i = 42;
// First transaction
int xid = Tbegin();
recordid rid = Talloc(xid, sizeof(int));
Tset(xid, rid, &i); // the application is responsible for memory management.
// Here, stack-allocated integers are used, although memory
// from malloc() works as well.
Tcommit(xid);
recordid rid = Talloc(xid, sizeof(int));
// The application is responsible for memory management.
// Tset() will copy i; it can be freed immediately after the call is made.
int i = 42;
Tset(xid, rid, &i);
Tcommit(xid);
int j;
xid = Tbegin();
Tread(xid, rid, &j); // j is now 42.
Tdealloc(xid, rid);
Tabort(xid);
Tdealloc(xid, rid);
Tabort(xid);
Tdeinit();
}

View file

@ -2,45 +2,50 @@
#include <stdio.h>
#include <assert.h>
int main (int argc, char ** argv) {
int main (int argc, char ** argv) {
Tinit();
recordid rootEntry;
int xid = Tbegin();
if(TrecordType(xid, ROOT_RECORD) == UNINITIALIZED_RECORD) {
// ThashAlloc() will work here as well.
rootEntry = Talloc(xid, sizeof(int));
rootEntry = Talloc(xid, sizeof(int));
assert(ROOT_RECORD.page == rootEntry.page);
assert(ROOT_RECORD.slot == rootEntry.slot);
// newRoot.size will be sizeof(something) from above.
// rootEntry.size will be sizeof(int) from above.
int zero = 0;
Tset(xid, rootEntry, &zero);
Tcommit(xid);
printf("New store; root = 0\n");
} else {
// The store already is initialized.
// The store already is initialized. If this were a real program,
// it would use some magic to make sure that it is compatible with
// the program that created the store...
rootEntry = ROOT_RECORD;
rootEntry.size = sizeof(int); // Same as sizeof(something) above.
// Perform any application initialization based upon its contents...
rootEntry.size = sizeof(int); // Same as sizeof(int) above.
int root;
Tread(xid, rootEntry, &root);
Tread(xid, rootEntry, &root);
printf("Old store: %d -> ", root);
root++;
Tset(xid, rootEntry, &root);
printf("%d\n", root);
Tcommit(xid);
Tset(xid, rootEntry, &root);
}
Tcommit(xid);
Tdeinit();
}

View file

@ -115,38 +115,13 @@ terms specified in this license.
simple program that uses Stasis. Currently, most generally useful programs
written on top of Stasis belong in lladd/src/apps, while utilities/ contains
programs useful for debugging the library.
@section usage Using Stasis in your software
Synopsis:
@code
#include <lladd/transactional.h>
...
Tinit();
int i = 42;
int xid = Tbegin();
recordid rid = Talloc(xid, sizeof(int));
Tset(xid, rid, &i); // the application is responsible for memory management.
// Here, stack-allocated integers are used, although memory
// from malloc() works as well.
Tcommit(xid);
int j;
xid = Tbegin();
Tread(xid, rid, &j); // j is now 42.
Tdealloc(xid, rid);
Tabort(xid);
Tdeinit();
@endcode
Synopsis:
@include examples/ex1.c
Hopefully, Tbegin(), Talloc(), Tset(), Tcommit(), Tabort() and Tdealloc() are
self explanatory. If not, they are covered in detail elsewhere. Tinit() and
Tdeinit() initialize the library, and clean up when the program is finished.
@ -171,60 +146,38 @@ terms specified in this license.
Therefore, the following code will safely initialize or reopen a data
store:
@code
Tinit();
recordid rootEntry;
int xid = Tbegin();
if(TrecordType(xid, ROOT_RECORD) == UNINITIALIZED_RECORD) {
// ThashAlloc() will work here as well.
rootEntry = Talloc(xid, sizeof(something));
assert(ROOT_RECORD.page == rootEntry.page);
assert(ROOT_RECORD.slot == rootEntry.slot);
// newRoot.size will be sizeof(something) from above.
// Continue initialization procedures...
} else {
// The store already is initialized.
rootEntry = ROOT_RECORD;
rootEntry.size = sizeof(something); // Same as sizeof(something) above.
// Perform any application initialization based upon its contents...
}
@endcode
@include examples/ex2.c
@see test.c for a complete, executable example of reopeneing an existing store.
@todo Explain how to determine the correct value of rootEntry.size in the case
of a hashtable.
@see OPERATIONS for more operations that may be useful for your software.
@subsection consistency Using Stasis in multithreaded applications.
Unless otherwise noted, Stasis' operations are re-entrant. This
means that an application may call them concurrently without
corrupting Stasis' internal data structures. However, this does
not mean that Stasis provides full transactional consistency or
serializable schedules. Therefore, an application must manipulate
data in a way that ensures logical consistency. In other words, if
two threads attempt to write to the same data value simultaneously,
the result is undefined. In database terms, you could say that
Stasis only provides latches.
corrupting Stasis' internal data structures. However, if two
threads attempt to write the same data value simultaneously, the
result is undefined.
In database terms, Stasis uses latches to protect its own data
structures' consistency (including those on disk), but does not
obtain short term read or write locks to protect data as it is
being written. This is less consistency than SQL's Level 0 (Dirty
Reads) provides. Some of Stasis' data structures do obtain short
read and write locks automatically. Refer to individual data
structues for more information.
Stasis' allocation functions, such as Talloc(), do not reuse space
that was freed by an ongoing transaction. This means that you may
safely overwrite freshly allocated space without writing undo
entries, and allows concurrent transactions to safely allocate
space.
This is different than saying all read and write locks are 'short';
short write locks would guarantee that once two concurrent writes
complete, one of the values have been stored. Stasis does not
guarantee this although some of its data structures do have this
property.
From the point of view of conventional multithreaded software
development, Stasis closely matches the semantics provided by
typical operating system thread implementations. However, it
@ -235,29 +188,25 @@ terms specified in this license.
Finally, Stasis asumes that each thread has its own transaction;
concurrent calls within the same transaction are not supported.
This restriction may be removed in the future.
@section selfTest The self-test suite
Stasis includes an extensive self test suite which may be invoked
by running 'make check' in Stasis' root directory. Some of the
tests are for older, unmaintained code that was built on top of
Stasis. Running 'make check' in test/lladd runs all of the Stasis
tests.
@section archictecture Stasis' architecture
@section archictecture Stasis' architecture
@todo Provide a brief summary of Stasis' architecture.
@section extending Implementing you own operations
@todo Provide a tutorial that explains howto extend Stasis with new operations.
@todo Provide a tutorial that explains how to extend Stasis with new operations.
@see increment.h for an example of a very simple logical operation.
@see linearHashNTA.h for a more sophisticated example that makes use of Nested Top Actions.
@section roadmap Roadmap
@todo Fill out the roadmap section.
*/
/**