Initial revision
This commit is contained in:
commit
d1f76f0b4a
323 changed files with 46021 additions and 0 deletions
4
AUTHORS
Normal file
4
AUTHORS
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Jason Bayer bayer@xcf.berkeley.edu
|
||||||
|
Jim Blomo jim@xcf.berkeley.edu
|
||||||
|
Jimmy Kittiyachavalit jkit@xcf.berkeley.edu
|
||||||
|
Russell Sears sears@cs.berkeley.edu
|
45
COPYING
Normal file
45
COPYING
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
LLADD LICENSE TERMS - (TCL/TK License)
|
||||||
|
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
0
ChangeLog
Normal file
0
ChangeLog
Normal file
9
Makefile.am
Normal file
9
Makefile.am
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
EXTRA_DIST = reconf
|
||||||
|
SUBDIRS = src test
|
||||||
|
AM_CFLAGS = -g -Wall -pedantic
|
||||||
|
|
||||||
|
docs:
|
||||||
|
doxygen doc/Doxyfile-api
|
||||||
|
doxygen doc/Doxyfile-developers
|
||||||
|
|
||||||
|
.PHONY: docs
|
3
NEWS
Normal file
3
NEWS
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Jun 9, 2004:
|
||||||
|
|
||||||
|
Set version number to 0.5, retired old directory structure, and added autoconf / unit testing framework.
|
160
NOTES
Normal file
160
NOTES
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
create new record
|
||||||
|
get a page with enough free space
|
||||||
|
check existing pages for free space
|
||||||
|
create a new emtpy page
|
||||||
|
alloc a record on that page
|
||||||
|
increment number of records on this page
|
||||||
|
update free space pointer
|
||||||
|
write to record
|
||||||
|
load the page into memory
|
||||||
|
find the page on disk
|
||||||
|
put the page in memory
|
||||||
|
lock the page
|
||||||
|
get the memory address of the record
|
||||||
|
look up the record offset in the slot directory
|
||||||
|
write to that record
|
||||||
|
update log
|
||||||
|
update lsn on page
|
||||||
|
|
||||||
|
read record
|
||||||
|
load the page into memory
|
||||||
|
get the address of the record
|
||||||
|
read that record
|
||||||
|
|
||||||
|
|
||||||
|
begin xaction
|
||||||
|
|
||||||
|
commit xaction
|
||||||
|
flush
|
||||||
|
unlock
|
||||||
|
|
||||||
|
abort xaction
|
||||||
|
delete page from memory
|
||||||
|
unlock
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
recordid memory.ralloc(int xid, size_t size) {
|
||||||
|
for each page in the page table // page table are pages in RAM
|
||||||
|
if locked, continue
|
||||||
|
// context switch here SUCKS
|
||||||
|
lock page
|
||||||
|
break if freeSpace(page) >= size
|
||||||
|
free page
|
||||||
|
if no free page
|
||||||
|
create a new page and lock and load
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (recordid) page.recordAllocate(page, size)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void page.writeRecord(recordid rid, void *data) {
|
||||||
|
|
||||||
|
assert page locked and loaded
|
||||||
|
if xid and recordid is in hash table, do nothing
|
||||||
|
else make shadow record
|
||||||
|
memcpy()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *page.readRecord(recordid rid, void *buff) {
|
||||||
|
make sure page is loaded
|
||||||
|
memcpy()
|
||||||
|
return pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
commitXaction(int xid) {
|
||||||
|
for each page that this xid has locked
|
||||||
|
unlock page
|
||||||
|
if pin count of page == 0
|
||||||
|
flush
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
abortXaction(int xid) {
|
||||||
|
for each locked page
|
||||||
|
restore shadow records
|
||||||
|
unlock page
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
transactional.c
|
||||||
|
Tread
|
||||||
|
Tbegin
|
||||||
|
Tcommit
|
||||||
|
Tabort
|
||||||
|
operations.h
|
||||||
|
Tset
|
||||||
|
Tdec
|
||||||
|
Tinc
|
||||||
|
|
||||||
|
struct page {
|
||||||
|
void *memAddr
|
||||||
|
long lsn
|
||||||
|
semaphore lock
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferManager.c
|
||||||
|
struct page loadPage(pageid)
|
||||||
|
flushPage(struct page) // maybe take pageid
|
||||||
|
dropPage(struct page) // maybe take pageid
|
||||||
|
bufTransCommit(xid) // call flush and dropPage on page buffer
|
||||||
|
bufTransAbort(xid) // call flush and dropPage on page buffer
|
||||||
|
pin
|
||||||
|
unpin
|
||||||
|
|
||||||
|
page.c
|
||||||
|
rid ralloc(int size) // depends on bufferManager
|
||||||
|
writeRecord(rid, data)
|
||||||
|
readRecord(rid, buff)
|
||||||
|
|
||||||
|
recovery.c
|
||||||
|
logger.c
|
||||||
|
constants.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
==============================
|
||||||
|
|
||||||
|
buffer needs
|
||||||
|
xid => ( pages )
|
||||||
|
(dirty pages)
|
||||||
|
page, first write LSN
|
||||||
|
|
||||||
|
page needs
|
||||||
|
xid => ( recordids )
|
||||||
|
xid,recordid => data
|
||||||
|
|
||||||
|
|
||||||
|
================
|
||||||
|
Testing
|
||||||
|
|
||||||
|
in main.c we can write something to the effect of
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
write
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
printf("looping");
|
||||||
|
|
||||||
|
commit
|
||||||
|
|
||||||
|
this way, when we see that "looping is printing, we can purposefully crash the program with control-c
|
||||||
|
|
||||||
|
not sure that this is anydifferent than having main.c {begin, write, exit}
|
31
README
Normal file
31
README
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
LLADD is an experimental Lightweight Library for Atomicity and Durability of Data.
|
||||||
|
|
||||||
|
Please see the COPYING file for licensing information.
|
||||||
|
|
||||||
|
To build, do:
|
||||||
|
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make check
|
||||||
|
make install
|
||||||
|
|
||||||
|
To build the API and internals documentation, run:
|
||||||
|
|
||||||
|
make docs
|
||||||
|
|
||||||
|
after configure.
|
||||||
|
|
||||||
|
'make check' requires the GNU check library, 'make doc' requires Doxygen.
|
||||||
|
|
||||||
|
We haven't tested make install. ;)
|
||||||
|
|
||||||
|
This package contains a copy of Peter Graf's Program Base Library, PBL, which is
|
||||||
|
distributed under the terms of the LGPL.
|
||||||
|
|
||||||
|
The original version can be found at:
|
||||||
|
|
||||||
|
http://mission.base.com/peter/source/
|
||||||
|
|
||||||
|
LLADD's version of the package adds the jbhash.* files, and compiles PBL using
|
||||||
|
LLADD's make files. Currently, LLADD's hash table implementations are based upon
|
||||||
|
code from PBL, and pbl is used in a number of places throughout LLADD.
|
2
autoscan.log
Normal file
2
autoscan.log
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
autoscan: warning: missing AC_PROG_RANLIB wanted by:
|
||||||
|
ltmain.sh:6370
|
11
bootstrap
Executable file
11
bootstrap
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
## aclocal warns way too much!
|
||||||
|
aclocal-1.8 2>&1 | grep -v '.usr.share.aclocal.'
|
||||||
|
# -I config
|
||||||
|
autoheader
|
||||||
|
automake-1.8 --add-missing --copy
|
||||||
|
#automake
|
||||||
|
autoconf
|
10
clean.sh
Executable file
10
clean.sh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#! /bin/sh
|
||||||
|
make distclean
|
||||||
|
rm -rf Makefile.in aclocal.m4 autom4te.cache config.h.in configure depcomp hello.c install-sh missing doc/api doc/developers
|
||||||
|
find . | grep \~$ | xargs rm -f
|
||||||
|
find . | perl -ne 'print if (/\/core(\.\d+)?$/)' | xargs rm -f
|
||||||
|
find . | perl -ne 'print if (/\/Makefile.in$/)' | xargs rm -f
|
||||||
|
find . | perl -ne 'print if (/\/storefile.txt$/)' | xargs rm -f
|
||||||
|
find . | perl -ne 'print if (/\/logfile.txt$/)' | xargs rm -f
|
||||||
|
find . | perl -ne 'print if (/\/blob._file.txt$/)' | xargs rm -f
|
||||||
|
|
188
config.h
Normal file
188
config.h
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/* config.h. Generated by configure. */
|
||||||
|
/* config.h.in. Generated from configure.in by autoheader. */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||||
|
#define HAVE_ARPA_INET_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `bzero' function. */
|
||||||
|
#define HAVE_BZERO 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#define HAVE_DIRENT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
#define HAVE_DLFCN_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
|
#define HAVE_FCNTL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `fdatasync' function. */
|
||||||
|
#define HAVE_FDATASYNC 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getcwd' function. */
|
||||||
|
#define HAVE_GETCWD 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpagesize' function. */
|
||||||
|
#define HAVE_GETPAGESIZE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
|
#define HAVE_GETTIMEOFDAY 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `inet_ntoa' function. */
|
||||||
|
#define HAVE_INET_NTOA 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#define HAVE_INTTYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||||
|
#define HAVE_LIBPTHREAD 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <limits.h> header file. */
|
||||||
|
#define HAVE_LIMITS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||||
|
to 0 otherwise. */
|
||||||
|
#define HAVE_MALLOC 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <malloc.h> header file. */
|
||||||
|
#define HAVE_MALLOC_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memmove' function. */
|
||||||
|
#define HAVE_MEMMOVE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#define HAVE_MEMORY_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memset' function. */
|
||||||
|
#define HAVE_MEMSET 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `mkdir' function. */
|
||||||
|
#define HAVE_MKDIR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have a working `mmap' system call. */
|
||||||
|
#define HAVE_MMAP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `munmap' function. */
|
||||||
|
#define HAVE_MUNMAP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||||
|
/* #undef HAVE_NDIR_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <netdb.h> header file. */
|
||||||
|
#define HAVE_NETDB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||||
|
#define HAVE_NETINET_IN_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `socket' function. */
|
||||||
|
#define HAVE_SOCKET 1
|
||||||
|
|
||||||
|
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
||||||
|
zero-length file name argument. */
|
||||||
|
/* #undef HAVE_STAT_EMPTY_STRING_BUG */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stddef.h> header file. */
|
||||||
|
#define HAVE_STDDEF_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#define HAVE_STDINT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#define HAVE_STDLIB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strchr' function. */
|
||||||
|
#define HAVE_STRCHR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strdup' function. */
|
||||||
|
#define HAVE_STRDUP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strerror' function. */
|
||||||
|
#define HAVE_STRERROR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#define HAVE_STRINGS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#define HAVE_STRING_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strrchr' function. */
|
||||||
|
#define HAVE_STRRCHR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strstr' function. */
|
||||||
|
#define HAVE_STRSTR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtoul' function. */
|
||||||
|
#define HAVE_STRTOUL 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <syslog.h> header file. */
|
||||||
|
#define HAVE_SYSLOG_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
/* #undef HAVE_SYS_DIR_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
/* #undef HAVE_SYS_NDIR_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||||
|
#define HAVE_SYS_SOCKET_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#define HAVE_SYS_TIME_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||||
|
#define HAVE_SYS_WAIT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#define HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
||||||
|
slash. */
|
||||||
|
#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#define PACKAGE "hello"
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#define PACKAGE_BUGREPORT "sears@cs.berkeley.edu"
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#define PACKAGE_NAME "PACKAGE"
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#define PACKAGE_STRING "PACKAGE VERSION"
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#define PACKAGE_TARNAME "package"
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#define PACKAGE_VERSION "VERSION"
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||||
|
#define TIME_WITH_SYS_TIME 1
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#define VERSION "0.1"
|
||||||
|
|
||||||
|
/* Define to empty if `const' does not conform to ANSI C. */
|
||||||
|
/* #undef const */
|
||||||
|
|
||||||
|
/* Define to rpl_malloc if the replacement function should be used. */
|
||||||
|
/* #undef malloc */
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
|
/* #undef pid_t */
|
||||||
|
|
||||||
|
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||||
|
/* #undef size_t */
|
72
configure.in
Normal file
72
configure.in
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
# -*- Autoconf -*-
|
||||||
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
|
PACKAGE=LLADD
|
||||||
|
VERSION=0.1
|
||||||
|
AC_PREREQ(2.59)
|
||||||
|
AC_INIT(PACKAGE, VERSION, sears@cs.berkeley.edu)
|
||||||
|
AM_INIT_AUTOMAKE(hello,0.1)
|
||||||
|
AC_CONFIG_SRCDIR([config.h.in])
|
||||||
|
AC_CONFIG_HEADER([config.h])
|
||||||
|
|
||||||
|
# Checks for programs.
|
||||||
|
AC_PROG_CXX
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_CPP
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_LN_S
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
## Need AC_PROG_LIBTOOL
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
#AC_PROG_RANLIB
|
||||||
|
|
||||||
|
# Checks for libraries.
|
||||||
|
|
||||||
|
AM_PATH_CHECK(,[have_check="yes"],
|
||||||
|
AC_MSG_WARN([Check not found; cannot run unit tests!])
|
||||||
|
[have_check="no"])
|
||||||
|
AM_CONDITIONAL(HAVE_CHECK, test x"$have_check", "xyes")
|
||||||
|
|
||||||
|
# Checks for header files.
|
||||||
|
AC_HEADER_DIRENT
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_HEADER_SYS_WAIT
|
||||||
|
AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h malloc.h memory.h netdb.h netinet/in.h stddef.h stdlib.h string.h strings.h sys/socket.h sys/time.h syslog.h unistd.h])
|
||||||
|
|
||||||
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
AC_C_CONST
|
||||||
|
AC_TYPE_PID_T
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_HEADER_TIME
|
||||||
|
|
||||||
|
# Checks for library functions.
|
||||||
|
AC_FUNC_MALLOC
|
||||||
|
AC_FUNC_MEMCMP
|
||||||
|
AC_FUNC_MMAP
|
||||||
|
AC_FUNC_STAT
|
||||||
|
AC_CHECK_FUNCS([bzero fdatasync getcwd gettimeofday inet_ntoa memmove memset mkdir munmap socket strchr strdup strerror strrchr strstr strtoul])
|
||||||
|
|
||||||
|
AC_CHECK_LIB(pthread, pthread_create)
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile
|
||||||
|
libdfa/Makefile
|
||||||
|
lladd/Makefile
|
||||||
|
pbl/Makefile
|
||||||
|
src/2pc/Makefile
|
||||||
|
src/Makefile
|
||||||
|
src/apps/Makefile
|
||||||
|
src/apps/cht/Makefile
|
||||||
|
src/apps/cyrus/Makefile
|
||||||
|
src/libdfa/Makefile
|
||||||
|
src/lladd/Makefile
|
||||||
|
src/pbl/Makefile
|
||||||
|
src/timing/Makefile
|
||||||
|
test/2pc/Makefile
|
||||||
|
test/Makefile
|
||||||
|
test/cht/Makefile
|
||||||
|
test/dfa/Makefile
|
||||||
|
test/lladd/Makefile
|
||||||
|
test/lladd-old/Makefile
|
||||||
|
test/messages/Makefile
|
||||||
|
test/monotree/Makefile])
|
||||||
|
AC_OUTPUT
|
197
libdfa/Makefile
Normal file
197
libdfa/Makefile
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
srcdir = .
|
||||||
|
top_srcdir = ..
|
||||||
|
|
||||||
|
prefix = /usr/local
|
||||||
|
exec_prefix = ${prefix}
|
||||||
|
|
||||||
|
bindir = ${exec_prefix}/bin
|
||||||
|
sbindir = ${exec_prefix}/sbin
|
||||||
|
libexecdir = ${exec_prefix}/libexec
|
||||||
|
datadir = ${prefix}/share
|
||||||
|
sysconfdir = ${prefix}/etc
|
||||||
|
sharedstatedir = ${prefix}/com
|
||||||
|
localstatedir = ${prefix}/var
|
||||||
|
libdir = ${exec_prefix}/lib
|
||||||
|
infodir = ${prefix}/info
|
||||||
|
mandir = ${prefix}/man
|
||||||
|
includedir = ${prefix}/include
|
||||||
|
oldincludedir = /usr/include
|
||||||
|
|
||||||
|
DESTDIR =
|
||||||
|
|
||||||
|
pkgdatadir = $(datadir)/hello
|
||||||
|
pkglibdir = $(libdir)/hello
|
||||||
|
pkgincludedir = $(includedir)/hello
|
||||||
|
|
||||||
|
top_builddir = ..
|
||||||
|
|
||||||
|
ACLOCAL = aclocal-1.4
|
||||||
|
AUTOCONF = autoconf
|
||||||
|
AUTOMAKE = automake-1.4
|
||||||
|
AUTOHEADER = autoheader
|
||||||
|
|
||||||
|
INSTALL = /usr/bin/install -c
|
||||||
|
INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS)
|
||||||
|
INSTALL_DATA = ${INSTALL} -m 644
|
||||||
|
INSTALL_SCRIPT = ${INSTALL}
|
||||||
|
transform = s,x,x,
|
||||||
|
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
host_alias =
|
||||||
|
host_triplet = i686-pc-linux-gnu
|
||||||
|
AR = ar
|
||||||
|
AS = @AS@
|
||||||
|
CC = gcc
|
||||||
|
CHECK_CFLAGS =
|
||||||
|
CHECK_LIBS = -lcheck
|
||||||
|
CPP = gcc -E
|
||||||
|
CXX = g++
|
||||||
|
CXXCPP = g++ -E
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
ECHO = echo
|
||||||
|
EGREP = grep -E
|
||||||
|
EXEEXT =
|
||||||
|
F77 = g77
|
||||||
|
GCJ = @GCJ@
|
||||||
|
GCJFLAGS = @GCJFLAGS@
|
||||||
|
HAVE_LIB = @HAVE_LIB@
|
||||||
|
LIB = @LIB@
|
||||||
|
LIBTOOL = $(SHELL) $(top_builddir)/libtool
|
||||||
|
LN_S = ln -s
|
||||||
|
LTLIB = @LTLIB@
|
||||||
|
MAKEINFO = makeinfo
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = o
|
||||||
|
PACKAGE = hello
|
||||||
|
RANLIB = ranlib
|
||||||
|
RC = @RC@
|
||||||
|
STRIP = strip
|
||||||
|
VERSION = 0.1
|
||||||
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
|
CONFIG_HEADER = ../[config.h]
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
DIST_COMMON = Makefile.am Makefile.in
|
||||||
|
|
||||||
|
|
||||||
|
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
|
||||||
|
TAR = tar
|
||||||
|
GZIP_ENV = --best
|
||||||
|
all: all-redirect
|
||||||
|
.SUFFIXES:
|
||||||
|
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||||
|
cd $(top_srcdir) && $(AUTOMAKE) --gnu libdfa/Makefile
|
||||||
|
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||||
|
cd $(top_builddir) \
|
||||||
|
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||||
|
|
||||||
|
tags: TAGS
|
||||||
|
TAGS:
|
||||||
|
|
||||||
|
|
||||||
|
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||||
|
|
||||||
|
subdir = libdfa
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
here=`cd $(top_builddir) && pwd`; \
|
||||||
|
top_distdir=`cd $(top_distdir) && pwd`; \
|
||||||
|
distdir=`cd $(distdir) && pwd`; \
|
||||||
|
cd $(top_srcdir) \
|
||||||
|
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu libdfa/Makefile
|
||||||
|
@for file in $(DISTFILES); do \
|
||||||
|
d=$(srcdir); \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||||
|
else \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
info-am:
|
||||||
|
info: info-am
|
||||||
|
dvi-am:
|
||||||
|
dvi: dvi-am
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
installcheck-am:
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-exec-am:
|
||||||
|
install-exec: install-exec-am
|
||||||
|
|
||||||
|
install-data-am:
|
||||||
|
install-data: install-data-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
install: install-am
|
||||||
|
uninstall-am:
|
||||||
|
uninstall: uninstall-am
|
||||||
|
all-am: Makefile
|
||||||
|
all-redirect: all-am
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||||
|
installdirs:
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||||
|
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
mostlyclean-am: mostlyclean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
clean-am: clean-generic mostlyclean-am
|
||||||
|
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
distclean-am: distclean-generic clean-am
|
||||||
|
-rm -f libtool
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
|
||||||
|
maintainer-clean-am: maintainer-clean-generic distclean-am
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
|
||||||
|
.PHONY: tags distdir info-am info dvi-am dvi check check-am \
|
||||||
|
installcheck-am installcheck install-exec-am install-exec \
|
||||||
|
install-data-am install-data install-am install uninstall-am uninstall \
|
||||||
|
all-redirect all-am all installdirs mostlyclean-generic \
|
||||||
|
distclean-generic clean-generic maintainer-clean-generic clean \
|
||||||
|
mostlyclean distclean maintainer-clean
|
||||||
|
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
0
libdfa/Makefile.am
Normal file
0
libdfa/Makefile.am
Normal file
160
libdfa/libdfa.h
Normal file
160
libdfa/libdfa.h
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _LIBDFA_H
|
||||||
|
#define _LIBDFA_H
|
||||||
|
#include <libdfa/statemachine.h>
|
||||||
|
/*#include "monotree.h"*/
|
||||||
|
#include <libdfa/smash.h>
|
||||||
|
#include <libdfa/messages.h>
|
||||||
|
#include <libdfa/rw.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maximum number of concurrent state machines.
|
||||||
|
*/
|
||||||
|
#define DFA_MACHINE_COUNT 100
|
||||||
|
|
||||||
|
|
||||||
|
/** TODO: Add transitions and states to dfaSet? */
|
||||||
|
typedef struct dfaSet {
|
||||||
|
/* MonoTree monoTree; */
|
||||||
|
smash_t * smash;
|
||||||
|
NetworkSetup networkSetup;
|
||||||
|
State * states;
|
||||||
|
state_name state_count;
|
||||||
|
Transition * transitions;
|
||||||
|
state_name transition_count;
|
||||||
|
/**
|
||||||
|
The locking scheme for libdfa currently works as follows:
|
||||||
|
|
||||||
|
There is a single, per process, read/write lock. When a writer
|
||||||
|
(either the main loop, or a worker thread that is deallocating
|
||||||
|
its machine) holds the lock, then none of the worker threads may
|
||||||
|
make progress. When any reader holds the lock, all worker
|
||||||
|
threads obtain an implicit write lock on their statemachine.
|
||||||
|
|
||||||
|
One final note: Since a writer can change the in-memory location
|
||||||
|
of state machines, the readers must re-initialize their state
|
||||||
|
machine pointer each time they obtain a read lock. This is one
|
||||||
|
of the primary barriers to finer grained locking. (See below for
|
||||||
|
a straightforward, improved, locking scheme.)
|
||||||
|
|
||||||
|
Performance issues:
|
||||||
|
|
||||||
|
Finer grained locking may be necessary, as all of the
|
||||||
|
user-defined callbacks are executed in the main loop while it
|
||||||
|
holds the global write lock. A better scheme might work as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
Workers obtain a pointer to their state machine, and that
|
||||||
|
pointer is immutable over the lifetime of the worker.
|
||||||
|
|
||||||
|
The global write lock is only held when the main loop is
|
||||||
|
allocating or deallocating machines; the global read lock is
|
||||||
|
only used when the main loop needs to lookup a machine to
|
||||||
|
service a request, or when creating new worker threads.
|
||||||
|
|
||||||
|
Each machine has a pthreads_mutex associated with it, and
|
||||||
|
worker threads obtain that mutex whenever they access the
|
||||||
|
machine. (Therefore user supplied callbacks only would block
|
||||||
|
progress on the machine that they are running against.)
|
||||||
|
|
||||||
|
*/
|
||||||
|
rwl * lock;
|
||||||
|
void * app_setup;
|
||||||
|
} DfaSet;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Clears DfaSet, and establishes a new empty set of state machines in
|
||||||
|
its place. Also zeroes out the callback tables. Does not
|
||||||
|
initialize transient state such as network sockets.
|
||||||
|
*/
|
||||||
|
void dfa_initialize_new(DfaSet * dfaSet, unsigned short port, int count);
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
int dfa_start (DfaSet *dfaSet,
|
||||||
|
Transition transitions[], int transition_count,
|
||||||
|
State states[], state_name state_count);
|
||||||
|
/**
|
||||||
|
|
||||||
|
Establishes all of the transient state of DfaSet, such as network
|
||||||
|
connections and callback tables. Should be called after dfa_initialize_new
|
||||||
|
(or, upon recovery, without dfa_initialize_new)
|
||||||
|
|
||||||
|
Returns -1 on error.
|
||||||
|
|
||||||
|
*/
|
||||||
|
int dfa_reinitialize (DfaSet *dfaSet, char * localhost,
|
||||||
|
Transition transitions[], int transition_count,
|
||||||
|
State states[], state_name state_count);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Spawns a new thread to handle incoming requests. (There should
|
||||||
|
only be one such thread per dfaSet.)
|
||||||
|
|
||||||
|
@see main_loop, which does the same thing, but blocks indefinitely.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pthread_t spawn_main_thread(DfaSet * dfaSet);
|
||||||
|
/**
|
||||||
|
Use the current thread as the worker thread for state machine machine_id. Returns when the machine is freed.
|
||||||
|
|
||||||
|
Should be called after spawn_main_thread (Could be called after main_loop if the application manually manages threads.)
|
||||||
|
|
||||||
|
@return TODO (Not sure what this returns / should return.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * request(DfaSet * dfaSet, state_name start_state, char * recipient_addr, state_machine_id recipient_machine_id, Message * message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Runs an infinite loop to handle network requests.
|
||||||
|
*/
|
||||||
|
void* main_loop(DfaSet *dfaSet);
|
||||||
|
|
||||||
|
DfaSet * dfa_malloc(int count, short port,
|
||||||
|
char *** broadcast_lists,
|
||||||
|
int broadcast_lists_count,
|
||||||
|
int * broadcast_list_host_count);
|
||||||
|
#endif
|
130
libdfa/messages.h
Normal file
130
libdfa/messages.h
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
#ifndef _MESSAGES_H
|
||||||
|
#define _MESSAGES_H
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
typedef unsigned long state_machine_id;
|
||||||
|
|
||||||
|
/* Maximum size of a message payload, in bytes. Should be a multiple of the system word length.*/
|
||||||
|
#define MAX_PAYLOAD 800
|
||||||
|
/**
|
||||||
|
Note that message_type UCHAR_MAX is reserved for the NULL (stop) state, and 0 is reserved for the
|
||||||
|
start state.
|
||||||
|
*/
|
||||||
|
#define MAX_MESSAGE_TYPE (UCHAR_MAX)
|
||||||
|
#define MAX_MESSAGE_COUNT (UCHAR_MAX+1)
|
||||||
|
typedef unsigned char message_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
"xxx.xxx.xxx.xxx:yyyyy" is 21 characters, and is as long as the
|
||||||
|
longest valid ip:port string we will ever encounter or produce
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_ADDRESS_LENGTH 21
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Message structs are the in-memory representation of network
|
||||||
|
messages. Everything except for the payload is translated to and
|
||||||
|
from network byte order automatically, and the whole struct is sent
|
||||||
|
(as is) over the network.
|
||||||
|
|
||||||
|
This is why the payload field can be of arbitrary length and is
|
||||||
|
defined as a char. Allocating a message with a payload larger than
|
||||||
|
one byte can be done with sizeof() arithmetic, and by setting size
|
||||||
|
accordingly.
|
||||||
|
*/
|
||||||
|
typedef struct message {
|
||||||
|
state_machine_id to_machine_id;
|
||||||
|
state_machine_id from_machine_id;
|
||||||
|
state_machine_id initiator_machine_id;
|
||||||
|
char initiator[MAX_ADDRESS_LENGTH];
|
||||||
|
message_name type;
|
||||||
|
/** Payload is a byte array of arbitrary length. **/
|
||||||
|
char payload[MAX_PAYLOAD];
|
||||||
|
} Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This struct contains the state for the messages (networking) layer.
|
||||||
|
Currently, everything here can be derived at startup, so this won't
|
||||||
|
need to be in transactional storage, with some luck. */
|
||||||
|
typedef struct networkSetup {
|
||||||
|
unsigned short localport;
|
||||||
|
char * localhost;
|
||||||
|
int socket;
|
||||||
|
/**
|
||||||
|
Same format as argv for main(). If a message is addressed to
|
||||||
|
"broadcast", then the message will be sent to each
|
||||||
|
"address:port" pair in this string. If you want to use proper
|
||||||
|
IP broadcast, then this list can simply contain one entry that
|
||||||
|
contains a subnet broadcast address like "1.2.3.0:1234".
|
||||||
|
|
||||||
|
It would be best to set this value to NULL and
|
||||||
|
broadcast_list_count to zero if you don't plan to use broadcast.
|
||||||
|
*/
|
||||||
|
char *** broadcast_lists;
|
||||||
|
int broadcast_lists_count;
|
||||||
|
int *broadcast_list_host_count;
|
||||||
|
} NetworkSetup;
|
||||||
|
|
||||||
|
int init_network(NetworkSetup *ns, unsigned short portnum);
|
||||||
|
|
||||||
|
int init_network_broadcast(NetworkSetup * ns, unsigned short portnum, char * localhost, char *** broadcast_lists,
|
||||||
|
int broadcast_lists_count, int * broadcast_list_host_count);
|
||||||
|
/*int init_network_broadcast(NetworkSetup * ns, unsigned short portnum, char *** broadcast_lists,
|
||||||
|
int broadcast_lists_count, int * broadcast_list_host_count); */
|
||||||
|
|
||||||
|
int send_message(const NetworkSetup *ns, Message *m, const char *to);
|
||||||
|
int receive_message(NetworkSetup *ns, Message *m, char *from);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Remember to call free() on the pointer that this returns!
|
||||||
|
*/
|
||||||
|
char * parse_addr(const char *message);
|
||||||
|
short parse_port(const char *message);
|
||||||
|
int get_index(char ** table, int table_length, const char *message);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
91
libdfa/rw.h
Normal file
91
libdfa/rw.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File : rw.c
|
||||||
|
*
|
||||||
|
* Title : Demo Readers/Writer.
|
||||||
|
*
|
||||||
|
* Short : A solution to the multi-reader's, one writer problem.
|
||||||
|
*
|
||||||
|
* Long :
|
||||||
|
*
|
||||||
|
* Author : Andrae Muys
|
||||||
|
*
|
||||||
|
* Date : 18 September 1997
|
||||||
|
*
|
||||||
|
* Revised : 4-7-04 Shamelessly stolen and adapted by Rusty Sears.
|
||||||
|
* Found the code at this url:
|
||||||
|
* http://www.cs.nmsu.edu/~jcook/Tools/pthreads/rw.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
pthread_mutex_t *mut;
|
||||||
|
int writers;
|
||||||
|
int readers;
|
||||||
|
int waiting;
|
||||||
|
pthread_cond_t *writeOK, *readOK;
|
||||||
|
} rwl;
|
||||||
|
|
||||||
|
rwl *initlock (void);
|
||||||
|
void readlock (rwl *lock, int d);
|
||||||
|
void writelock (rwl *lock, int d);
|
||||||
|
void readunlock (rwl *lock);
|
||||||
|
void writeunlock (rwl *lock);
|
||||||
|
void deletelock (rwl *lock);
|
||||||
|
/*
|
||||||
|
typedef struct {
|
||||||
|
rwl *lock;
|
||||||
|
int id;
|
||||||
|
long delay;
|
||||||
|
} rwargs;
|
||||||
|
|
||||||
|
rwargs *newRWargs (rwl *l, int i, long d);
|
||||||
|
void *reader (void *args);
|
||||||
|
void *writer (void *args);
|
||||||
|
*/
|
84
libdfa/smash.h
Normal file
84
libdfa/smash.h
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <pbl/pbl.h>
|
||||||
|
#include <pbl/jbhash.h>
|
||||||
|
#include <libdfa/statemachine.h>
|
||||||
|
/** State machine hash library. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int size;
|
||||||
|
int contents;
|
||||||
|
state_machine_id next_sm_id;
|
||||||
|
recordid store;
|
||||||
|
/* Need to save the recordid of the hash if we want to recover... (???)*/
|
||||||
|
recordid hash_store;
|
||||||
|
jbHashTable_t * hash;
|
||||||
|
pthread_mutex_t * lock;
|
||||||
|
int xid;
|
||||||
|
pblHashTable_t * memHash;
|
||||||
|
} smash_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
rb = malloc (sizeof(MonoTree));
|
||||||
|
rb->buffer = malloc(sizeof(StateMachine) * rb_size);
|
||||||
|
|
||||||
|
init_MonoTree(rb, rb_size);
|
||||||
|
|
||||||
|
*/
|
||||||
|
smash_t * init_Smash(int size);
|
||||||
|
/**
|
||||||
|
Returns a pointer to a new machine, or null if the
|
||||||
|
buffer is full.
|
||||||
|
|
||||||
|
*/
|
||||||
|
StateMachine* allocSmash (smash_t * smash);
|
||||||
|
StateMachine* insertSmash(smash_t * smash, state_machine_id id);
|
||||||
|
int freeSmash (smash_t * smash, state_machine_id id);
|
||||||
|
|
||||||
|
void * getSmash (smash_t * smash, state_machine_id id);
|
||||||
|
int setSmash (smash_t * smash, state_machine_id id);
|
||||||
|
|
||||||
|
int forceSmash (smash_t * smash);
|
||||||
|
/*StateMachine * enumerateSmash(smash_t * rb, int * count);*/
|
163
libdfa/statemachine.h
Normal file
163
libdfa/statemachine.h
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _STATEMACHINE_H
|
||||||
|
#define _STATEMACHINE_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <lladd/transactional.h>
|
||||||
|
#include <libdfa/messages.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#define MAX_STATE_NAME UCHAR_MAX-1
|
||||||
|
/*
|
||||||
|
|
||||||
|
If a transition's post state is OVERRIDDEN_STATE, then the new
|
||||||
|
state is read from the return value of the callback_fcn. If
|
||||||
|
callback_fcn returns OVERRIDDEN_STATE, then no transition is
|
||||||
|
performed.
|
||||||
|
|
||||||
|
Otherwise, then callback_fcn returns a standard boolean value.
|
||||||
|
(0-> no transition, !=0 -> take transition.)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_STATE_COUNT UCHAR_MAX+1
|
||||||
|
|
||||||
|
#define MAX_APP_STATE_SIZE (sizeof(int) * 32)
|
||||||
|
|
||||||
|
#define NULL_MACHINE (ULONG_MAX-1)
|
||||||
|
#define NULL_STATE MAX_STATE_NAME
|
||||||
|
#define NULL_STATE_TOMBSTONE (MAX_STATE_NAME-1)
|
||||||
|
#define OVERRIDDEN_STATE (MAX_STATE_NAME-2)
|
||||||
|
#define START_STATE 0
|
||||||
|
|
||||||
|
typedef unsigned char dfa_bool;
|
||||||
|
|
||||||
|
typedef unsigned char state_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This struct contains all of the information associated with an
|
||||||
|
instance of a state machine. When combined with a set of states and
|
||||||
|
transitions, this provides enough information to actually execute a machine.
|
||||||
|
|
||||||
|
The page record contains application specific state, which must be
|
||||||
|
stored in transactional, or otherwise reliable storage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct stateMachine {
|
||||||
|
/** The unique identifier of this state machine. */
|
||||||
|
state_machine_id machine_id;
|
||||||
|
/** The wall-clock time of the last transition made by this
|
||||||
|
machine. (Used to abort hung machines.)*/
|
||||||
|
time_t last_transition;
|
||||||
|
/** A pointer to this state machine's page in memory. */
|
||||||
|
Page * page;
|
||||||
|
/** The recordid of page (for recovery) */
|
||||||
|
recordid page_id;
|
||||||
|
/** The current state of this machine, or NULL_STATE for machines
|
||||||
|
that should be garbage collected. */
|
||||||
|
state_name current_state;
|
||||||
|
pthread_t worker_thread;
|
||||||
|
int pending;
|
||||||
|
pthread_mutex_t * mutex;
|
||||||
|
pthread_cond_t * sleepCond;
|
||||||
|
Message message;
|
||||||
|
char message_recipient[MAX_ADDRESS_LENGTH];
|
||||||
|
int app_state[MAX_APP_STATE_SIZE];
|
||||||
|
} StateMachine;
|
||||||
|
|
||||||
|
|
||||||
|
typedef state_name(callback_fcn)(void * dfaSet, StateMachine * stateMachine, Message * m, char * from);
|
||||||
|
|
||||||
|
|
||||||
|
/* All function pointers follow this prototype:
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
and may be null if no function needs to be executed.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct state {
|
||||||
|
/** The name of this state. Usually just the index of this state in the states array.
|
||||||
|
*/
|
||||||
|
state_name name;
|
||||||
|
/** A function pointer that will be periodically executed when the machine is in this state. Most network
|
||||||
|
transmits belong here, while 'guards' belong in fcn_ptr in the Transistion struct.
|
||||||
|
*/
|
||||||
|
callback_fcn* retry_fcn;
|
||||||
|
/** NULL unless the machine can be aborted while in this state. If
|
||||||
|
not-null, then it should point to a function that performs a
|
||||||
|
No-op or does any house-keeping that should be performed before
|
||||||
|
the machine gets nuked.
|
||||||
|
|
||||||
|
Should normally be a callback_fcn, as defined in libdfa.h */
|
||||||
|
|
||||||
|
callback_fcn* abort_fcn;
|
||||||
|
} State;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct transition {
|
||||||
|
/** A unique (per machine type) identifier for this transition. */
|
||||||
|
state_name remote_state;
|
||||||
|
/** The start state for this transition */
|
||||||
|
state_name pre_state;
|
||||||
|
/** The stop state. */
|
||||||
|
state_name post_state;
|
||||||
|
/** Executed when the machine traverses this arc. Returns false if
|
||||||
|
the arc should not be traversed. For sane semantics, exactly
|
||||||
|
one transition from a given start state should return true given
|
||||||
|
the same network message. */
|
||||||
|
callback_fcn * fcn_ptr;
|
||||||
|
/** If true, this transitions causes a force to disk after fcn_ptr
|
||||||
|
returns, but before the retry_fcn for the state is automatically
|
||||||
|
executed the first time. */
|
||||||
|
dfa_bool force;
|
||||||
|
|
||||||
|
} Transition;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
306
lladd.prj
Normal file
306
lladd.prj
Normal file
|
@ -0,0 +1,306 @@
|
||||||
|
# Anjuta Version 1.2.2
|
||||||
|
Compatibility Level: 1
|
||||||
|
|
||||||
|
<PROJECT_DESCRIPTION_START>
|
||||||
|
LLADD - Lightweight Library for Atomicity and Data Durability<PROJECT_DESCRIPTION_END>
|
||||||
|
<CONFIG_PROGS_START>
|
||||||
|
<CONFIG_PROGS_END>
|
||||||
|
<CONFIG_LIBS_START>
|
||||||
|
<CONFIG_LIBS_END>
|
||||||
|
<CONFIG_HEADERS_START>
|
||||||
|
<CONFIG_HEADERS_END>
|
||||||
|
<CONFIG_CHARACTERISTICS_START>
|
||||||
|
<CONFIG_CHARACTERISTICS_END>
|
||||||
|
<CONFIG_LIB_FUNCS_START>
|
||||||
|
<CONFIG_LIB_FUNCS_END>
|
||||||
|
<CONFIG_ADDITIONAL_START>
|
||||||
|
<CONFIG_ADDITIONAL_END>
|
||||||
|
<CONFIG_FILES_START>
|
||||||
|
<CONFIG_FILES_END>
|
||||||
|
<MAKEFILE_AM_START>
|
||||||
|
<MAKEFILE_AM_END>
|
||||||
|
|
||||||
|
props.file.type=project
|
||||||
|
|
||||||
|
anjuta.version=1.2.2
|
||||||
|
anjuta.compatibility.level=1
|
||||||
|
|
||||||
|
project.name=lladd
|
||||||
|
project.type=GENERIC
|
||||||
|
project.target.type=EXECUTABLE
|
||||||
|
project.version=0.99
|
||||||
|
project.author=Russell Sears
|
||||||
|
project.source.target=unknown
|
||||||
|
project.has.gettext=0
|
||||||
|
project.gui.command=
|
||||||
|
project.programming.language=C
|
||||||
|
project.excluded.modules=intl
|
||||||
|
|
||||||
|
project.config.extra.modules.before=
|
||||||
|
project.config.extra.modules.after=
|
||||||
|
project.config.blocked=1
|
||||||
|
project.config.disable.overwriting=1 1 1 1 1 1 1 1 1
|
||||||
|
|
||||||
|
project.menu.entry=lladd Version 0.99
|
||||||
|
project.menu.group=Application
|
||||||
|
project.menu.comment=lladd Version 0.99
|
||||||
|
project.menu.icon=
|
||||||
|
project.menu.need.terminal=0
|
||||||
|
|
||||||
|
project.configure.options=
|
||||||
|
anjuta.program.arguments=
|
||||||
|
preferences.build.option.jobs=0
|
||||||
|
preferences.build.option.silent=0
|
||||||
|
preferences.build.option.autosave=0
|
||||||
|
preferences.make=make
|
||||||
|
preferences.build.option.keep.going=1
|
||||||
|
preferences.build.option.warn.undef=0
|
||||||
|
preferences.autoformat.custom.style= -i8 -sc -bli0 -bl0 -cbi0 -ss
|
||||||
|
preferences.indent.opening=0
|
||||||
|
preferences.autoformat.disable=1
|
||||||
|
preferences.indent.automatic=1
|
||||||
|
preferences.use.tabs=1
|
||||||
|
preferences.indent.size=4
|
||||||
|
preferences.tabsize=4
|
||||||
|
preferences.indent.closing=0
|
||||||
|
|
||||||
|
module.include.name=.
|
||||||
|
module.include.type=
|
||||||
|
module.include.files=\
|
||||||
|
2pc/src/2pc/2pc.h\
|
||||||
|
2pc/src/cht/cht.h\
|
||||||
|
2pc/src/libdfa/rw.h\
|
||||||
|
2pc/src/libdfa/messages.h\
|
||||||
|
2pc/src/libdfa/smash.h\
|
||||||
|
2pc/src/libdfa/monotree.h\
|
||||||
|
2pc/src/libdfa/callbacks.h\
|
||||||
|
2pc/src/libdfa/libdfa.h\
|
||||||
|
2pc/src/libdfa/statemachine.h\
|
||||||
|
2pc/config.h\
|
||||||
|
pbl/pbl.h\
|
||||||
|
pbl/jbhash.h\
|
||||||
|
test/test.h\
|
||||||
|
test/rand_str.h\
|
||||||
|
constants.h\
|
||||||
|
bufferManager.h\
|
||||||
|
operations/set.h\
|
||||||
|
operations/lladdhash.h\
|
||||||
|
operations/increment.h\
|
||||||
|
operations/decrement.h\
|
||||||
|
operations/prepare.h\
|
||||||
|
recovery.h\
|
||||||
|
logger/logstreamer.h\
|
||||||
|
logger/logparser.h\
|
||||||
|
page.h\
|
||||||
|
logger.h\
|
||||||
|
transactional.h\
|
||||||
|
linkedlist.h\
|
||||||
|
operations.h
|
||||||
|
|
||||||
|
module.source.name=.
|
||||||
|
module.source.type=
|
||||||
|
module.source.files=\
|
||||||
|
2pc/src/2pc/2pc.c\
|
||||||
|
2pc/src/cht/cht.c\
|
||||||
|
2pc/src/tests/2pc/always_commit.c\
|
||||||
|
2pc/src/tests/cht/simple.c\
|
||||||
|
2pc/src/tests/cht/cht_server.c\
|
||||||
|
2pc/src/tests/dfa/ping_pong_dfa.c\
|
||||||
|
2pc/src/tests/dfa/star.c\
|
||||||
|
2pc/src/tests/dfa/fork_bomb.c\
|
||||||
|
2pc/src/tests/messages/ping_pong.c\
|
||||||
|
2pc/src/tests/monotree/binary_search.c\
|
||||||
|
2pc/src/tests/monotree/bit_arithmetic.c\
|
||||||
|
2pc/src/tests/monotree/soundness.c\
|
||||||
|
2pc/src/libdfa/rw.c\
|
||||||
|
2pc/src/libdfa/messages.c\
|
||||||
|
2pc/src/libdfa/smash.c\
|
||||||
|
2pc/src/libdfa/monotree.c\
|
||||||
|
2pc/src/libdfa/callbacks.c\
|
||||||
|
2pc/src/libdfa/libdfa.c\
|
||||||
|
pbl/pbl.c\
|
||||||
|
pbl/pblkfblockprint.c\
|
||||||
|
pbl/pbliftst.c\
|
||||||
|
pbl/pblhttst.c\
|
||||||
|
pbl/pblhash.c\
|
||||||
|
pbl/jbhash.c\
|
||||||
|
pbl/pblisam.c\
|
||||||
|
pbl/pblkf.c\
|
||||||
|
pbl/pbltest.c\
|
||||||
|
pbl/pblkftst.c\
|
||||||
|
test/db41/dbInsertSequential.c\
|
||||||
|
test/db41/jbhashmany.c\
|
||||||
|
test/db41/dbInsert.c\
|
||||||
|
test/db41/dbAbort.c\
|
||||||
|
test/db41/jbhashsimple.c\
|
||||||
|
test/db41/dbUpdate.c\
|
||||||
|
test/db41/dbGet.c\
|
||||||
|
test/strings.c\
|
||||||
|
test/jbhashdisk.c\
|
||||||
|
test/TGet.c\
|
||||||
|
test/TUpdate.c\
|
||||||
|
test/jbhashmany.c\
|
||||||
|
test/twentyfour2.c\
|
||||||
|
test/abort-speed.c\
|
||||||
|
test/nontrans.c\
|
||||||
|
test/lhpackingfactor.c\
|
||||||
|
test/jbhtsimple.c\
|
||||||
|
test/inc_dec.c\
|
||||||
|
test/test0.c\
|
||||||
|
test/test1.c\
|
||||||
|
test/test2.c\
|
||||||
|
test/test3.c\
|
||||||
|
test/recover.c\
|
||||||
|
test/commit-speed.c\
|
||||||
|
test/logvals.c\
|
||||||
|
test/jbht-speed.c\
|
||||||
|
test/interleaved.c\
|
||||||
|
test/TAbort.c\
|
||||||
|
test/loop.c\
|
||||||
|
test/abort.c\
|
||||||
|
test/test.c\
|
||||||
|
test/TInsertSequential.c\
|
||||||
|
test/lhmany.c\
|
||||||
|
test/twentyfour.c\
|
||||||
|
test/prepare_1.c\
|
||||||
|
test/prepare_2.c\
|
||||||
|
test/prepare_3.c\
|
||||||
|
test/rand_str.c\
|
||||||
|
test/TInsert.c\
|
||||||
|
cyrus/cyrusdb_lladd.c\
|
||||||
|
bufferManager.c\
|
||||||
|
operations/set.c\
|
||||||
|
operations/lladdhash.c\
|
||||||
|
operations/increment.c\
|
||||||
|
operations/decrement.c\
|
||||||
|
operations/prepare.c\
|
||||||
|
recovery.c\
|
||||||
|
logger/logstreamer.c\
|
||||||
|
logger/logparser.c\
|
||||||
|
page.c\
|
||||||
|
timing/getTimeOfDay.c\
|
||||||
|
logger.c\
|
||||||
|
transactional.c\
|
||||||
|
linkedlist.c
|
||||||
|
|
||||||
|
module.pixmap.name=.
|
||||||
|
module.pixmap.type=
|
||||||
|
module.pixmap.files=\
|
||||||
|
pbl/doc/icon1.gif\
|
||||||
|
pbl/doc/icon2.gif
|
||||||
|
|
||||||
|
module.data.name=.
|
||||||
|
module.data.type=
|
||||||
|
module.data.files=
|
||||||
|
|
||||||
|
module.help.name=.
|
||||||
|
module.help.type=
|
||||||
|
module.help.files=
|
||||||
|
|
||||||
|
module.doc.name=.
|
||||||
|
module.doc.type=
|
||||||
|
module.doc.files=\
|
||||||
|
2pc/COPYING\
|
||||||
|
pbl/doc/pblKfInit.html\
|
||||||
|
pbl/doc/pblHtNext.html\
|
||||||
|
pbl/doc/pblKfPrev.html\
|
||||||
|
pbl/doc/pbl_LongToBuf.html\
|
||||||
|
pbl/doc/pbl_LongToVarBuf.html\
|
||||||
|
pbl/doc/pbl_VarBufToLong.html\
|
||||||
|
pbl/doc/pblKfFlush.html\
|
||||||
|
pbl/doc/pblKfOpen.html\
|
||||||
|
pbl/doc/pblIsamGet.html\
|
||||||
|
pbl/doc/pblKfDelete.html\
|
||||||
|
pbl/doc/pblIsamFile_t.html\
|
||||||
|
pbl/doc/pbl_LongSize.html\
|
||||||
|
pbl/doc/pbl_errno.html\
|
||||||
|
pbl/doc/pblIsamReadKey.html\
|
||||||
|
pbl/doc/pblIsamCommit.html\
|
||||||
|
pbl/doc/AIntroduction.html\
|
||||||
|
pbl/doc/pblKEYFILE_TestFrame.html\
|
||||||
|
pbl/doc/pbl_mem2dup.html\
|
||||||
|
pbl/doc/pbl_ShortToBuf.html\
|
||||||
|
pbl/doc/pblIsamFlush.html\
|
||||||
|
pbl/doc/pblHtInsert.html\
|
||||||
|
pbl/doc/DDefinitionsforKeyFileParameters.html\
|
||||||
|
pbl/doc/pbl_memlcpy.html\
|
||||||
|
pbl/doc/pblKfCreate.html\
|
||||||
|
pbl/doc/pblIsamFind.html\
|
||||||
|
pbl/doc/pblHtLookup.html\
|
||||||
|
pbl/doc/pblKfUpdate.html\
|
||||||
|
pbl/doc/index.html\
|
||||||
|
pbl/doc/pblHtDelete.html\
|
||||||
|
pbl/doc/pblHtRemove.html\
|
||||||
|
pbl/doc/pbl_malloc0.html\
|
||||||
|
pbl/doc/pblIsamInsert.html\
|
||||||
|
pbl/doc/pblKfGetRel.html\
|
||||||
|
pbl/doc/pblKfLast.html\
|
||||||
|
pbl/doc/pblKfStartTransaction.html\
|
||||||
|
pbl/doc/pblIsamStartTransaction.html\
|
||||||
|
pbl/doc/pblKfRead.html\
|
||||||
|
pbl/doc/pblIsamDelete.html\
|
||||||
|
pbl/doc/BFiles.html\
|
||||||
|
pbl/doc/pblHashTable_t.html\
|
||||||
|
pbl/doc/pblKeyFile_t.html\
|
||||||
|
pbl/doc/pbl_memdup.html\
|
||||||
|
pbl/doc/pblIsamOpen.html\
|
||||||
|
pbl/doc/pblIsamUpdateData.html\
|
||||||
|
pbl/doc/pbl_memcmplen.html\
|
||||||
|
pbl/doc/pblHtFirst.html\
|
||||||
|
pbl/doc/pblHtCreate.html\
|
||||||
|
pbl/doc/pblKfClose.html\
|
||||||
|
pbl/doc/pblKfSetCompareFunction.html\
|
||||||
|
pbl/doc/CErrorcodes.html\
|
||||||
|
pbl/doc/pblKfNext.html\
|
||||||
|
pbl/doc/PBLKEYLENGTH.html\
|
||||||
|
pbl/doc/pbl_malloc.html\
|
||||||
|
pbl/doc/pblIsamReadDatalen.html\
|
||||||
|
pbl/doc/pblISAMFILE_TestFrame.html\
|
||||||
|
pbl/doc/pblHtCurrent.html\
|
||||||
|
pbl/doc/General.html\
|
||||||
|
pbl/doc/pblKfRestorePosition.html\
|
||||||
|
pbl/doc/pblKfFirst.html\
|
||||||
|
pbl/doc/pblIsamUpdateKey.html\
|
||||||
|
pbl/doc/pbl_BufToShort.html\
|
||||||
|
pbl/doc/PBL_LIST_PUSH.html\
|
||||||
|
pbl/doc/pbl_memcmp.html\
|
||||||
|
pbl/doc/pblKfThis.html\
|
||||||
|
pbl/doc/pblKfCommit.html\
|
||||||
|
pbl/doc/pblKfGetAbs.html\
|
||||||
|
pbl/doc/pblIsamClose.html\
|
||||||
|
pbl/doc/pbl_errstr.html\
|
||||||
|
pbl/doc/PBLDATALENGTH.html\
|
||||||
|
pbl/doc/PBL_LIST_APPEND.html\
|
||||||
|
pbl/doc/PBL_LIST_.html\
|
||||||
|
pbl/doc/pblKfFind.html\
|
||||||
|
pbl/doc/PBL_FREE.html\
|
||||||
|
pbl/doc/EDefinitionsforISAMParameters.html\
|
||||||
|
pbl/doc/pbl_VarBufSize.html\
|
||||||
|
pbl/doc/pblKfSavePosition.html\
|
||||||
|
pbl/doc/PBL_LIST_UNLINK.html\
|
||||||
|
pbl/doc/pblIsamReadData.html\
|
||||||
|
pbl/doc/pbl_BufToLong.html\
|
||||||
|
pbl/doc/pblKfInsert.html\
|
||||||
|
pbl/doc/pblIsamSetCompareFunction.html\
|
||||||
|
timing/README
|
||||||
|
|
||||||
|
module.po.files=
|
||||||
|
|
||||||
|
compiler.options.supports=
|
||||||
|
compiler.options.include.paths=\
|
||||||
|
.\
|
||||||
|
..
|
||||||
|
compiler.options.library.paths=
|
||||||
|
compiler.options.libraries=
|
||||||
|
compiler.options.libraries.selected=
|
||||||
|
compiler.options.defines=\
|
||||||
|
HAVE_CONFIG_H
|
||||||
|
compiler.options.defines.selected=
|
||||||
|
compiler.options.warning.buttons=0 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0
|
||||||
|
compiler.options.optimize.buttons=0 0 1 0
|
||||||
|
compiler.options.other.buttons=1 0
|
||||||
|
compiler.options.other.c.flags=
|
||||||
|
compiler.options.other.l.flags=
|
||||||
|
compiler.options.other.l.libs=
|
||||||
|
|
||||||
|
project.src.paths=
|
78
lladd.pws
Normal file
78
lladd.pws
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
|
||||||
|
[executer]
|
||||||
|
RunInTerminal=true
|
||||||
|
|
||||||
|
[Project State]
|
||||||
|
clean before build=false
|
||||||
|
|
||||||
|
[File View]
|
||||||
|
filter.file.unmatch=*.so *.o *.a *.la
|
||||||
|
filter.file.ignore.hidden=0
|
||||||
|
filter.dir.ignore.hidden=0
|
||||||
|
|
||||||
|
[filelist]
|
||||||
|
0=/home/morph/lladd/recovery.c
|
||||||
|
1=/home/morph/lladd/logger/logparser.c
|
||||||
|
2=/home/morph/lladd/logger/logstreamer.c
|
||||||
|
3=/home/morph/lladd/constants.h
|
||||||
|
4=/home/morph/lladd/bufferManager.c
|
||||||
|
5=/home/morph/lladd/page.c
|
||||||
|
6=/home/morph/lladd/logger/logparser.h
|
||||||
|
7=/home/morph/lladd/operations.c
|
||||||
|
8=/home/morph/lladd/logger.c
|
||||||
|
9=/home/morph/lladd/operations/increment.c
|
||||||
|
10=/home/morph/lladd/transactional.c
|
||||||
|
11=/home/morph/lladd/operations.h
|
||||||
|
12=/home/morph/lladd/test/lhpackingfactor.c
|
||||||
|
13=/home/morph/lladd/test/lladdHashTest.c
|
||||||
|
14=/home/morph/lladd/operations/lladdhash.c
|
||||||
|
15=/home/morph/lladd/pbl/pbl.h
|
||||||
|
16=/home/morph/lladd/operations/lladdhash.h
|
||||||
|
17=/home/morph/lladd/transactional.h
|
||||||
|
|
||||||
|
[filenumbers]
|
||||||
|
0=61
|
||||||
|
1=21
|
||||||
|
2=1
|
||||||
|
3=43
|
||||||
|
4=329
|
||||||
|
5=510
|
||||||
|
6=71
|
||||||
|
7=1
|
||||||
|
8=63
|
||||||
|
9=1
|
||||||
|
10=67
|
||||||
|
11=1
|
||||||
|
12=17
|
||||||
|
13=1
|
||||||
|
14=104
|
||||||
|
15=387
|
||||||
|
16=58
|
||||||
|
17=8
|
||||||
|
|
||||||
|
[filemarkers]
|
||||||
|
0=
|
||||||
|
1=
|
||||||
|
2=
|
||||||
|
3=
|
||||||
|
4=
|
||||||
|
5=
|
||||||
|
6=
|
||||||
|
7=
|
||||||
|
8=
|
||||||
|
9=
|
||||||
|
10=
|
||||||
|
11=
|
||||||
|
12=
|
||||||
|
13=
|
||||||
|
14=
|
||||||
|
15=
|
||||||
|
16=
|
||||||
|
17=
|
||||||
|
|
||||||
|
[Project Tree]
|
||||||
|
0=0
|
||||||
|
|
||||||
|
[File Tree]
|
||||||
|
0=0
|
||||||
|
1=0:7
|
197
lladd/Makefile
Normal file
197
lladd/Makefile
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
srcdir = .
|
||||||
|
top_srcdir = ..
|
||||||
|
|
||||||
|
prefix = /usr/local
|
||||||
|
exec_prefix = ${prefix}
|
||||||
|
|
||||||
|
bindir = ${exec_prefix}/bin
|
||||||
|
sbindir = ${exec_prefix}/sbin
|
||||||
|
libexecdir = ${exec_prefix}/libexec
|
||||||
|
datadir = ${prefix}/share
|
||||||
|
sysconfdir = ${prefix}/etc
|
||||||
|
sharedstatedir = ${prefix}/com
|
||||||
|
localstatedir = ${prefix}/var
|
||||||
|
libdir = ${exec_prefix}/lib
|
||||||
|
infodir = ${prefix}/info
|
||||||
|
mandir = ${prefix}/man
|
||||||
|
includedir = ${prefix}/include
|
||||||
|
oldincludedir = /usr/include
|
||||||
|
|
||||||
|
DESTDIR =
|
||||||
|
|
||||||
|
pkgdatadir = $(datadir)/hello
|
||||||
|
pkglibdir = $(libdir)/hello
|
||||||
|
pkgincludedir = $(includedir)/hello
|
||||||
|
|
||||||
|
top_builddir = ..
|
||||||
|
|
||||||
|
ACLOCAL = aclocal-1.4
|
||||||
|
AUTOCONF = autoconf
|
||||||
|
AUTOMAKE = automake-1.4
|
||||||
|
AUTOHEADER = autoheader
|
||||||
|
|
||||||
|
INSTALL = /usr/bin/install -c
|
||||||
|
INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS)
|
||||||
|
INSTALL_DATA = ${INSTALL} -m 644
|
||||||
|
INSTALL_SCRIPT = ${INSTALL}
|
||||||
|
transform = s,x,x,
|
||||||
|
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
host_alias =
|
||||||
|
host_triplet = i686-pc-linux-gnu
|
||||||
|
AR = ar
|
||||||
|
AS = @AS@
|
||||||
|
CC = gcc
|
||||||
|
CHECK_CFLAGS =
|
||||||
|
CHECK_LIBS = -lcheck
|
||||||
|
CPP = gcc -E
|
||||||
|
CXX = g++
|
||||||
|
CXXCPP = g++ -E
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
ECHO = echo
|
||||||
|
EGREP = grep -E
|
||||||
|
EXEEXT =
|
||||||
|
F77 = g77
|
||||||
|
GCJ = @GCJ@
|
||||||
|
GCJFLAGS = @GCJFLAGS@
|
||||||
|
HAVE_LIB = @HAVE_LIB@
|
||||||
|
LIB = @LIB@
|
||||||
|
LIBTOOL = $(SHELL) $(top_builddir)/libtool
|
||||||
|
LN_S = ln -s
|
||||||
|
LTLIB = @LTLIB@
|
||||||
|
MAKEINFO = makeinfo
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = o
|
||||||
|
PACKAGE = hello
|
||||||
|
RANLIB = ranlib
|
||||||
|
RC = @RC@
|
||||||
|
STRIP = strip
|
||||||
|
VERSION = 0.1
|
||||||
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
|
CONFIG_HEADER = ../[config.h]
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
DIST_COMMON = Makefile.am Makefile.in
|
||||||
|
|
||||||
|
|
||||||
|
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
|
||||||
|
TAR = tar
|
||||||
|
GZIP_ENV = --best
|
||||||
|
all: all-redirect
|
||||||
|
.SUFFIXES:
|
||||||
|
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||||
|
cd $(top_srcdir) && $(AUTOMAKE) --gnu lladd/Makefile
|
||||||
|
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||||
|
cd $(top_builddir) \
|
||||||
|
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||||
|
|
||||||
|
tags: TAGS
|
||||||
|
TAGS:
|
||||||
|
|
||||||
|
|
||||||
|
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||||
|
|
||||||
|
subdir = lladd
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
here=`cd $(top_builddir) && pwd`; \
|
||||||
|
top_distdir=`cd $(top_distdir) && pwd`; \
|
||||||
|
distdir=`cd $(distdir) && pwd`; \
|
||||||
|
cd $(top_srcdir) \
|
||||||
|
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu lladd/Makefile
|
||||||
|
@for file in $(DISTFILES); do \
|
||||||
|
d=$(srcdir); \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||||
|
else \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
info-am:
|
||||||
|
info: info-am
|
||||||
|
dvi-am:
|
||||||
|
dvi: dvi-am
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
installcheck-am:
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-exec-am:
|
||||||
|
install-exec: install-exec-am
|
||||||
|
|
||||||
|
install-data-am:
|
||||||
|
install-data: install-data-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
install: install-am
|
||||||
|
uninstall-am:
|
||||||
|
uninstall: uninstall-am
|
||||||
|
all-am: Makefile
|
||||||
|
all-redirect: all-am
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||||
|
installdirs:
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||||
|
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
mostlyclean-am: mostlyclean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
clean-am: clean-generic mostlyclean-am
|
||||||
|
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
distclean-am: distclean-generic clean-am
|
||||||
|
-rm -f libtool
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
|
||||||
|
maintainer-clean-am: maintainer-clean-generic distclean-am
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
|
||||||
|
.PHONY: tags distdir info-am info dvi-am dvi check check-am \
|
||||||
|
installcheck-am installcheck install-exec-am install-exec \
|
||||||
|
install-data-am install-data install-am install uninstall-am uninstall \
|
||||||
|
all-redirect all-am all installdirs mostlyclean-generic \
|
||||||
|
distclean-generic clean-generic maintainer-clean-generic clean \
|
||||||
|
mostlyclean distclean maintainer-clean
|
||||||
|
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
0
lladd/Makefile.am
Normal file
0
lladd/Makefile.am
Normal file
288
lladd/bufferManager.h
Normal file
288
lladd/bufferManager.h
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Manages the page buffer
|
||||||
|
*
|
||||||
|
* @todo Allow error checking!
|
||||||
|
*
|
||||||
|
* @todo CORRECTNESS PROBLEM: Recovery assumes that each page is
|
||||||
|
* written atomically to disk, and that the LSN field of the page will
|
||||||
|
* be in sync with the contents of each record on the page. Since we
|
||||||
|
* use mmap() to read and write the pages, and a page fault could
|
||||||
|
* interrupt LLADD between a writeRecord and writeLSN call, it is
|
||||||
|
* possible for the operating system to steal dirty pages from the
|
||||||
|
* buffer manager. (We support steal in the normal case, but still
|
||||||
|
* need to be sure that the stolen pages are internally consistent!)
|
||||||
|
*
|
||||||
|
* It looks as though we will need to re-write the buffer manager so
|
||||||
|
* that it only uses read or write calls. Alternatively, we could
|
||||||
|
* lock pages as we update them, but that requires root privliges.
|
||||||
|
*
|
||||||
|
* @todo Refactoring for lock manager / correctness
|
||||||
|
*
|
||||||
|
* Possible interfaces:
|
||||||
|
*
|
||||||
|
|
||||||
|
|
||||||
|
blobManager - Provides blob handling @todo Set range??
|
||||||
|
Plan for modularity: Exactly one blob manager per storeFile.
|
||||||
|
Blob manager interacts with page manger via page manager's
|
||||||
|
public api.
|
||||||
|
|
||||||
|
- void * readBlob(rid); // if blob is resident, return a pointer to it.
|
||||||
|
// if blob isn't dirty, read it from its primary location.
|
||||||
|
// if it is dirty, but not resident (stolen), read from secondary location.
|
||||||
|
|
||||||
|
- writeBlob(rid); // if blob isn't dirty, marks blob dirty.
|
||||||
|
|
||||||
|
- kickBlob(rid); // if blob isn't dirty, free it.
|
||||||
|
// Otherwise, steal to blob store, but
|
||||||
|
// remember that its dirty.
|
||||||
|
|
||||||
|
- commitBlob(rid); // if blob is resident, flush it to disk,
|
||||||
|
// set pointer to new store bit, then
|
||||||
|
// write new store bit to bufferManager
|
||||||
|
|
||||||
|
- abortBlob(rid); // kickBlob(), mark it clean.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pageManager - Provides cached page handling, delegates to blob
|
||||||
|
manager when necessary. Doesn't implement an eviction policy.
|
||||||
|
That is left to a cacheManager. (Multiple cacheManagers can be
|
||||||
|
used with a single page manager.)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Page * page;
|
||||||
|
/* If this page is pinned, what's the maximum lsn that's dirtied it? * /
|
||||||
|
lsn_t * max_dirty_lsn = 0;
|
||||||
|
/* How many times has this page been pinned using readWriteMap()? * /
|
||||||
|
int pin_count;
|
||||||
|
} page_metadata_t;
|
||||||
|
|
||||||
|
|
||||||
|
Calls for user managed memory:
|
||||||
|
|
||||||
|
Read only access to record:
|
||||||
|
|
||||||
|
Cost with cache hit: memcpy();
|
||||||
|
|
||||||
|
- int readRecord(rid, void *);
|
||||||
|
|
||||||
|
Write record directly:
|
||||||
|
Cost with cache hit: memcpy(rid.size), eventual disk flush;
|
||||||
|
|
||||||
|
- int writeRecord(rid, lsn, void *);
|
||||||
|
|
||||||
|
@todo need alloc + free...
|
||||||
|
|
||||||
|
Calls for LLADD managed memory (returns pointers to LLADD's cache.)
|
||||||
|
|
||||||
|
Read only access to record (requires an un-pinning)
|
||||||
|
|
||||||
|
Cost with cache hit: pointer arithmetic.
|
||||||
|
|
||||||
|
- map_t readMapRecord(rid, &((const void *));
|
||||||
|
|
||||||
|
Map a page read / write. Pins the page, sets its lsn, and provides a pointer to the record:
|
||||||
|
Cost with cache hit: pointer arithmetic, eventual disk flush.
|
||||||
|
|
||||||
|
- map_t readWriteMapRecord(rid, &(void *));
|
||||||
|
|
||||||
|
Unmap a mapped page so that it can be kicked.
|
||||||
|
|
||||||
|
@param lsn can be 0 if this is a read-only mapping. Otherwise,
|
||||||
|
it should be the LSN of the operation that calls unmapRecord.
|
||||||
|
@todo What connection between the lock manager and this function
|
||||||
|
is there? Presumably, unmap should be called when the locks are
|
||||||
|
released...
|
||||||
|
|
||||||
|
- void unmapRecord(map_t, lsn);
|
||||||
|
|
||||||
|
cachePolicy
|
||||||
|
|
||||||
|
page_id kickPage(); // Choose a page to kick. May call logFlush() if necessary.
|
||||||
|
readPage(page); // Inform the cache that a page was read.
|
||||||
|
writePage(page); // Inform the cache that a page was written.
|
||||||
|
cacheHint(void *); // Optional method needed to implement dbmin.
|
||||||
|
|
||||||
|
lockManager
|
||||||
|
|
||||||
|
- These functions provide a locking implementation based on logical operations:
|
||||||
|
|
||||||
|
lock_t lock(Operation o);
|
||||||
|
unlock(Operation o);
|
||||||
|
|
||||||
|
- These functions provide a locking implementation based on physical operations:
|
||||||
|
|
||||||
|
(Insert bufferManager API here, but make each call take a xid and a lock_t* parameter)
|
||||||
|
|
||||||
|
Locking functions can return errors such as DEADLOCK, etc.
|
||||||
|
|
||||||
|
*
|
||||||
|
* @ingroup LLADD_CORE
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BUFFERMANAGER_H__
|
||||||
|
#define __BUFFERMANAGER_H__
|
||||||
|
|
||||||
|
#include <lladd/page.h>
|
||||||
|
#include <lladd/constants.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize buffer manager
|
||||||
|
* @return 0 on success
|
||||||
|
* @return error code on failure
|
||||||
|
*/
|
||||||
|
int bufInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pageid ID of the page you want to load
|
||||||
|
* @return fully formed Page type
|
||||||
|
* @return page with -1 ID if page not found
|
||||||
|
*/
|
||||||
|
Page loadPage(int pageid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* allocate a record
|
||||||
|
* @param xid The active transaction.
|
||||||
|
* @param size The size of the new record
|
||||||
|
* @return allocated record
|
||||||
|
*/
|
||||||
|
recordid ralloc(int xid, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function updates the LSN of a page. This is needed by the
|
||||||
|
* recovery process to make sure that each action is undone or redone
|
||||||
|
* exactly once.
|
||||||
|
*
|
||||||
|
* @param LSN The new LSN of the page.
|
||||||
|
* @param pageid ID of the page you want to write
|
||||||
|
*
|
||||||
|
* @todo This needs to be handled by ralloc and writeRecord for
|
||||||
|
* correctness. Right now, there is no way to atomically update a
|
||||||
|
* page(!) To fix this, we need to change bufferManager's
|
||||||
|
* implementation to use read/write (to prevent the OS from stealing
|
||||||
|
* pages in the middle of updates), and alter kickPage to see what the
|
||||||
|
* last LSN synced to disk was. If the log is too far behind, it will
|
||||||
|
* need to either choose a different page, or call flushLog(). We may
|
||||||
|
* need to implement a special version of fwrite() to do this
|
||||||
|
* atomically. (write does not have to write all of the data that was
|
||||||
|
* passed to it...)
|
||||||
|
*/
|
||||||
|
void writeLSN(long LSN, int pageid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pageid ID of page you want to read
|
||||||
|
* @return LSN found on disk
|
||||||
|
*/
|
||||||
|
long readLSN(int pageid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param rid recordid where you want to write
|
||||||
|
* @param dat data you wish to write
|
||||||
|
*/
|
||||||
|
void writeRecord(int xid, recordid rid, const void *dat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param xid transaction ID
|
||||||
|
* @param rid
|
||||||
|
* @param dat buffer for data
|
||||||
|
*/
|
||||||
|
void readRecord(int xid, recordid rid, void *dat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param page write page to disk, including correct LSN
|
||||||
|
* @return 0 on success
|
||||||
|
* @return error code on failure
|
||||||
|
*/
|
||||||
|
int flushPage(Page page);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this function does NOT write to disk, just drops the page from the active
|
||||||
|
* pages
|
||||||
|
* @param page to take out of buffer manager
|
||||||
|
* @return 0 on success
|
||||||
|
* @return error code on failure
|
||||||
|
int dropPage(Page page);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* all actions necessary when committing a transaction. Can assume that the log
|
||||||
|
* has been written as well as any other actions that do not depend on the
|
||||||
|
* buffer manager
|
||||||
|
*
|
||||||
|
* Basicly, this call is here because we used to do copy on write, and
|
||||||
|
* it might be useful when locking is implemented.
|
||||||
|
*
|
||||||
|
* @param xid transaction ID
|
||||||
|
* @return 0 on success
|
||||||
|
* @return error code on failure
|
||||||
|
*/
|
||||||
|
int bufTransCommit(int xid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Currently identical to bufTransCommit.
|
||||||
|
*
|
||||||
|
* @param xid transaction ID
|
||||||
|
* @return 0 on success
|
||||||
|
* @return error code on failure
|
||||||
|
*/
|
||||||
|
int bufTransAbort(int xid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* will write out any dirty pages, assumes that there are no running
|
||||||
|
* transactions
|
||||||
|
*/
|
||||||
|
void bufDeinit();
|
||||||
|
|
||||||
|
/** @todo Global file descriptors are nasty. */
|
||||||
|
|
||||||
|
extern int blobfd0;
|
||||||
|
extern int blobfd1;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
105
lladd/common.h
Normal file
105
lladd/common.h
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* A standard header file, adopted from Autobook.
|
||||||
|
*
|
||||||
|
* @todo: Need to make sure everyone actually includes this thing, and also includes constants.h
|
||||||
|
*
|
||||||
|
* @ingroup LLADD_CORE
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __lladd_common_h
|
||||||
|
#define __lladd_common_h 1
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
# define BEGIN_C_DECLS extern "C" {
|
||||||
|
# define END_C_DECLS }
|
||||||
|
#else /* !__cplusplus */
|
||||||
|
# define BEGIN_C_DECLS
|
||||||
|
# define END_C_DECLS
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/* Should be included by the .c files only. :( */
|
||||||
|
/*#if HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#if STDC_HEADERS
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <string.h>
|
||||||
|
#elif HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
#endif /*STDC_HEADERS*/
|
||||||
|
|
||||||
|
#if HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_ERRNO_H
|
||||||
|
# include <errno.h>
|
||||||
|
#endif /*HAVE_ERRNO_H*/
|
||||||
|
#ifndef errno
|
||||||
|
/* Some systems #define this! */
|
||||||
|
extern int errno;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define byte unsigned char
|
||||||
|
#define lsn_t off_t
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define DEBUGGING
|
||||||
|
#define DEBUG(...) \
|
||||||
|
printf(__VA_ARGS__); fflush(NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/*#define DEBUG(...) */
|
||||||
|
|
||||||
|
#endif /* __lladd_common_h */
|
178
lladd/config.h.in
Normal file
178
lladd/config.h.in
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/* lladd/config.h.in. Generated from configure.in by autoheader. */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||||
|
#undef HAVE_ARPA_INET_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `bzero' function. */
|
||||||
|
#undef HAVE_BZERO
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_DIRENT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
|
#undef HAVE_FCNTL_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getcwd' function. */
|
||||||
|
#undef HAVE_GETCWD
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpagesize' function. */
|
||||||
|
#undef HAVE_GETPAGESIZE
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
|
#undef HAVE_GETTIMEOFDAY
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `inet_ntoa' function. */
|
||||||
|
#undef HAVE_INET_NTOA
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <limits.h> header file. */
|
||||||
|
#undef HAVE_LIMITS_H
|
||||||
|
|
||||||
|
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||||
|
to 0 otherwise. */
|
||||||
|
#undef HAVE_MALLOC
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <malloc.h> header file. */
|
||||||
|
#undef HAVE_MALLOC_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memmove' function. */
|
||||||
|
#undef HAVE_MEMMOVE
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#undef HAVE_MEMORY_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memset' function. */
|
||||||
|
#undef HAVE_MEMSET
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `mkdir' function. */
|
||||||
|
#undef HAVE_MKDIR
|
||||||
|
|
||||||
|
/* Define to 1 if you have a working `mmap' system call. */
|
||||||
|
#undef HAVE_MMAP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `munmap' function. */
|
||||||
|
#undef HAVE_MUNMAP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||||
|
#undef HAVE_NDIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <netdb.h> header file. */
|
||||||
|
#undef HAVE_NETDB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||||
|
#undef HAVE_NETINET_IN_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `socket' function. */
|
||||||
|
#undef HAVE_SOCKET
|
||||||
|
|
||||||
|
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
||||||
|
zero-length file name argument. */
|
||||||
|
#undef HAVE_STAT_EMPTY_STRING_BUG
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stddef.h> header file. */
|
||||||
|
#undef HAVE_STDDEF_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strchr' function. */
|
||||||
|
#undef HAVE_STRCHR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strdup' function. */
|
||||||
|
#undef HAVE_STRDUP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strerror' function. */
|
||||||
|
#undef HAVE_STRERROR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#undef HAVE_STRING_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strrchr' function. */
|
||||||
|
#undef HAVE_STRRCHR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strstr' function. */
|
||||||
|
#undef HAVE_STRSTR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtoul' function. */
|
||||||
|
#undef HAVE_STRTOUL
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <syslog.h> header file. */
|
||||||
|
#undef HAVE_SYSLOG_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_SYS_DIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_SYS_NDIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||||
|
#undef HAVE_SYS_SOCKET_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#undef HAVE_SYS_TIME_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||||
|
#undef HAVE_SYS_WAIT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
||||||
|
slash. */
|
||||||
|
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#undef PACKAGE_BUGREPORT
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#undef PACKAGE_NAME
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#undef PACKAGE_STRING
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#undef PACKAGE_TARNAME
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
|
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||||
|
#undef TIME_WITH_SYS_TIME
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#undef VERSION
|
||||||
|
|
||||||
|
/* Define to empty if `const' does not conform to ANSI C. */
|
||||||
|
#undef const
|
||||||
|
|
||||||
|
/* Define to rpl_malloc if the replacement function should be used. */
|
||||||
|
#undef malloc
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
|
#undef pid_t
|
||||||
|
|
||||||
|
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||||
|
#undef size_t
|
126
lladd/constants.h
Normal file
126
lladd/constants.h
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* defines various constants
|
||||||
|
*
|
||||||
|
* @todo Sometime, LLADD's #includes need to be cleaned up. In
|
||||||
|
* particular, we should make sure everything directly or indirectly
|
||||||
|
* includes this file, common.h, and constants.h
|
||||||
|
*
|
||||||
|
* @ingroup LLADD_CORE
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CONSTANTS_H__
|
||||||
|
#define __CONSTANTS_H__
|
||||||
|
|
||||||
|
/*#define DEBUG 1*/
|
||||||
|
|
||||||
|
#define LOG_FILE "logfile.txt"
|
||||||
|
#define STORE_FILE "storefile.txt"
|
||||||
|
#define BLOB0_FILE "blob0_file.txt"
|
||||||
|
#define BLOB1_FILE "blob1_file.txt"
|
||||||
|
|
||||||
|
/* @define error codes
|
||||||
|
*/
|
||||||
|
#define OUT_OF_MEM 1
|
||||||
|
#define FILE_OPEN_ERROR 2
|
||||||
|
#define FILE_READ_ERROR 3
|
||||||
|
#define FILE_WRITE_ERROR 4
|
||||||
|
#define FILE_WRITE_OPEN_ERROR 5
|
||||||
|
#define MEM_WRITE_ERROR 6
|
||||||
|
|
||||||
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
|
/*#define MAX_BUFFER_SIZE 100003 */
|
||||||
|
/*#define MAX_BUFFER_SIZE 10007 */
|
||||||
|
#define MAX_BUFFER_SIZE 71
|
||||||
|
|
||||||
|
/* 71 */
|
||||||
|
#define BUFFER_ASOOCIATIVE 2
|
||||||
|
|
||||||
|
#define MAX_TRANSACTIONS 32
|
||||||
|
|
||||||
|
/** Operation types */
|
||||||
|
|
||||||
|
#define NO_INVERSE -1
|
||||||
|
#define OPERATION_SET 0
|
||||||
|
#define OPERATION_INCREMENT 1
|
||||||
|
#define OPERATION_DECREMENT 2
|
||||||
|
#define OPERATION_ALLOC 3
|
||||||
|
#define OPERATION_PREPARE 4
|
||||||
|
#define OPERATION_LHINSERT 5
|
||||||
|
#define OPERATION_LHREMOVE 6
|
||||||
|
#define OPERATION_DEALLOC 7
|
||||||
|
/* number above should be less than number below */
|
||||||
|
#define MAX_OPERATIONS 20
|
||||||
|
|
||||||
|
/** @todo undocumented */
|
||||||
|
|
||||||
|
#define INVALID_SLOT PAGE_SIZE
|
||||||
|
#define BLOB_SLOT (PAGE_SIZE + 1)
|
||||||
|
#define BLOB_REC_SIZE 12
|
||||||
|
#define BLOB_THRESHOLD_SIZE (PAGE_SIZE-30)
|
||||||
|
|
||||||
|
#define BITS_PER_BYTE 8
|
||||||
|
|
||||||
|
/** Log entry types. (Not to be confused with operation types, which are more interesting.) */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Definitions for different types of logs
|
||||||
|
*/
|
||||||
|
#define UPDATELOG 1
|
||||||
|
#define XBEGIN 2
|
||||||
|
#define XCOMMIT 3
|
||||||
|
#define XABORT 4
|
||||||
|
/* Folded into update log entries */
|
||||||
|
/*#define XALLOC 5*/
|
||||||
|
/** XEND is used for after a transaction is aborted or commited, and some
|
||||||
|
* additional steps are taken and then the XEND is written */
|
||||||
|
#define XEND 6
|
||||||
|
#define CLRLOG 7
|
||||||
|
|
||||||
|
#endif
|
126
lladd/logger.h
Normal file
126
lladd/logger.h
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* External interaface to Logging API. (Only exposes operations used
|
||||||
|
* to add entries to the log.)
|
||||||
|
*
|
||||||
|
* Logger is the front end for logging actions -- whatever must be done (ie
|
||||||
|
* write to the log tail; flushing for commits) is handled in these functions
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* @see logger2.h
|
||||||
|
*
|
||||||
|
* @ingroup LLADD_CORE
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* *************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __LOGGER_H__
|
||||||
|
#define __LOGGER_H__
|
||||||
|
|
||||||
|
#include "transactional.h"
|
||||||
|
#include "operations.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Does NOT write a transaction begin; rather, just returns that the
|
||||||
|
LSN of a potential entry is -1 so the next command will have a
|
||||||
|
prevLSN of -1. (Althoug this is currently a no-op, it's possible
|
||||||
|
that some other logging scheme would actually write begin records.)
|
||||||
|
*/
|
||||||
|
long LogTransBegin(Transaction t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* logs the fact that a rid has been allocated for a transaction
|
||||||
|
*/
|
||||||
|
long LogTransAlloc(long prevLSN, int xid, recordid rid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a transaction COMMIT to the log tail, then flush the log tail immediately to disk
|
||||||
|
|
||||||
|
@return the LSN of this entry
|
||||||
|
*/
|
||||||
|
long LogTransCommit(long prevLSN, int xid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a transaction ABORTto the log tail
|
||||||
|
|
||||||
|
@return returns the LSN of this entry
|
||||||
|
*/
|
||||||
|
long LogTransAbort(long prevLSN, int xid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
LogUpdate writes an UPDATE log record to the log tail
|
||||||
|
|
||||||
|
returns the LSN of this entry
|
||||||
|
*/
|
||||||
|
long LogUpdate (long prevLSN, int xid, recordid rid, Operation op, const void *args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a compensation log record. These records are used to allow
|
||||||
|
for efficient recovery, and possibly for log truncation. They
|
||||||
|
record the completion of undo operations.
|
||||||
|
*/
|
||||||
|
long LogCLR (long prevLSN, int xid, long ulLSN, recordid ulRID, long ulPrevLSN);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a end transaction record @ todo What does this do exactly? Indicate completion of aborts?
|
||||||
|
*/
|
||||||
|
long LogEnd (long prevLSN, int xid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Starts a new log stream, possibly other stuff can go here too?
|
||||||
|
*/
|
||||||
|
void logInit();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called when ALL transactions are guaranteed to be completed (either
|
||||||
|
committed or aborted) and no new ones can be had. So therefore we
|
||||||
|
can close the log streamer and delete the log file. @todo Doesn't
|
||||||
|
delete logs right now. (For debugging)
|
||||||
|
*/
|
||||||
|
void logDeinit();
|
||||||
|
|
||||||
|
#endif
|
129
lladd/logger/logEntry.h
Normal file
129
lladd/logger/logEntry.h
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
#ifndef __LLADD_LOGGING_LOGENTRY_H
|
||||||
|
#define __LLADD_LOGGING_LOGENTRY_H
|
||||||
|
|
||||||
|
#include <lladd/common.h>
|
||||||
|
#include <lladd/page.h>
|
||||||
|
|
||||||
|
BEGIN_C_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
@file
|
||||||
|
|
||||||
|
Next generation logger api.
|
||||||
|
|
||||||
|
@todo Was getting some memory over-runs from the fact that I didn't
|
||||||
|
know the exact length of a raw log entry. This seems to be fixed
|
||||||
|
now. (Need to run through electric fence / determine the 'right
|
||||||
|
way' to do this...)
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
lsn_t thisUpdateLSN;
|
||||||
|
recordid rid;
|
||||||
|
lsn_t undoNextLSN;
|
||||||
|
} CLRLogEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int funcID : 8;
|
||||||
|
recordid rid;
|
||||||
|
unsigned int argSize : 16; /*2^16 = 64M*/
|
||||||
|
/* int invertible; */ /* no longer needed */
|
||||||
|
/* Implicit members:
|
||||||
|
args; @ ((byte*)ule) + sizeof(UpdateLogEntry)
|
||||||
|
preImage; @ ((byte*)ule) + sizeof(UpdateLogEntry) + ule.argSize */
|
||||||
|
} UpdateLogEntry;
|
||||||
|
|
||||||
|
struct __raw_log_entry {
|
||||||
|
lsn_t LSN;
|
||||||
|
lsn_t prevLSN;
|
||||||
|
int xid;
|
||||||
|
unsigned int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*#define sizeofRawLogEntry (sizeof(lsn_t)*2+sizeof(int)+4)*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
lsn_t LSN;
|
||||||
|
lsn_t prevLSN;
|
||||||
|
int xid;
|
||||||
|
unsigned int type;
|
||||||
|
union {
|
||||||
|
UpdateLogEntry update;
|
||||||
|
CLRLogEntry clr;
|
||||||
|
} contents;
|
||||||
|
} LogEntry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
All of these return a pointer to a single malloced region that should be freed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate a log entry that does not contain any extra payload information. (Eg: Tbegin, Tcommit, etc.)
|
||||||
|
*/
|
||||||
|
LogEntry * allocCommonLogEntry(lsn_t prevLSN, int xid, unsigned int type);
|
||||||
|
/**
|
||||||
|
Allocate a log entry with extra payload info.(eg: Tupdate, Talloc, etc)
|
||||||
|
*/
|
||||||
|
LogEntry * allocUpdateLogEntry(lsn_t prevLSN, int xid,
|
||||||
|
unsigned int operation, recordid rid,
|
||||||
|
const byte * args, unsigned int argSize, const byte * preImage);
|
||||||
|
/**
|
||||||
|
Allocate a CLR entry. These are written during recovery to
|
||||||
|
indicate that the stable copy of the store file reflects the state
|
||||||
|
of the database after an operation has successfuly been
|
||||||
|
redone/undone.
|
||||||
|
*/
|
||||||
|
LogEntry * allocCLRLogEntry (lsn_t prevLSN, int xid,
|
||||||
|
lsn_t thisUpdateLSN, recordid rid, lsn_t undoNextLSN);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t sizeofLogEntry(const LogEntry * log);
|
||||||
|
const byte * getUpdateArgs(const LogEntry * log);
|
||||||
|
const byte * getUpdatePreImage(const LogEntry * log);
|
||||||
|
|
||||||
|
END_C_DECLS
|
||||||
|
|
||||||
|
#endif /* __LOGENTRY_H */
|
115
lladd/logger/logHandle.h
Normal file
115
lladd/logger/logHandle.h
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 "logEntry.h"
|
||||||
|
#include "logWriter.h"
|
||||||
|
|
||||||
|
#ifndef __LOGHANDLE_H
|
||||||
|
#define __LOGHANDLE_H
|
||||||
|
|
||||||
|
BEGIN_C_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
@file
|
||||||
|
A simple data structure that allows forward iterations over
|
||||||
|
the log, and also allows reverse iterations. Forward iterations
|
||||||
|
are used for redo, and return every log entry, in its original
|
||||||
|
order. Reverse iterations are used for undo, and are transaction
|
||||||
|
specific. They follow the prevLSN. (or the next entry to be
|
||||||
|
undone stored in any CLR's that are encountered.)
|
||||||
|
|
||||||
|
logHandle is useful for read only access to the log.
|
||||||
|
|
||||||
|
@see logWriter.h For write access to the log.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int (guard_fcn_t)(LogEntry *, void *);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/** The LSN of the last log entry returned.*/
|
||||||
|
/* lsn_t file_offset; */ /* Unneeded? */
|
||||||
|
/** The LSN of the log entry that we would return if next is called. */
|
||||||
|
lsn_t next_offset;
|
||||||
|
/** The LSN of the log entry that we would return if previous is called. */
|
||||||
|
lsn_t prev_offset;
|
||||||
|
guard_fcn_t * guard;
|
||||||
|
void * guard_state;
|
||||||
|
} LogHandle;
|
||||||
|
|
||||||
|
/** Returns a logHandle pointing at the first log entry in the log. */
|
||||||
|
LogHandle getLogHandle();
|
||||||
|
/** Returns a logHandle pointing at lsn. */
|
||||||
|
LogHandle getLSNHandle(lsn_t lsn);
|
||||||
|
/** Returns a 'guarded log handle'. This handle executes a callback
|
||||||
|
function on each entry it encounters. If the guard returns 0,
|
||||||
|
then it's iterator terminates. Otherwise, it behaves normally. */
|
||||||
|
LogHandle getGuardedHandle(lsn_t lsn, guard_fcn_t * f, void * guard_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@return a pointer to the next log entry in the log, or NULL if at
|
||||||
|
EOF.
|
||||||
|
|
||||||
|
*/
|
||||||
|
LogEntry * nextInLog(LogHandle * h);
|
||||||
|
/**
|
||||||
|
Returns a pointer to the previous log entry in this
|
||||||
|
transaction. This is used to undo transactions. If the logHandle
|
||||||
|
is a guarded handle, the handle returns null.
|
||||||
|
|
||||||
|
The guard is useful for Tprepare, partial rollback, and probably
|
||||||
|
any reasonable lock manager implementations.
|
||||||
|
|
||||||
|
If we encounter a CLR, that means that everything after the clr's
|
||||||
|
undoNextLSN has already been undone. In that case, we can skip
|
||||||
|
all intervening log entries (including CLR's), since they contain
|
||||||
|
'stale' data.
|
||||||
|
|
||||||
|
@return NULL if there is no previous LogEntry for this
|
||||||
|
transaction, or if the guard indicates that we're done by returning 0.
|
||||||
|
*/
|
||||||
|
LogEntry * previousInTransaction(LogHandle * h);
|
||||||
|
/*
|
||||||
|
void closeHandle(LogHandle h);
|
||||||
|
*/
|
||||||
|
END_C_DECLS
|
||||||
|
|
||||||
|
#endif
|
158
lladd/logger/logWriter.h
Normal file
158
lladd/logger/logWriter.h
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 All of the logWriter calls should be reentrant.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LOGWRITER_H__
|
||||||
|
#define __LOGWRITER_H__
|
||||||
|
|
||||||
|
#include "logEntry.h"
|
||||||
|
#include <lladd/constants.h>
|
||||||
|
#include <lladd/common.h>
|
||||||
|
|
||||||
|
BEGIN_C_DECLS
|
||||||
|
/**
|
||||||
|
start a new log stream by opening the log file for reading
|
||||||
|
|
||||||
|
returns 0 on success, or an error code define above
|
||||||
|
|
||||||
|
*/
|
||||||
|
int openLogWriter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
@param e Pointer to a log entry. After the call, e->LSN will be set appropriately.
|
||||||
|
|
||||||
|
returns 0 on success, or an error code defined above
|
||||||
|
*/
|
||||||
|
int writeLogEntry(LogEntry * e);
|
||||||
|
|
||||||
|
/*
|
||||||
|
flush the entire log (tail) that is currently in memory to disk
|
||||||
|
*/
|
||||||
|
void syncLog();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Close the log stream
|
||||||
|
*/
|
||||||
|
void closeLogWriter();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the current position of the stream (in terms of bytes)
|
||||||
|
*/
|
||||||
|
/*long getFilePos();*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Actually deletes the log file that may have been written to disk! Danger!!
|
||||||
|
Only use after calling closeLogStream AND you are sure there are no active (or
|
||||||
|
future active) transactions!
|
||||||
|
*/
|
||||||
|
void deleteLogWriter();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the current position of the stream no matter where it is
|
||||||
|
*/
|
||||||
|
/*long streamPos();*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the position of the stream if it were to read.
|
||||||
|
*/
|
||||||
|
/*long writeStreamPos();*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* readLog reads a line from the log puts it in a string
|
||||||
|
*
|
||||||
|
* This was made static because it exports state that the interface
|
||||||
|
* should be hiding. (To use this function, the user must make
|
||||||
|
* assumptions regarding the value of the FILE's current offset.)
|
||||||
|
*
|
||||||
|
* returns the number of bytes read and put into buffer
|
||||||
|
* */
|
||||||
|
/*int readLog(byte **buffer);*/
|
||||||
|
/* LogEntry * readLogEntry(); */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* seek to a position in the log file and read it into the buffer
|
||||||
|
*
|
||||||
|
* returns the number of bytes read and put into buffer
|
||||||
|
* */
|
||||||
|
|
||||||
|
/*int seekAndReadLog(long pos, byte **buffer);*/
|
||||||
|
|
||||||
|
LogEntry * readLSNEntry(lsn_t LSN);
|
||||||
|
|
||||||
|
/* lsn_t nextLSN(); */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tell the current position in the log file
|
||||||
|
* */
|
||||||
|
/*long readPos ();
|
||||||
|
|
||||||
|
void seekInLog(long pos);*/
|
||||||
|
|
||||||
|
END_C_DECLS
|
||||||
|
|
||||||
|
#endif /* __LLADD_LOGGER_LOGWRITER_H */
|
||||||
|
|
123
lladd/logger/logger2.h
Normal file
123
lladd/logger/logger2.h
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* New version of logger. Based on logger.h
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __LOGGER2_H__
|
||||||
|
#define __LOGGER2_H__
|
||||||
|
|
||||||
|
#include "logEntry.h"
|
||||||
|
#include "logHandle.h"
|
||||||
|
#include <lladd/operations.h>
|
||||||
|
/**
|
||||||
|
Contains the state needed by the logging layer to perform
|
||||||
|
operations on a transaction.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int xid;
|
||||||
|
lsn_t prevLSN;
|
||||||
|
LogHandle lh;
|
||||||
|
} TransactionLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Inform the logging layer that a new transaction has begun.
|
||||||
|
Currently a no-op.
|
||||||
|
*/
|
||||||
|
TransactionLog LogTransBegin(int xid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a transaction COMMIT to the log tail, then flush the log tail immediately to disk
|
||||||
|
|
||||||
|
@return 0 if the transaction succeeds, an error code otherwise.
|
||||||
|
*/
|
||||||
|
void LogTransCommit(TransactionLog * l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a transaction ABORT to the log tail
|
||||||
|
|
||||||
|
@return 0 if the transaction was successfully aborted.
|
||||||
|
*/
|
||||||
|
void LogTransAbort(TransactionLog * l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
LogUpdate writes an UPDATE log record to the log tail
|
||||||
|
*/
|
||||||
|
LogEntry * LogUpdate(TransactionLog * l, recordid rid, int operation, const byte * args);
|
||||||
|
/* *
|
||||||
|
(Was folded into LogUpdate.)
|
||||||
|
|
||||||
|
Logs the fact that a rid has been allocated for a transaction.
|
||||||
|
@ todo Should this be folded into LogUpdate? (Make "alloc" an operation...)
|
||||||
|
@ todo Surely, we need a dealloc!
|
||||||
|
*/
|
||||||
|
/*lsn_t LogTransAlloc(TransactionLog * l, recordid rid);*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a compensation log record. These records are used to allow
|
||||||
|
for efficient recovery, and possibly for log truncation. They
|
||||||
|
record the completion of undo operations.
|
||||||
|
|
||||||
|
@return the lsn of the CLR entry that was written to the log.
|
||||||
|
(Needed so that the lsn slot of the page in question can be
|
||||||
|
updated.)
|
||||||
|
|
||||||
|
@todo Remove this from this interface? Should it be internal to
|
||||||
|
the recovery routines?
|
||||||
|
*/
|
||||||
|
lsn_t LogCLR (LogEntry * undone); /*TransactionLog * l, long ulLSN, recordid ulRID, long ulPrevLSN); */
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a end transaction record @todo What does this do exactly? Indicate completion of aborts?
|
||||||
|
@todo Move into recovery-only code?
|
||||||
|
*/
|
||||||
|
void LogEnd (TransactionLog * l);
|
||||||
|
|
||||||
|
#endif
|
179
lladd/operations.h
Normal file
179
lladd/operations.h
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Interface for defining new logical operations.
|
||||||
|
*
|
||||||
|
* @ingroup LLADD_CORE OPERATIONS
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __OPERATIONS_H__
|
||||||
|
#define __OPERATIONS_H__
|
||||||
|
|
||||||
|
/*#include <stddef.h>*/
|
||||||
|
/*#include "common.h"*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <lladd/constants.h>
|
||||||
|
#include <lladd/transactional.h>
|
||||||
|
#include <lladd/logger/logEntry.h>
|
||||||
|
|
||||||
|
BEGIN_C_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
/* @type Function
|
||||||
|
* function pointer that the operation will run
|
||||||
|
*/
|
||||||
|
typedef int (*Function)(int xid, recordid r, const void *d);
|
||||||
|
|
||||||
|
/* @type Operation
|
||||||
|
|
||||||
|
* @param sizeofData size of the data that function accepts (as void*)
|
||||||
|
* @param undo index into operations table of undo function (takes same args)
|
||||||
|
* @param run what function to actually run
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @type Special cases
|
||||||
|
*/
|
||||||
|
#define SIZEOF_RECORD -1
|
||||||
|
#define NO_INVERSE -1
|
||||||
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* ID of operation, also index into operations table
|
||||||
|
*/
|
||||||
|
int id;
|
||||||
|
/**
|
||||||
|
This value is the size of the arguments that this operation
|
||||||
|
takes. If set to SIZEOF_RECORD, then the size of the record
|
||||||
|
that the operation affects will be used instead.
|
||||||
|
*/
|
||||||
|
size_t sizeofData;
|
||||||
|
/**
|
||||||
|
Does this operation supply an undo operation?
|
||||||
|
|
||||||
|
--Unneeded; just set undo to the special value NO_INVERSE.
|
||||||
|
*/
|
||||||
|
/* int invertible; */
|
||||||
|
/**
|
||||||
|
Implementing operations that may span records is subtle.
|
||||||
|
Recovery assumes that page writes (and therefore logical
|
||||||
|
operations) are atomic. This isn't the case for operations that
|
||||||
|
span records. Instead, there are two (and probably other) choices:
|
||||||
|
|
||||||
|
- Periodically checkpoint, syncing the data store to disk, and
|
||||||
|
writing a checkpoint operation. No writes can be serviced
|
||||||
|
during the sync, and this implies 'no steal'. See:
|
||||||
|
|
||||||
|
@inproceedings{ woo97accommodating,
|
||||||
|
author = "Seung-Kyoon Woo and Myoung-Ho Kim and Yoon-Joon Lee",
|
||||||
|
title = "Accommodating Logical Logging under Fuzzy Checkpointing in Main Memory Databases",
|
||||||
|
booktitle = "International Database Engineering and Application Symposium",
|
||||||
|
pages = "53-62",
|
||||||
|
year = "1997",
|
||||||
|
url = "citeseer.ist.psu.edu/135200.html" }
|
||||||
|
|
||||||
|
for a more complex scheme involving a hybrid logical/physical
|
||||||
|
logging system that does not implement steal.
|
||||||
|
|
||||||
|
The other option:
|
||||||
|
|
||||||
|
- Get rid of operations that span records entirely by
|
||||||
|
splitting complex logical operations into simpler one.
|
||||||
|
|
||||||
|
We chose the second option for now.
|
||||||
|
|
||||||
|
*/
|
||||||
|
int undo;
|
||||||
|
Function run;
|
||||||
|
} Operation;
|
||||||
|
|
||||||
|
/* These need to be installed, since they are required by applications that use LLADD. */
|
||||||
|
/*#include "constants.h"
|
||||||
|
#include <lladd/bufferManager.h>*/
|
||||||
|
|
||||||
|
#include "operations/increment.h"
|
||||||
|
#include "operations/decrement.h"
|
||||||
|
#include "operations/set.h"
|
||||||
|
#include "operations/prepare.h"
|
||||||
|
#include "operations/lladdhash.h"
|
||||||
|
#include "operations/alloc.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern Operation operationsTable[]; /* [MAX_OPERATIONS]; memset somewhere */
|
||||||
|
|
||||||
|
/** Performs an operation during normal execution.
|
||||||
|
|
||||||
|
Does not write to the log, and assumes that the operation's
|
||||||
|
results are not already in the buffer manager.
|
||||||
|
*/
|
||||||
|
void doUpdate(const LogEntry * e);
|
||||||
|
/** Undo the update under normal operation, and during recovery.
|
||||||
|
|
||||||
|
Assumes that the operation's results are reflected in the contents of the buffer manager.
|
||||||
|
|
||||||
|
Does not write to the log.
|
||||||
|
|
||||||
|
@todo Currently, undos do not result in CLR entries, but they should. (Should this be done here?)
|
||||||
|
|
||||||
|
*/
|
||||||
|
void undoUpdate(const LogEntry * e);
|
||||||
|
/**
|
||||||
|
Redoes an operation during recovery. This is different than
|
||||||
|
doUpdate because it checks to see if the operation needs to be redone
|
||||||
|
before redoing it. (if(e->lsn > e->rid.lsn) { doUpdate(e); } return)
|
||||||
|
|
||||||
|
Also, this is the only function in operations.h that can take
|
||||||
|
either CLR or UPDATE log entries. The other functions can only
|
||||||
|
handle update entries.
|
||||||
|
|
||||||
|
Does not write to the log.
|
||||||
|
*/
|
||||||
|
void redoUpdate(const LogEntry * e);
|
||||||
|
|
||||||
|
END_C_DECLS
|
||||||
|
|
||||||
|
#endif
|
11
lladd/operations/alloc.h
Normal file
11
lladd/operations/alloc.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include <lladd/operations.h>
|
||||||
|
|
||||||
|
#ifndef __ALLOC_H
|
||||||
|
#define __ALLOC_H
|
||||||
|
|
||||||
|
Operation getAlloc();
|
||||||
|
Operation getDealloc();
|
||||||
|
recordid Talloc(int xid, size_t size);
|
||||||
|
void Tdealloc(int xid, recordid rid);
|
||||||
|
|
||||||
|
#endif
|
65
lladd/operations/decrement.h
Normal file
65
lladd/operations/decrement.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* function definitions for decrement
|
||||||
|
*
|
||||||
|
* @ingroup OPERATIONS
|
||||||
|
*
|
||||||
|
* @see increment.h
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DECREMENT_H__
|
||||||
|
#define __DECREMENT_H__
|
||||||
|
|
||||||
|
/*#include "../constants.h"*/
|
||||||
|
#include <lladd/operations.h>
|
||||||
|
/*#include "../bufferManager.h"*/
|
||||||
|
|
||||||
|
#define Tdecrement(xid,rid) Tupdate(xid,rid,0, OPERATION_DECREMENT)
|
||||||
|
|
||||||
|
Operation getDecrement();
|
||||||
|
|
||||||
|
#endif
|
68
lladd/operations/increment.h
Normal file
68
lladd/operations/increment.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* function definitions for increment
|
||||||
|
*
|
||||||
|
* Increment provides an example of a logical operation that does not
|
||||||
|
* require any extra logging information, and (could someday) support
|
||||||
|
* reordering.
|
||||||
|
*
|
||||||
|
* @see decrement.h
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __INCREMENT_H__
|
||||||
|
#define __INCREMENT_H__
|
||||||
|
|
||||||
|
/*#include "../constants.h"*/
|
||||||
|
#include <lladd/operations.h>
|
||||||
|
/*#include "../bufferManager.h"*/
|
||||||
|
|
||||||
|
#define Tincrement(xid,rid) Tupdate(xid,rid,0, OPERATION_INCREMENT)
|
||||||
|
|
||||||
|
Operation getIncrement();
|
||||||
|
|
||||||
|
#endif
|
78
lladd/operations/lladdhash.h
Normal file
78
lladd/operations/lladdhash.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* A durable, recoverable hashtable
|
||||||
|
* Based on Peter Graf's pblhash, <http://mission.base.com/peter/source/>
|
||||||
|
* (actually based on jbhash.c, which was based on pblhash)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
@file
|
||||||
|
|
||||||
|
A persistant hash, based on logical operations.
|
||||||
|
|
||||||
|
lladdhash: /yad-hash/ n. LLADD's hash table, based on logical operations.
|
||||||
|
|
||||||
|
@todo CORRECTNESS PROBLEM. It allows logical operations to span
|
||||||
|
more than one record, which is incompatible with our logical
|
||||||
|
operations. Also, Blob handling + LLADD hash's implementation
|
||||||
|
result in poor performance when the bucket size is large, and
|
||||||
|
transactions are short.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LLADDHASH_H__
|
||||||
|
#define __LLADDHASH_H__
|
||||||
|
|
||||||
|
/*#include "../transactional.h"*/
|
||||||
|
|
||||||
|
#include <lladd/operations.h>
|
||||||
|
|
||||||
|
#define MAX_LLADDHASHES 1000
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
recordid store;
|
||||||
|
size_t keylen;
|
||||||
|
size_t datlen;
|
||||||
|
recordid next;
|
||||||
|
} lladdHashItem_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int size;
|
||||||
|
recordid hashmap_record;
|
||||||
|
/* recordid store; */
|
||||||
|
int store;
|
||||||
|
lladdHashItem_t *iterItem;
|
||||||
|
unsigned int iterIndex;
|
||||||
|
void *iterData;
|
||||||
|
recordid* hashmap;
|
||||||
|
} lladdHash_t;
|
||||||
|
|
||||||
|
/** Allocate a new hash */
|
||||||
|
|
||||||
|
lladdHash_t * lHtCreate(int xid, int size);
|
||||||
|
int lHtValid(int xid, lladdHash_t *ht);
|
||||||
|
int lHtLookup( int xid, lladdHash_t *ht, const void *key, size_t keylen, void *buf );
|
||||||
|
int lHtFirst( int xid, lladdHash_t *ht, void *buf );
|
||||||
|
int lHtNext( int xid, lladdHash_t *ht, void *buf );
|
||||||
|
int lHtCurrent( int xid, lladdHash_t *ht, void *buf);
|
||||||
|
int lHtCurrentKey(int xid, lladdHash_t *ht, void *buf);
|
||||||
|
int lHtDelete(int xid, lladdHash_t *ht);
|
||||||
|
int lHtPosition( int xid, lladdHash_t *ht, const void *key, size_t key_length );
|
||||||
|
/* These two are the only ones that result in a log entry... */
|
||||||
|
/*
|
||||||
|
int _lHtInsert(int xid, lladdHash_t *ht, const void *key, size_t keylen, void * dat, size_t datlen);
|
||||||
|
int _lHtRemove( int xid, lladdHash_t *ht, const void *key, size_t keylen, void *buf );
|
||||||
|
*/
|
||||||
|
|
||||||
|
int lHtInsert(int xid, lladdHash_t *ht, const void *key, size_t keylen, void * dat, size_t datlen);
|
||||||
|
int lHtRemove( int xid, lladdHash_t *ht, const void *key, size_t keylen, void *buf, size_t buflen);
|
||||||
|
|
||||||
|
Operation getLHInsert();
|
||||||
|
Operation getLHRemove();
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
71
lladd/operations/prepare.h
Normal file
71
lladd/operations/prepare.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Prepare pseudo-operation
|
||||||
|
*
|
||||||
|
* Tprepare() uses the operation interface to abstract away log handling.
|
||||||
|
* It would be nice if the logger API could be simplified by having
|
||||||
|
* more of its functionality handled this way.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @ingroup OPERATIONS
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PREPARE_H__
|
||||||
|
#define __PREPARE_H__
|
||||||
|
|
||||||
|
#include <lladd/operations.h>
|
||||||
|
|
||||||
|
extern recordid prepare_bogus_rec;
|
||||||
|
|
||||||
|
#define Tprepare(xid, rec, dat) Tupdate(xid, rec, 0, OPERATION_PREPARE)
|
||||||
|
|
||||||
|
Operation getPrepare();
|
||||||
|
|
||||||
|
int prepareGuard(LogEntry * e, void * state);
|
||||||
|
void * getPrepareGuardState();
|
||||||
|
#endif
|
62
lladd/operations/set.h
Normal file
62
lladd/operations/set.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* function definitions for set
|
||||||
|
*
|
||||||
|
* @ingroup OPERATIONS
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
**********************************************/
|
||||||
|
|
||||||
|
#ifndef __SET_H__
|
||||||
|
#define __SET_H__
|
||||||
|
|
||||||
|
#include <lladd/operations.h>
|
||||||
|
|
||||||
|
#define Tset(xid,rid,dat) Tupdate(xid,rid,dat, OPERATION_SET)
|
||||||
|
|
||||||
|
Operation getSet();
|
||||||
|
|
||||||
|
#endif
|
150
lladd/page.h
Normal file
150
lladd/page.h
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* interface for dealing with pages
|
||||||
|
*
|
||||||
|
* @ingroup LLADD_CORE
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* @todo update docs in this file.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __PAGE_H__
|
||||||
|
#define __PAGE_H__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
BEGIN_C_DECLS
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
/*#include <pbl/pbl.h> */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* represents how to look up a record on a page
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int page;
|
||||||
|
int slot;
|
||||||
|
size_t size;
|
||||||
|
} recordid;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct Page_s {
|
||||||
|
int id;
|
||||||
|
long LSN;
|
||||||
|
byte *memAddr;
|
||||||
|
int dirty;
|
||||||
|
struct Page_s *next;
|
||||||
|
/** for replacement policy */
|
||||||
|
struct Page_s *prev;
|
||||||
|
/** this too */
|
||||||
|
int queue;
|
||||||
|
} Page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tracks changes to blobs
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int xid;
|
||||||
|
recordid *records;
|
||||||
|
size_t len;
|
||||||
|
} touchedBlob_t;
|
||||||
|
|
||||||
|
#define DEFAULT_TOUCHED 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initializes all the important variables needed in all the
|
||||||
|
* functions dealing with pages.
|
||||||
|
*/
|
||||||
|
void pageInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assumes that the page is already loaded in memory. It takes
|
||||||
|
* as a parameter a Page. The Page struct contains the new LSN and the page
|
||||||
|
* number to which the new LSN must be written to.
|
||||||
|
*/
|
||||||
|
void pageWriteLSN(Page page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assumes that the page is already loaded in memory. It takes
|
||||||
|
* as a parameter a Page and returns the LSN that is currently written on that
|
||||||
|
* page in memory.
|
||||||
|
*/
|
||||||
|
long pageReadLSN(Page page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assumes that the page is already loaded in memory. It takes as a
|
||||||
|
* parameter a Page, and returns an estimate of the amount of free space on this
|
||||||
|
* page. This is either exact, or an underestimate.
|
||||||
|
*/
|
||||||
|
size_t freespace(Page page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assumes that the page is already loaded in memory. It takes as
|
||||||
|
* parameters a Page and the size in bytes of the new record. pageRalloc()
|
||||||
|
* returns a recordid representing the newly allocated record.
|
||||||
|
*/
|
||||||
|
recordid pageRalloc(Page page, size_t size);
|
||||||
|
|
||||||
|
void pageWriteRecord(int xid, Page page, recordid rid, const byte *data);
|
||||||
|
|
||||||
|
void pageReadRecord(int xid, Page page, recordid rid, byte *buff);
|
||||||
|
|
||||||
|
void pageCommit(int xid);
|
||||||
|
|
||||||
|
void pageAbort(int xid);
|
||||||
|
|
||||||
|
void pageRealloc(Page *p, int id);
|
||||||
|
|
||||||
|
Page* pageAlloc(int id);
|
||||||
|
|
||||||
|
recordid pageSlotRalloc(Page page, recordid rid);
|
||||||
|
|
||||||
|
int pageTest();
|
||||||
|
recordid pageBalloc(Page page, int size, int offset);
|
||||||
|
|
||||||
|
END_C_DECLS
|
||||||
|
|
||||||
|
#endif
|
9
lladd/recovery2.h
Normal file
9
lladd/recovery2.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#ifndef __LLADD_RECOVERY2_H
|
||||||
|
#define __LLADD_RECOVERY2_H
|
||||||
|
|
||||||
|
void InitiateRecovery();
|
||||||
|
/** This really doesn't belong in recovery.c, but there's so much code overlap, it doesn't make sense not to put it there. */
|
||||||
|
void undoTrans();
|
||||||
|
|
||||||
|
#endif
|
0
lladd/stamp-h.in
Normal file
0
lladd/stamp-h.in
Normal file
1
lladd/stamp-h1
Normal file
1
lladd/stamp-h1
Normal file
|
@ -0,0 +1 @@
|
||||||
|
timestamp for lladd/config.h
|
186
lladd/transactional.h
Normal file
186
lladd/transactional.h
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup LLADD_CORE Core API
|
||||||
|
*
|
||||||
|
* The minimal subset of LLADD necessary to implement transactional consistency.
|
||||||
|
*
|
||||||
|
* This module includes the standard API (excluding operations), the logger, the buffer mananger, and recovery code.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @defgroup OPERATIONS Logical Operations
|
||||||
|
*
|
||||||
|
* Implementations of logical operations, and the interfaces that allow new operations to be added.
|
||||||
|
*
|
||||||
|
* @todo Write a brief howto to explain the implementation of new operations.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Defines LLADD's primary interface.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @todo error handling
|
||||||
|
*
|
||||||
|
* @ingroup LLADD_CORE
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __TRANSACTIONAL_H__
|
||||||
|
#define __TRANSACTIONAL_H__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
BEGIN_C_DECLS
|
||||||
|
|
||||||
|
#include "page.h"
|
||||||
|
#include "operations.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently, LLADD has a fixed number of transactions that may be
|
||||||
|
* active at one time.
|
||||||
|
*/
|
||||||
|
#define EXCEED_MAX_TRANSACTIONS 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param xid transaction ID
|
||||||
|
* @param LSN last log that this transaction used
|
||||||
|
*/
|
||||||
|
/* @param status @ todo Undocumented. (Unused?)
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int xid;
|
||||||
|
long LSN;
|
||||||
|
/* int status; */
|
||||||
|
} Transaction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize the transactional system, including running recover (if
|
||||||
|
* necessary), building the operations_table, and opening the logs
|
||||||
|
* @return 0 on success
|
||||||
|
* @throws error code on error
|
||||||
|
*/
|
||||||
|
int Tinit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return positive transaction ID on success, negative return value on error
|
||||||
|
*/
|
||||||
|
int Tbegin();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used when extending LLADD.
|
||||||
|
* Operation implementors should wrap around this function to provide more mnuemonic names.
|
||||||
|
*
|
||||||
|
* @param xid The current transaction.
|
||||||
|
* @param rid The record the operation pertains to. For some logical operations, this will be a dummy record.
|
||||||
|
* @param dat Application specific data to be recorded in the log (for undo/redo), and to be passed to the implementation of op.
|
||||||
|
* @param op The operation's offset in operationsTable
|
||||||
|
*
|
||||||
|
* @see operations.h set.h
|
||||||
|
*/
|
||||||
|
void Tupdate(int xid, recordid rid, const void *dat, int op);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param xid transaction ID
|
||||||
|
* @param rid reference to page/slot
|
||||||
|
* @param dat buffer into which data goes
|
||||||
|
*/
|
||||||
|
void Tread(int xid, recordid rid, void *dat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param xid transaction ID
|
||||||
|
* @return 0 on success
|
||||||
|
* @throws error vallue on error
|
||||||
|
*/
|
||||||
|
int Tcommit(int xid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param xid The current transaction
|
||||||
|
* @param size The size, in bytes of the new record you wish to allocate
|
||||||
|
* @returns A new recordid. On success, this recordid's size will be
|
||||||
|
* the requested size. On failure, its size will be zero.
|
||||||
|
*/
|
||||||
|
recordid Talloc(int xid, size_t size);
|
||||||
|
|
||||||
|
/* @function Tabort
|
||||||
|
* @param xid transaction ID
|
||||||
|
* @return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
int Tabort(int xid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flushes all pages, cleans up log
|
||||||
|
* @return 0 on success
|
||||||
|
* @throws error value on error
|
||||||
|
*/
|
||||||
|
int Tdeinit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by the recovery process.
|
||||||
|
* Revives Tprepare'ed transactions.
|
||||||
|
*
|
||||||
|
* @param xid The xid that is to be revived.
|
||||||
|
* @param lsn The lsn of that xid's most recent PREPARE entry in the log.
|
||||||
|
*/
|
||||||
|
void Trevive(int xid, long lsn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by the recovery process.
|
||||||
|
*
|
||||||
|
* Sets the number of active transactions.
|
||||||
|
* Should not be used elsewhere.
|
||||||
|
*
|
||||||
|
* @param xid The new active transaction count.
|
||||||
|
*/
|
||||||
|
void TsetXIDCount(int xid);
|
||||||
|
|
||||||
|
END_C_DECLS
|
||||||
|
|
||||||
|
#endif
|
40
mkinstalldirs
Executable file
40
mkinstalldirs
Executable file
|
@ -0,0 +1,40 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# mkinstalldirs --- make directory hierarchy
|
||||||
|
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||||
|
# Created: 1993-05-16
|
||||||
|
# Public domain
|
||||||
|
|
||||||
|
# $Id$
|
||||||
|
|
||||||
|
errstatus=0
|
||||||
|
|
||||||
|
for file
|
||||||
|
do
|
||||||
|
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
|
||||||
|
shift
|
||||||
|
|
||||||
|
pathcomp=
|
||||||
|
for d
|
||||||
|
do
|
||||||
|
pathcomp="$pathcomp$d"
|
||||||
|
case "$pathcomp" in
|
||||||
|
-* ) pathcomp=./$pathcomp ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test ! -d "$pathcomp"; then
|
||||||
|
echo "mkdir $pathcomp"
|
||||||
|
|
||||||
|
mkdir "$pathcomp" || lasterr=$?
|
||||||
|
|
||||||
|
if test ! -d "$pathcomp"; then
|
||||||
|
errstatus=$lasterr
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
pathcomp="$pathcomp/"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $errstatus
|
||||||
|
|
||||||
|
# mkinstalldirs ends here
|
197
pbl/Makefile
Normal file
197
pbl/Makefile
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
srcdir = .
|
||||||
|
top_srcdir = ..
|
||||||
|
|
||||||
|
prefix = /usr/local
|
||||||
|
exec_prefix = ${prefix}
|
||||||
|
|
||||||
|
bindir = ${exec_prefix}/bin
|
||||||
|
sbindir = ${exec_prefix}/sbin
|
||||||
|
libexecdir = ${exec_prefix}/libexec
|
||||||
|
datadir = ${prefix}/share
|
||||||
|
sysconfdir = ${prefix}/etc
|
||||||
|
sharedstatedir = ${prefix}/com
|
||||||
|
localstatedir = ${prefix}/var
|
||||||
|
libdir = ${exec_prefix}/lib
|
||||||
|
infodir = ${prefix}/info
|
||||||
|
mandir = ${prefix}/man
|
||||||
|
includedir = ${prefix}/include
|
||||||
|
oldincludedir = /usr/include
|
||||||
|
|
||||||
|
DESTDIR =
|
||||||
|
|
||||||
|
pkgdatadir = $(datadir)/hello
|
||||||
|
pkglibdir = $(libdir)/hello
|
||||||
|
pkgincludedir = $(includedir)/hello
|
||||||
|
|
||||||
|
top_builddir = ..
|
||||||
|
|
||||||
|
ACLOCAL = aclocal-1.4
|
||||||
|
AUTOCONF = autoconf
|
||||||
|
AUTOMAKE = automake-1.4
|
||||||
|
AUTOHEADER = autoheader
|
||||||
|
|
||||||
|
INSTALL = /usr/bin/install -c
|
||||||
|
INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS)
|
||||||
|
INSTALL_DATA = ${INSTALL} -m 644
|
||||||
|
INSTALL_SCRIPT = ${INSTALL}
|
||||||
|
transform = s,x,x,
|
||||||
|
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
host_alias =
|
||||||
|
host_triplet = i686-pc-linux-gnu
|
||||||
|
AR = ar
|
||||||
|
AS = @AS@
|
||||||
|
CC = gcc
|
||||||
|
CHECK_CFLAGS =
|
||||||
|
CHECK_LIBS = -lcheck
|
||||||
|
CPP = gcc -E
|
||||||
|
CXX = g++
|
||||||
|
CXXCPP = g++ -E
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
ECHO = echo
|
||||||
|
EGREP = grep -E
|
||||||
|
EXEEXT =
|
||||||
|
F77 = g77
|
||||||
|
GCJ = @GCJ@
|
||||||
|
GCJFLAGS = @GCJFLAGS@
|
||||||
|
HAVE_LIB = @HAVE_LIB@
|
||||||
|
LIB = @LIB@
|
||||||
|
LIBTOOL = $(SHELL) $(top_builddir)/libtool
|
||||||
|
LN_S = ln -s
|
||||||
|
LTLIB = @LTLIB@
|
||||||
|
MAKEINFO = makeinfo
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = o
|
||||||
|
PACKAGE = hello
|
||||||
|
RANLIB = ranlib
|
||||||
|
RC = @RC@
|
||||||
|
STRIP = strip
|
||||||
|
VERSION = 0.1
|
||||||
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
|
CONFIG_HEADER = ../[config.h]
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
DIST_COMMON = Makefile.am Makefile.in
|
||||||
|
|
||||||
|
|
||||||
|
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
|
||||||
|
TAR = tar
|
||||||
|
GZIP_ENV = --best
|
||||||
|
all: all-redirect
|
||||||
|
.SUFFIXES:
|
||||||
|
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||||
|
cd $(top_srcdir) && $(AUTOMAKE) --gnu pbl/Makefile
|
||||||
|
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||||
|
cd $(top_builddir) \
|
||||||
|
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||||
|
|
||||||
|
tags: TAGS
|
||||||
|
TAGS:
|
||||||
|
|
||||||
|
|
||||||
|
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||||
|
|
||||||
|
subdir = pbl
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
here=`cd $(top_builddir) && pwd`; \
|
||||||
|
top_distdir=`cd $(top_distdir) && pwd`; \
|
||||||
|
distdir=`cd $(distdir) && pwd`; \
|
||||||
|
cd $(top_srcdir) \
|
||||||
|
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu pbl/Makefile
|
||||||
|
@for file in $(DISTFILES); do \
|
||||||
|
d=$(srcdir); \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||||
|
else \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
info-am:
|
||||||
|
info: info-am
|
||||||
|
dvi-am:
|
||||||
|
dvi: dvi-am
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
installcheck-am:
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-exec-am:
|
||||||
|
install-exec: install-exec-am
|
||||||
|
|
||||||
|
install-data-am:
|
||||||
|
install-data: install-data-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
install: install-am
|
||||||
|
uninstall-am:
|
||||||
|
uninstall: uninstall-am
|
||||||
|
all-am: Makefile
|
||||||
|
all-redirect: all-am
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||||
|
installdirs:
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||||
|
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
mostlyclean-am: mostlyclean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
clean-am: clean-generic mostlyclean-am
|
||||||
|
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
distclean-am: distclean-generic clean-am
|
||||||
|
-rm -f libtool
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
|
||||||
|
maintainer-clean-am: maintainer-clean-generic distclean-am
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
|
||||||
|
.PHONY: tags distdir info-am info dvi-am dvi check check-am \
|
||||||
|
installcheck-am installcheck install-exec-am install-exec \
|
||||||
|
install-data-am install-data install-am install uninstall-am uninstall \
|
||||||
|
all-redirect all-am all installdirs mostlyclean-generic \
|
||||||
|
distclean-generic clean-generic maintainer-clean-generic clean \
|
||||||
|
mostlyclean distclean maintainer-clean
|
||||||
|
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
0
pbl/Makefile.am
Normal file
0
pbl/Makefile.am
Normal file
176
pbl/jbhash.h
Normal file
176
pbl/jbhash.h
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/**
|
||||||
|
* header file for jb hash table structs
|
||||||
|
* Based on Peter Graf's pblhash, <http://mission.base.com/peter/source/>
|
||||||
|
* Jim Blomo <jim@xcf.berkeley.edu>
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __JBHASH_H__
|
||||||
|
#define __JBHASH_H__
|
||||||
|
|
||||||
|
#include <lladd/common.h>
|
||||||
|
#include <lladd/transactional.h>
|
||||||
|
|
||||||
|
/* #define JB_HASHTABLE_SIZE 79 */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
recordid store;
|
||||||
|
size_t keylen;
|
||||||
|
size_t datlen;
|
||||||
|
recordid next;
|
||||||
|
} jbHashItem_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int size;
|
||||||
|
recordid hashmap_record; /*[JB_HASHTABLE_SIZE]*/
|
||||||
|
recordid store;
|
||||||
|
jbHashItem_t *iterItem;
|
||||||
|
unsigned int iterIndex;
|
||||||
|
byte *iterData;
|
||||||
|
recordid* hashmap;
|
||||||
|
} jbHashTable_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jbHtCreate makes a new persistant hashtable
|
||||||
|
* @param xid transaction id
|
||||||
|
*
|
||||||
|
* @param size The number of hashbuckets. Currently, jbHash does not
|
||||||
|
* resize its bucket table, so it is important to set this number
|
||||||
|
* appropriately.
|
||||||
|
*
|
||||||
|
* @return pointer to hashtable, or NULL on error
|
||||||
|
*/
|
||||||
|
jbHashTable_t* jbHtCreate(int xid, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jbHtValid determins if a hashtable pointer is valid
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable you want to validate
|
||||||
|
* @return true if valid, false otherwise
|
||||||
|
*/
|
||||||
|
int jbHtValid(int xid, jbHashTable_t *ht);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a key/value pair
|
||||||
|
* makes a SHALLOW COPY of the data to keep in durable storage
|
||||||
|
* will REPLACE an existing entry with the same key
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable in which to insert
|
||||||
|
* @param key pointer to data serving as key
|
||||||
|
* @param keylen how much data to use from pointer
|
||||||
|
* @param dat data to insert
|
||||||
|
* @param datlen length data
|
||||||
|
* @return -1 on error, 0 on success
|
||||||
|
*/
|
||||||
|
int jbHtInsert(int xid, jbHashTable_t *ht, const byte *key, size_t keylen, const byte *dat, size_t datlen);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup a value with a key
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable in which to look
|
||||||
|
* @param key pointer to key data
|
||||||
|
* @param keylen length of key
|
||||||
|
* @param buf preallocated buffer in which to put data
|
||||||
|
* @return -1 if error occurs, including nothing found
|
||||||
|
*/
|
||||||
|
int jbHtLookup( int xid, jbHashTable_t *ht, const byte *key, size_t keylen, byte *buf );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete entry associated with key
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable in which to delete
|
||||||
|
* @param key pointer to key data
|
||||||
|
* @param keylen length of key
|
||||||
|
* @param buf if non-NULL, preallocated space to copy data from deleted key
|
||||||
|
* @return -1 on errors or not found, 0 if existing entry was deleted
|
||||||
|
*/
|
||||||
|
int jbHtRemove( int xid, jbHashTable_t *ht, const byte *key, size_t keylen, byte *buf );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start an iterator on the hash table
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable
|
||||||
|
* @param buf preallocated space to put data
|
||||||
|
* @return -1 for no data or error, 0 on success
|
||||||
|
*/
|
||||||
|
int jbHtFirst( int xid, jbHashTable_t *ht, byte *buf );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iterates to the next item
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable
|
||||||
|
* @param buf preallocated space to put data
|
||||||
|
* @return -1 for no data or error, 0 on success
|
||||||
|
*/
|
||||||
|
int jbHtNext( int xid, jbHashTable_t *ht, byte *buf );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get data for the place the iterator is currently in
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable
|
||||||
|
* @param buf preallocated space to put data
|
||||||
|
* @return -1 for no data or error, 0 on success
|
||||||
|
*/
|
||||||
|
int jbHtCurrent(int xid, jbHashTable_t *ht, byte *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get key for the place the iterator is currently in
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable
|
||||||
|
* @param buf preallocated space to put key
|
||||||
|
* @return -1 for no data or error, 0 on success
|
||||||
|
*/
|
||||||
|
int jbHtCurrentKey(int xid, jbHashTable_t *ht, byte *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a hashtable
|
||||||
|
* table must be empty
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable to delete
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int jbHtDelete(int xid, jbHashTable_t *ht);
|
||||||
|
|
||||||
|
#endif
|
549
pbl/pbl.h
Normal file
549
pbl/pbl.h
Normal file
|
@ -0,0 +1,549 @@
|
||||||
|
#ifndef _PBL_H_
|
||||||
|
#define _PBL_H_
|
||||||
|
/*
|
||||||
|
pbl.h - external include file of library
|
||||||
|
|
||||||
|
Copyright (C) 2002 Peter Graf
|
||||||
|
|
||||||
|
This file is part of PBL - The Program Base Library.
|
||||||
|
PBL is free software.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
For more information on the Program Base Library or Peter Graf,
|
||||||
|
please see: http://mission.base.com/.
|
||||||
|
|
||||||
|
$Log$
|
||||||
|
Revision 1.1 2004/06/24 21:11:33 sears
|
||||||
|
Initial revision
|
||||||
|
|
||||||
|
Revision 1.4 2004/06/09 21:27:40 sears
|
||||||
|
Final CVS checkin before major refactoring.
|
||||||
|
|
||||||
|
Revision 1.3 2003/12/11 10:48:16 jim
|
||||||
|
compiles, not link. added quasi-pincount, shadow pages
|
||||||
|
|
||||||
|
Revision 1.2 2003/12/11 09:21:20 jim
|
||||||
|
update includes
|
||||||
|
|
||||||
|
Revision 1.1 2003/12/11 09:10:48 jim
|
||||||
|
pbl
|
||||||
|
|
||||||
|
Revision 1.2 2002/09/12 20:47:18 peter
|
||||||
|
added the isam file handling to the library
|
||||||
|
|
||||||
|
Revision 1.1 2002/09/05 13:44:12 peter
|
||||||
|
Initial revision
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make sure "strings <exe> | grep Id | sort -u" shows the source file versions
|
||||||
|
*/
|
||||||
|
static char* _PBL_H_id = "$Id$";
|
||||||
|
static int _PBL_H_fct() { return( _PBL_H_id ? 0 : _PBL_H_fct() ); }
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* #defines */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
/*
|
||||||
|
* some functions have strange names on windows
|
||||||
|
*/
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
#define strncasecmp _strnicmp
|
||||||
|
#define snprintf _snprintf
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef O_BINARY
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PBL_ERRSTR_LEN 2048
|
||||||
|
|
||||||
|
/** @name B: Files
|
||||||
|
* list of files of component
|
||||||
|
* <P>
|
||||||
|
* <B>FILES</B>
|
||||||
|
* <UL>
|
||||||
|
* <LI> <a href="../pbl.h">pbl.h</a> - the include file of the library
|
||||||
|
* <LI> <a href="../pbl.c">pbl.c</a> - source for the base functions
|
||||||
|
* <LI> <a href="../pblhash.c">pblhash.c</a> - source file for the
|
||||||
|
* hash functions
|
||||||
|
* <LI> <a href="../pblhttst.c">pblhttst.c</a> - source file for the
|
||||||
|
* hash function test frame
|
||||||
|
* <LI> <a href="../pblkf.c">pblkf.c</a> - source file for the key
|
||||||
|
* file functions
|
||||||
|
* <LI> <a href="../pblkftst.c">pblkftst.c</a> - source file for the
|
||||||
|
* key file handling test frame
|
||||||
|
* <LI> <a href="../pblisam.c">pblisam.c</a> - source file for the isam
|
||||||
|
* file functions
|
||||||
|
* <LI> <a href="../pbliftst.c">pbliftst.c</a> - source file for the
|
||||||
|
* isam file handling test frame
|
||||||
|
* <LI> <a href="../makefile">makefile</a> - a Unix makefile for the
|
||||||
|
* component
|
||||||
|
* <LI> <a href="../pblhttstdeb.dsp">pblhttstdeb.dsp</a> - a Microsoft Visual
|
||||||
|
* Studio 6.0 project file for
|
||||||
|
* hash table debug
|
||||||
|
* <LI> <a href="../pblkftstdeb.dsp">pblkftstdeb.dsp</a> - a Microsoft
|
||||||
|
* Visual Studio 6.0 project file
|
||||||
|
* for key file debug
|
||||||
|
* <LI> <a href="../pbliftstdeb.dsp">pbliftstdeb.dsp</a> - a Microsoft Visual
|
||||||
|
* Studio 6.0 project file for
|
||||||
|
* isam file debug
|
||||||
|
* <LI> <a href="../ISAM0001.LOG">ISAM0001.LOG</a> - a test case for the
|
||||||
|
* isam file handling test frame
|
||||||
|
* <LI> <a href="../pbl.dxx">pbl.dxx</a> - the source for this document
|
||||||
|
* </UL>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PBL_FILE_LIST
|
||||||
|
|
||||||
|
/** @name C: Error codes
|
||||||
|
* error codes of the pbl library
|
||||||
|
*
|
||||||
|
* @field PBL_ERROR_OUT_OF_MEMORY out of memory
|
||||||
|
* @field PBL_ERROR_EXISTS record already exists
|
||||||
|
* @field PBL_ERROR_NOT_FOUND record not found
|
||||||
|
* @field PBL_ERROR_BAD_FILE file structure damaged
|
||||||
|
* @field PBL_ERROR_PARAM_MODE parameter mode is not valid
|
||||||
|
* @field PBL_ERROR_PARAM_KEY parameter key is not valid
|
||||||
|
* @field PBL_ERROR_PARAM_KEYLEN parameter keylen is not valid
|
||||||
|
* @field PBL_ERROR_PARAM_DATA parameter data is not valid
|
||||||
|
* @field PBL_ERROR_PARAM_DATALEN parameter datalen is not valid
|
||||||
|
* @field PBL_ERROR_PARAM_INDEX parameter index is not valid
|
||||||
|
* @field PBL_ERROR_CREATE file system create error, see errno
|
||||||
|
* @field PBL_ERROR_OPEN file system open error, see errno
|
||||||
|
* @field PBL_ERROR_SEEK file system seek error, see errno
|
||||||
|
* @field PBL_ERROR_READ file system read error, see errno
|
||||||
|
* @field PBL_ERROR_WRITE file system write error, see errno
|
||||||
|
* @field PBL_ERROR_PROGRAM an internal error in the code, debug it!!
|
||||||
|
* @field PBL_ERROR_NOFIT internal error forcing a block split
|
||||||
|
* @field PBL_ERROR_NOT_ALLOWED file not open for update, operation not allowed
|
||||||
|
* @field PBL_ERROR_POSITION current record is not positioned
|
||||||
|
*/
|
||||||
|
#define PBL_ERROR_BASE 1000
|
||||||
|
|
||||||
|
#define PBL_ERROR_OUT_OF_MEMORY ( PBL_ERROR_BASE + 1 )
|
||||||
|
#define PBL_ERROR_EXISTS ( PBL_ERROR_BASE + 2 )
|
||||||
|
#define PBL_ERROR_NOT_FOUND ( PBL_ERROR_BASE + 3 )
|
||||||
|
#define PBL_ERROR_BAD_FILE ( PBL_ERROR_BASE + 4 )
|
||||||
|
#define PBL_ERROR_PARAM_MODE ( PBL_ERROR_BASE + 5 )
|
||||||
|
#define PBL_ERROR_PARAM_KEY ( PBL_ERROR_BASE + 6 )
|
||||||
|
#define PBL_ERROR_PARAM_KEYLEN ( PBL_ERROR_BASE + 7 )
|
||||||
|
#define PBL_ERROR_PARAM_DATA ( PBL_ERROR_BASE + 8 )
|
||||||
|
#define PBL_ERROR_PARAM_DATALEN ( PBL_ERROR_BASE + 9 )
|
||||||
|
#define PBL_ERROR_PARAM_INDEX ( PBL_ERROR_BASE + 10 )
|
||||||
|
|
||||||
|
#define PBL_ERROR_CREATE ( PBL_ERROR_BASE + 20 )
|
||||||
|
#define PBL_ERROR_OPEN ( PBL_ERROR_BASE + 21 )
|
||||||
|
#define PBL_ERROR_SEEK ( PBL_ERROR_BASE + 22 )
|
||||||
|
#define PBL_ERROR_READ ( PBL_ERROR_BASE + 23 )
|
||||||
|
#define PBL_ERROR_WRITE ( PBL_ERROR_BASE + 24 )
|
||||||
|
|
||||||
|
#define PBL_ERROR_PROGRAM ( PBL_ERROR_BASE + 30 )
|
||||||
|
#define PBL_ERROR_NOFIT ( PBL_ERROR_BASE + 31 )
|
||||||
|
|
||||||
|
#define PBL_ERROR_NOT_ALLOWED ( PBL_ERROR_BASE + 40 )
|
||||||
|
#define PBL_ERROR_POSITION ( PBL_ERROR_BASE + 41 )
|
||||||
|
|
||||||
|
/** @name D: Definitions for Key File Parameters
|
||||||
|
* DEFINES FOR PARAMETER <B> mode </B> OF \Ref{pblKfFind}()
|
||||||
|
* @field PBLEQ any record that is equal
|
||||||
|
* @field PBLFI first record that is equal
|
||||||
|
* @field PBLLA last record that is equal
|
||||||
|
* @field PBLGE last equal or first that is greater
|
||||||
|
* @field PBLGT first that is greater
|
||||||
|
* @field PBLLE first equal or last that is smaller
|
||||||
|
* @field PBLLT last that is smaller
|
||||||
|
*/
|
||||||
|
#define PBLEQ 1
|
||||||
|
#define PBLFI 2
|
||||||
|
#define PBLLA 3
|
||||||
|
#define PBLGE 4
|
||||||
|
#define PBLGT 5
|
||||||
|
#define PBLLE 6
|
||||||
|
#define PBLLT 7
|
||||||
|
|
||||||
|
/** @name E: Definitions for ISAM Parameters
|
||||||
|
* DEFINES FOR PARAMETER <B> which </B> OF \Ref{pblIsamGet}()
|
||||||
|
* @field PBLTHIS get key and keylen of current record
|
||||||
|
* @field PBLNEXT get key and keylen of next record
|
||||||
|
* @field PBLPREV get key and keylen of previous record
|
||||||
|
* @field PBLFIRST get key and keylen of first record
|
||||||
|
* @field PBLLAST get key and keylen of last record
|
||||||
|
*/
|
||||||
|
#define PBLTHIS 1
|
||||||
|
#define PBLNEXT 2
|
||||||
|
#define PBLPREV 3
|
||||||
|
#define PBLFIRST 4
|
||||||
|
#define PBLLAST 5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the maximum length of a key of the key file component,
|
||||||
|
* @doc maximum length of a key, 255 for now
|
||||||
|
*/
|
||||||
|
#define PBLKEYLENGTH 255
|
||||||
|
|
||||||
|
/**
|
||||||
|
* maximum data length of data being stored on index blocks of key files,
|
||||||
|
* @doc maximum length of data stored with an item on the level 0 block, 1024
|
||||||
|
* @doc data that is longer is stored on data blocks.
|
||||||
|
*/
|
||||||
|
#define PBLDATALENGTH 1024
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* macros */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The PBL_MEMTRACE define can be used for debugging the library,
|
||||||
|
* if defined the library will log a line for all memory chunks
|
||||||
|
* that are allocated for more than 3 minutes into the file ./pblmemtrace.log
|
||||||
|
*
|
||||||
|
* This can be used to detect heap memory lost by the code.
|
||||||
|
* See also function pbl_memtrace_out in pbl.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #define PBL_MEMTRACE */
|
||||||
|
#ifdef PBL_MEMTRACE
|
||||||
|
|
||||||
|
extern void pbl_memtrace_delete( void * data );
|
||||||
|
extern void pbl_memtrace_out( int checktime );
|
||||||
|
|
||||||
|
#define PBL_FREE( ptr ) if( ptr ){ pbl_memtrace_delete( ptr );\
|
||||||
|
free( ptr ); ptr = 0; }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/**
|
||||||
|
* make free save against NULL pointers,
|
||||||
|
* @doc also the parameter ptr is set to NULL
|
||||||
|
*/
|
||||||
|
#define PBL_FREE( ptr ) if( ptr ){ free( ptr ); ptr = 0; }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* macros for linear list handling,
|
||||||
|
*/
|
||||||
|
#define PBL_LIST_( Parameters )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* push an element to the beginning of a linear list
|
||||||
|
*/
|
||||||
|
#define PBL_LIST_PUSH( HEAD, TAIL, ITEM, NEXT, PREV )\
|
||||||
|
{\
|
||||||
|
(ITEM)->PREV = 0;\
|
||||||
|
if(( (ITEM)->NEXT = (HEAD) ))\
|
||||||
|
{ (ITEM)->NEXT->PREV = (ITEM); }\
|
||||||
|
else\
|
||||||
|
{ (TAIL) = (ITEM); }\
|
||||||
|
(HEAD) = (ITEM);\
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* append an element to the end of a linear list
|
||||||
|
*/
|
||||||
|
#define PBL_LIST_APPEND( HEAD, TAIL, ITEM, NEXT, PREV )\
|
||||||
|
PBL_LIST_PUSH( TAIL, HEAD, ITEM, PREV, NEXT )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove an element from a linear list
|
||||||
|
*/
|
||||||
|
#define PBL_LIST_UNLINK( HEAD, TAIL, ITEM, NEXT, PREV )\
|
||||||
|
{\
|
||||||
|
if( (ITEM)->NEXT )\
|
||||||
|
{ (ITEM)->NEXT->PREV = (ITEM)->PREV; }\
|
||||||
|
else\
|
||||||
|
{ (TAIL) = (ITEM)->PREV; }\
|
||||||
|
if( (ITEM)->PREV )\
|
||||||
|
{ (ITEM)->PREV->NEXT = (ITEM)->NEXT; }\
|
||||||
|
else\
|
||||||
|
{ (HEAD) = (ITEM)->NEXT; }\
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SOME MACROS FOR KEY FILE READ FUNCTIONS
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* set the current record to the first record of the file
|
||||||
|
*/
|
||||||
|
#define pblKfFirst( KF, K, L ) pblKfGetAbs( KF, 0, K, L )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the current record to the last record of the file
|
||||||
|
*/
|
||||||
|
#define pblKfLast( KF, K, L ) pblKfGetAbs( KF, -1, K, L )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the current record to the next record of the file
|
||||||
|
*/
|
||||||
|
#define pblKfNext( KF, K, L ) pblKfGetRel( KF, 1, K, L )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the current record to the previous record of the file
|
||||||
|
*/
|
||||||
|
#define pblKfPrev( KF, K, L ) pblKfGetRel( KF, -1, K, L )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return the datalen of the current record
|
||||||
|
*/
|
||||||
|
#define pblKfThis( KF, K, L ) pblKfGetRel( KF, 0, K, L )
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* typedefs */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
struct pblHashTable_s
|
||||||
|
{
|
||||||
|
char * magic;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the hash table type the pblHt* functions are dealing with,
|
||||||
|
* @doc the details of the structure are hidden from the user
|
||||||
|
*/
|
||||||
|
typedef struct pblHashTable_s pblHashTable_t;
|
||||||
|
|
||||||
|
struct pblKeyFile_s
|
||||||
|
{
|
||||||
|
char * magic;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the key file type the pblKf* functions are dealing with,
|
||||||
|
* @doc the details of the structure are hidden from the user
|
||||||
|
*/
|
||||||
|
typedef struct pblKeyFile_s pblKeyFile_t;
|
||||||
|
|
||||||
|
struct pblIsamFile_s
|
||||||
|
{
|
||||||
|
char * magic;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the ISAM file type the pblIsam* functions are dealing with,
|
||||||
|
* @doc the details of the structure are hidden from the user
|
||||||
|
*/
|
||||||
|
typedef struct pblIsamFile_s pblIsamFile_t;
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* variable declarations */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* integer value used for returning error codes
|
||||||
|
*/
|
||||||
|
extern int pbl_errno;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* character buffer used for returning error strings
|
||||||
|
*/
|
||||||
|
extern char * pbl_errstr;
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* function declarations */
|
||||||
|
/*****************************************************************************/
|
||||||
|
extern void * pbl_malloc( char * tag, size_t size );
|
||||||
|
extern void * pbl_malloc0( char * tag, size_t size );
|
||||||
|
extern void * pbl_memdup( char * tag, void * data, size_t size );
|
||||||
|
extern void * pbl_mem2dup( char * tag, void * mem1, size_t len1,
|
||||||
|
void * mem2, size_t len2 );
|
||||||
|
extern int pbl_memcmplen( void * left, size_t llen,
|
||||||
|
void * right, size_t rlen );
|
||||||
|
extern int pbl_memcmp( void * left, size_t llen, void * right, size_t rlen );
|
||||||
|
extern size_t pbl_memlcpy( void * to, size_t tolen, void * from, size_t n );
|
||||||
|
|
||||||
|
extern void pbl_ShortToBuf( unsigned char * buf, int s );
|
||||||
|
extern int pbl_BufToShort( unsigned char * buf );
|
||||||
|
extern void pbl_LongToBuf( unsigned char * buf, long l );
|
||||||
|
extern long pbl_BufToLong( unsigned char * buf );
|
||||||
|
extern int pbl_LongToVarBuf( unsigned char * buffer, unsigned long value );
|
||||||
|
extern int pbl_VarBufToLong( unsigned char * buffer, long * value );
|
||||||
|
extern int pbl_LongSize( unsigned long value );
|
||||||
|
extern int pbl_VarBufSize( unsigned char * buffer );
|
||||||
|
|
||||||
|
extern pblHashTable_t * pblHtCreate( );
|
||||||
|
extern int pblHtInsert ( pblHashTable_t * h, void * key, size_t keylen,
|
||||||
|
void * dataptr);
|
||||||
|
extern void * pblHtLookup ( pblHashTable_t * h, void * key, size_t keylen );
|
||||||
|
extern void * pblHtFirst ( pblHashTable_t * h );
|
||||||
|
extern void * pblHtNext ( pblHashTable_t * h );
|
||||||
|
extern void * pblHtCurrent ( pblHashTable_t * h );
|
||||||
|
extern void * pblHtCurrentKey ( pblHashTable_t * h );
|
||||||
|
extern int pblHtRemove ( pblHashTable_t * h, void * key, size_t keylen );
|
||||||
|
extern int pblHtDelete ( pblHashTable_t * h );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTIONS ON KEY FILES
|
||||||
|
*/
|
||||||
|
int pblKfInit ( int nblocks );
|
||||||
|
extern pblKeyFile_t * pblKfCreate( char * path, void * filesettag );
|
||||||
|
extern pblKeyFile_t * pblKfOpen ( char * path, int update, void * filesettag );
|
||||||
|
extern int pblKfClose ( pblKeyFile_t * k );
|
||||||
|
extern int pblKfFlush ( pblKeyFile_t * k );
|
||||||
|
extern int pblKfStartTransaction( pblKeyFile_t * k );
|
||||||
|
extern int pblKfCommit( pblKeyFile_t * k, int rollback );
|
||||||
|
extern int pblKfSavePosition( pblKeyFile_t * k );
|
||||||
|
extern int pblKfRestorePosition( pblKeyFile_t * k );
|
||||||
|
|
||||||
|
extern void pblKfSetCompareFunction(
|
||||||
|
pblKeyFile_t * k, /** key file to set compare function for */
|
||||||
|
int ( *keycompare ) /** compare function to set */
|
||||||
|
(
|
||||||
|
void* left, /** "left" buffer for compare */ size_t llen, /** length of that buffer */ void* right, /** "right" buffer for compare */ size_t rlen /** length of that buffer */
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WRITE FUNCTIONS ON RECORDS, DELETE AND UPDATE WORK ON CURRENT RECORD
|
||||||
|
*/
|
||||||
|
extern int pblKfInsert(
|
||||||
|
pblKeyFile_t * k,
|
||||||
|
unsigned char * key,
|
||||||
|
int keylen,
|
||||||
|
unsigned char * data,
|
||||||
|
long datalen
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int pblKfDelete( pblKeyFile_t * k );
|
||||||
|
|
||||||
|
extern int pblKfUpdate(
|
||||||
|
pblKeyFile_t * k,
|
||||||
|
unsigned char * data,
|
||||||
|
long datalen
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* KEY FILE READ FUNCTIONS ON RECORDS
|
||||||
|
*/
|
||||||
|
extern long pblKfFind(
|
||||||
|
pblKeyFile_t * k,
|
||||||
|
int mode,
|
||||||
|
unsigned char * skey,
|
||||||
|
int skeylen,
|
||||||
|
unsigned char * okey,
|
||||||
|
int * okeylen
|
||||||
|
);
|
||||||
|
|
||||||
|
extern long pblKfRead(
|
||||||
|
pblKeyFile_t * k,
|
||||||
|
unsigned char * data,
|
||||||
|
long datalen
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTIONS ACTUALLY ONLY TO BE USED THROUGH THE MAKROS DEFINED BELOW
|
||||||
|
*
|
||||||
|
* however, the functions work, but they are not very fast
|
||||||
|
*
|
||||||
|
* pblKfGetRel - positions relative to the current record to any other
|
||||||
|
* record of the file, interface is like pblKfNext
|
||||||
|
*
|
||||||
|
* pblKfGetAbs - positions absolute to the absindex 'th record of the file,
|
||||||
|
* -1L means last, interface is like pblKfFirst
|
||||||
|
*/
|
||||||
|
extern long pblKfGetRel( pblKeyFile_t * k, long relindex,
|
||||||
|
char *okey, int *okeylen);
|
||||||
|
extern long pblKfGetAbs( pblKeyFile_t * k, long absindex,
|
||||||
|
char *okey, int *okeylen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTIONS ON ISAM FILES
|
||||||
|
*/
|
||||||
|
extern int pblIsamClose( pblIsamFile_t * isamfile );
|
||||||
|
extern int pblIsamFlush( pblIsamFile_t * isamfile );
|
||||||
|
extern int pblIsamDelete( pblIsamFile_t * isamfile );
|
||||||
|
|
||||||
|
extern pblIsamFile_t * pblIsamOpen(
|
||||||
|
char * path,
|
||||||
|
int update,
|
||||||
|
void * filesettag,
|
||||||
|
int nkeys,
|
||||||
|
char ** keyfilenames,
|
||||||
|
int * keydup
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int pblIsamInsert(
|
||||||
|
pblIsamFile_t * isamfile,
|
||||||
|
unsigned char * allkeys,
|
||||||
|
int allkeyslen,
|
||||||
|
unsigned char * data,
|
||||||
|
long datalen
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int pblIsamFind(
|
||||||
|
pblIsamFile_t * isamfile,
|
||||||
|
int mode,
|
||||||
|
int index,
|
||||||
|
unsigned char * skey,
|
||||||
|
int skeylen,
|
||||||
|
unsigned char * okey
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int pblIsamGet(
|
||||||
|
pblIsamFile_t * isamfile,
|
||||||
|
int which,
|
||||||
|
int index,
|
||||||
|
unsigned char * okey
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int pblIsamReadKey(
|
||||||
|
pblIsamFile_t * isamfile,
|
||||||
|
int index,
|
||||||
|
unsigned char * okey
|
||||||
|
);
|
||||||
|
|
||||||
|
extern long pblIsamReadDatalen( pblIsamFile_t * isamfile );
|
||||||
|
|
||||||
|
extern long pblIsamReadData(
|
||||||
|
pblIsamFile_t * isamfile,
|
||||||
|
unsigned char * buffer,
|
||||||
|
long bufferlen
|
||||||
|
);
|
||||||
|
|
||||||
|
extern long pblIsamUpdateData(
|
||||||
|
pblIsamFile_t * isamfile,
|
||||||
|
unsigned char * data,
|
||||||
|
long datalen
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int pblIsamUpdateKey(
|
||||||
|
pblIsamFile_t * isamfile,
|
||||||
|
int index,
|
||||||
|
unsigned char * ukey,
|
||||||
|
int ukeylen
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int pblIsamStartTransaction( int nfiles, pblIsamFile_t ** isamfiles );
|
||||||
|
extern int pblIsamCommit( int nfiles, pblIsamFile_t ** isamfiles, int rollback);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
11
reconf
Executable file
11
reconf
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/sh
|
||||||
|
rm -f config.cache
|
||||||
|
rm -f acconfig.h
|
||||||
|
#touch acconfig.h
|
||||||
|
#aclocal -I m4
|
||||||
|
aclocal
|
||||||
|
autoconf
|
||||||
|
autoheader
|
||||||
|
#acconfig
|
||||||
|
automake -a
|
||||||
|
exit
|
285
src/2pc/2pc.c
Normal file
285
src/2pc/2pc.c
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 "2pc.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../libdfa/callbacks.h"
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
/* #define _TWO_PC 1 */
|
||||||
|
|
||||||
|
const int transition_count_2pc = 14;
|
||||||
|
const int client_transition_count_2pc = 4;
|
||||||
|
const int state_count_2pc = 9;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
callback_fcn check_veto_2pc;
|
||||||
|
callback_fcn tally_2pc;
|
||||||
|
callback_fcn send_ack_2pc;
|
||||||
|
callback_fcn coordinator_init_xact_2pc;
|
||||||
|
callback_fcn veto_or_prepare_2pc;
|
||||||
|
callback_fcn abort_2pc;
|
||||||
|
callback_fcn commit_2pc;
|
||||||
|
|
||||||
|
|
||||||
|
/* Remember to update transition_count_2pc if you add/remove transitions */
|
||||||
|
Transition transitions_2pc[] = {
|
||||||
|
|
||||||
|
/* Coordinator transitions */
|
||||||
|
|
||||||
|
/* Library user must provide callback that init_xact_2pc calls. */
|
||||||
|
{ AWAIT_ARRIVAL, NULL_STATE, COORDINATOR_START_2PC, coordinator_init_xact_2pc, FALSE },
|
||||||
|
{ AWAIT_COMMIT_POINT, NULL_STATE, COORDINATOR_START_2PC, coordinator_init_xact_2pc, FALSE },
|
||||||
|
{ AWAIT_RESULT, NULL_STATE, COORDINATOR_START_2PC, coordinator_init_xact_2pc, FALSE },
|
||||||
|
{ NULL_STATE, NULL_STATE, COORDINATOR_START_2PC, coordinator_init_xact_2pc, FALSE },
|
||||||
|
|
||||||
|
/* TODO: tally_2pc and check_veto_2pc should respond to initiator where applicable. */
|
||||||
|
{ SUBORDINATE_VETO_2PC, COORDINATOR_START_2PC, COORDINATOR_ABORTING_2PC, &check_veto_2pc, TRUE },
|
||||||
|
{ SUBORDINATE_PREPARED_2PC, COORDINATOR_START_2PC, COORDINATOR_COMMITTING_2PC, &tally_2pc, TRUE },
|
||||||
|
{ SUBORDINATE_ACKING_2PC, COORDINATOR_ABORTING_2PC, NULL_STATE, &tally_2pc, FALSE},
|
||||||
|
{ SUBORDINATE_ACKING_2PC, COORDINATOR_COMMITTING_2PC, NULL_STATE, &tally_2pc, FALSE},
|
||||||
|
|
||||||
|
/* Subordinate transitions */
|
||||||
|
/* veto_or_prepare overrides target state. */
|
||||||
|
|
||||||
|
/* Library user must provide the subordinate function pointers for these transitions */
|
||||||
|
{ COORDINATOR_START_2PC, NULL_STATE, OVERRIDDEN_STATE, &veto_or_prepare_2pc, TRUE },
|
||||||
|
{ COORDINATOR_ABORTING_2PC, SUBORDINATE_PREPARED_2PC, NULL_STATE, &abort_2pc, FALSE},
|
||||||
|
{ COORDINATOR_COMMITTING_2PC, SUBORDINATE_PREPARED_2PC, NULL_STATE, &commit_2pc, FALSE},
|
||||||
|
{ COORDINATOR_ABORTING_2PC, SUBORDINATE_VETO_2PC, NULL_STATE, NULL, FALSE},
|
||||||
|
|
||||||
|
/* transition fcn always fails, but sends ack to coordinator */
|
||||||
|
{ COORDINATOR_COMMITTING_2PC, NULL_STATE, OVERRIDDEN_STATE, &send_ack_2pc, TRUE},
|
||||||
|
{ COORDINATOR_ABORTING_2PC, NULL_STATE, OVERRIDDEN_STATE, &send_ack_2pc, TRUE},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Transition client_transitions_2pc[] = {
|
||||||
|
|
||||||
|
/* Caller transitions */
|
||||||
|
|
||||||
|
{ COORDINATOR_START_2PC, AWAIT_ARRIVAL, NULL_STATE, NULL, FALSE},
|
||||||
|
|
||||||
|
{ COORDINATOR_COMMITTING_2PC, AWAIT_COMMIT_POINT, NULL_STATE, NULL, FALSE},
|
||||||
|
{ COORDINATOR_ABORTING_2PC, AWAIT_COMMIT_POINT, NULL_STATE, NULL, FALSE},
|
||||||
|
|
||||||
|
{ SUBORDINATE_ACKING_2PC, AWAIT_RESULT, NULL_STATE, NULL, FALSE},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
State states_2pc[MAX_STATE_COUNT] = {
|
||||||
|
|
||||||
|
/* Coordinator states */
|
||||||
|
|
||||||
|
{ COORDINATOR_START_2PC, NULL, NULL }, /* Need abort fcn */
|
||||||
|
{ COORDINATOR_COMMITTING_2PC, NULL, NULL },
|
||||||
|
{ COORDINATOR_ABORTING_2PC, NULL, NULL },
|
||||||
|
|
||||||
|
/* Subordinate states */
|
||||||
|
|
||||||
|
{ SUBORDINATE_VETO_2PC, NULL, NULL }, /* Need to think about callback fcns */
|
||||||
|
{ SUBORDINATE_PREPARED_2PC, NULL, NULL },
|
||||||
|
{ SUBORDINATE_ACKING_2PC, NULL, NULL },
|
||||||
|
|
||||||
|
/* Client states */
|
||||||
|
|
||||||
|
{ AWAIT_ARRIVAL, NULL, NULL},
|
||||||
|
{ AWAIT_RESULT, NULL, NULL},
|
||||||
|
{ AWAIT_COMMIT_POINT, NULL, NULL},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
- add broadcast to messages.h (Done)
|
||||||
|
- change libdfa so that it scans the states array (Done)
|
||||||
|
- add support for OVERRIDDEN_STATE to libdfa (Done, test it)
|
||||||
|
- add support for transactions to libdfa (Need to replace monotree)
|
||||||
|
- write the callback fcns. (~Done, test it!)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Probably should ack the client that called commit(), instead of
|
||||||
|
hoping that UDP got it here for them... ;) So, they should have a
|
||||||
|
state machine that initiated the transaction, and waits for an ACK
|
||||||
|
or NAK from us. */
|
||||||
|
state_name coordinator_init_xact_2pc(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
TwoPCMachineState * state = (TwoPCMachineState*) &(stateMachine->app_state);
|
||||||
|
TwoPCAppState * app_state = ((TwoPCAppState*)(((DfaSet*)dfaSet)->app_setup));
|
||||||
|
short bc_group = app_state->get_broadcast_group(dfaSet, m);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(!app_state->is_coordinator) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("bc_group %d\n", bc_group);
|
||||||
|
|
||||||
|
/* Need to check for this somewhere... */
|
||||||
|
assert(sizeof(TwoPCAppState) <= MAX_APP_STATE_SIZE);
|
||||||
|
|
||||||
|
memset(state->subordinate_votes, 0, MAX_SUBORDINATES);
|
||||||
|
/* state->xid = m->from_machine_id; */
|
||||||
|
state->xid = stateMachine->machine_id;
|
||||||
|
printf("From: %s", from);
|
||||||
|
/*strncpy(state->initiator, from, MAX_ADDRESS_LENGTH);*/
|
||||||
|
|
||||||
|
sprintf(from, "bc:%d\n", bc_group);
|
||||||
|
|
||||||
|
/* TODO: (n)ack the client. (Implies yes / no / already pending return values for callback on last line)
|
||||||
|
Currently, this is handled by the library user. It could be moved back into here.
|
||||||
|
|
||||||
|
*/
|
||||||
|
if(app_state->init_xact_2pc != NULL) {
|
||||||
|
ret = app_state->init_xact_2pc(dfaSet, stateMachine, m, from);
|
||||||
|
} else {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
/* Where was this before?? */
|
||||||
|
m->from_machine_id = stateMachine->machine_id;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
state_name send_ack_2pc(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
respond_once(&((DfaSet*)dfaSet)->networkSetup, SUBORDINATE_ACKING_2PC, m, from);
|
||||||
|
return OVERRIDDEN_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
TODO: Can this be done in a way that avoids blocking?
|
||||||
|
*/
|
||||||
|
state_name veto_or_prepare_2pc(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
TwoPCAppState * app_state = ((TwoPCAppState*)(((DfaSet*)dfaSet)->app_setup));
|
||||||
|
|
||||||
|
return app_state->veto_or_prepare_2pc(dfaSet, stateMachine, m, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
TODO: The next two functions should fork and immediately return true.
|
||||||
|
*/
|
||||||
|
|
||||||
|
state_name abort_2pc(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
TwoPCAppState * app_state = ((TwoPCAppState*)(((DfaSet*)dfaSet)->app_setup));
|
||||||
|
|
||||||
|
send_ack_2pc(dfaSet, stateMachine, m, from);
|
||||||
|
|
||||||
|
return app_state->abort_2pc(dfaSet, stateMachine, m, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
state_name commit_2pc(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
TwoPCAppState * app_state = ((TwoPCAppState*)(((DfaSet*)dfaSet)->app_setup));
|
||||||
|
|
||||||
|
send_ack_2pc(dfaSet, stateMachine, m, from);
|
||||||
|
return app_state->commit_2pc(dfaSet, stateMachine, m, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
state_name check_veto_2pc(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
/* Clear subordinate_votes array, so that it can be used to
|
||||||
|
tally acks after the votes are tallied. */
|
||||||
|
|
||||||
|
TwoPCAppState * app_state = ((TwoPCAppState*)(((DfaSet*)dfaSet)->app_setup));
|
||||||
|
TwoPCMachineState * machine_state = (TwoPCMachineState*)&(stateMachine->app_state);
|
||||||
|
|
||||||
|
/* if (!check_from()) { return 0; } */
|
||||||
|
short bc_group = app_state->get_broadcast_group(dfaSet, m);
|
||||||
|
|
||||||
|
printf("bc_group:veto %d\n", bc_group);
|
||||||
|
|
||||||
|
memset(machine_state->subordinate_votes, 0, MAX_SUBORDINATES);
|
||||||
|
sprintf(from, "bc:%d", bc_group);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_name tally_2pc(void * dfaSetPtr, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
|
||||||
|
TwoPCMachineState * machine_state = (TwoPCMachineState*)&(stateMachine->app_state);
|
||||||
|
DfaSet * dfaSet = (DfaSet*) dfaSetPtr;
|
||||||
|
|
||||||
|
TwoPCAppState * app_state = ((TwoPCAppState*)(((DfaSet*)dfaSet)->app_setup));
|
||||||
|
|
||||||
|
/* if (!check_from()) { return 0; } */
|
||||||
|
short bc_group = app_state->get_broadcast_group(dfaSet, m);
|
||||||
|
|
||||||
|
if(bc_group < dfaSet->networkSetup.broadcast_lists_count) {
|
||||||
|
state_name ret = tally(dfaSet->networkSetup.broadcast_lists[bc_group],
|
||||||
|
dfaSet->networkSetup.broadcast_list_host_count[bc_group],
|
||||||
|
(char*)(machine_state->subordinate_votes), from);
|
||||||
|
if(ret) {
|
||||||
|
/* Clear subordinate_votes array, so that it can be used to
|
||||||
|
tally acks after the votes are tallied. */
|
||||||
|
memset(machine_state->subordinate_votes, 0, MAX_SUBORDINATES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Needed to use the from variable to do the tally, so this
|
||||||
|
sprintf needs to be down here. */
|
||||||
|
|
||||||
|
sprintf(from, "bc:%d", bc_group);
|
||||||
|
|
||||||
|
if(ret && app_state->tally_2pc != NULL) {
|
||||||
|
return app_state->tally_2pc(dfaSet, stateMachine, m, from);
|
||||||
|
} else {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sprintf(from, "bc:%d", bc_group);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
153
src/2pc/2pc.h
Normal file
153
src/2pc/2pc.h
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <libdfa/libdfa.h>
|
||||||
|
|
||||||
|
#define MAX_SUBORDINATES 10
|
||||||
|
|
||||||
|
/** To use this library, you need to implement:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> get_broadcast_group, which maps from message to broadcast group.
|
||||||
|
<li> prepare_or_veto_2pc, which, given a message, returns SUBORDINATE_VETO_2PC or SUBORDINATE_PREPARED_2PC, and calls abort, if appropriate
|
||||||
|
<li> abort, which handles the application specific actions for abort
|
||||||
|
<li> commit, which handles the application specific commit.
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
A note on transaction ID's: clients specify transaction ID's by
|
||||||
|
addressing messages to the state machine with machine_id =
|
||||||
|
transaction_id.
|
||||||
|
|
||||||
|
The coordinator sends an ack to the client once the transaction
|
||||||
|
commits or aborts, and keeps the machine around until the client ack's
|
||||||
|
the ack. This is done in order to provide exactly once semantics.
|
||||||
|
|
||||||
|
No locking, or ordering of requests is performed by the library.
|
||||||
|
|
||||||
|
The 64-bit transaction id's could, in principle, be reused.
|
||||||
|
|
||||||
|
Distinct requests with identical transaction id's are serialized by
|
||||||
|
the current implementation, but no scheduling is done. The first
|
||||||
|
request that retries after a transaction completes is the one that
|
||||||
|
gets to reuse the transaction id.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
These will generally be defined by the user of the library.
|
||||||
|
|
||||||
|
(If you need more than one instance of 2pc per binary, memcpy the tranistions_2pc and states_2pc arrays...)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* STATES */
|
||||||
|
#define COORDINATOR_START_2PC 101
|
||||||
|
#define COORDINATOR_COMMITTING_2PC 102
|
||||||
|
#define COORDINATOR_ABORTING_2PC 103
|
||||||
|
|
||||||
|
#define SUBORDINATE_VETO_2PC 201
|
||||||
|
#define SUBORDINATE_PREPARED_2PC 202
|
||||||
|
#define SUBORDINATE_ACKING_2PC 203
|
||||||
|
|
||||||
|
#define AWAIT_ARRIVAL 211
|
||||||
|
#define AWAIT_COMMIT_POINT 212
|
||||||
|
#define AWAIT_RESULT 213
|
||||||
|
|
||||||
|
/**
|
||||||
|
The callbacks are called whenever the transition 'should' succeed.
|
||||||
|
Other than tally_2pc, they are always called when a
|
||||||
|
corresponding message comes in. tally_2pc is only called after
|
||||||
|
the last subordinate votes to prepare.
|
||||||
|
|
||||||
|
All callbacks (other than veto_or_prepare) should return TRUE or
|
||||||
|
FALSE, depending on whether or not the transition should
|
||||||
|
succeed. veto_or_prepare returns SUBORDINATE_PREPARED_2PC,
|
||||||
|
SUBORDINATE_VETO_2PC, or OVERRIDDEN_STATE.
|
||||||
|
|
||||||
|
Under normal operations, they should never return OVERRIDDEN_STATE
|
||||||
|
or FALSE, since that would violate the normal 2pc protocol.
|
||||||
|
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** The global transaction ID. Provided by caller of api's commit() function. */
|
||||||
|
int xid;
|
||||||
|
/* char initiator[MAX_ADDRESS_LENGTH]; */
|
||||||
|
|
||||||
|
/** Right now, get number of subordinates from network setup. (Need
|
||||||
|
to do something more fancy for recursive transactions.)
|
||||||
|
*/
|
||||||
|
char subordinate_votes[MAX_SUBORDINATES];
|
||||||
|
|
||||||
|
} TwoPCMachineState;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/** TRUE if this instance of the program is the coordinator. A
|
||||||
|
single process could be both a subordinate and the coordinator,
|
||||||
|
in priniciple. In that case, is_coordinator should be set to
|
||||||
|
true, (and the coordinator process's address sould be present in
|
||||||
|
two broadcast groups.) */
|
||||||
|
char is_coordinator;
|
||||||
|
callback_fcn *init_xact_2pc;
|
||||||
|
callback_fcn *veto_or_prepare_2pc;
|
||||||
|
callback_fcn *abort_2pc;
|
||||||
|
callback_fcn *commit_2pc;
|
||||||
|
callback_fcn *tally_2pc;
|
||||||
|
/**
|
||||||
|
The get_broadcast_group function should return the number of the
|
||||||
|
broadcast group that the message should be forwarded to. (The
|
||||||
|
coordinator is in broadcast group 0, so this function should
|
||||||
|
return a number greater than zero.
|
||||||
|
*/
|
||||||
|
short (*get_broadcast_group)(DfaSet *, Message * m);
|
||||||
|
recordid app_state_record_id;
|
||||||
|
void * app_state;
|
||||||
|
} TwoPCAppState;
|
||||||
|
|
||||||
|
/* #ifndef _TWO_PC */
|
||||||
|
extern const int transition_count_2pc;
|
||||||
|
extern const int client_transition_count_2pc;
|
||||||
|
extern const int state_count_2pc;
|
||||||
|
extern Transition client_transitions_2pc[];
|
||||||
|
extern Transition transitions_2pc[];
|
||||||
|
extern State states_2pc[];
|
||||||
|
/* #endif */
|
4
src/2pc/Makefile.am
Normal file
4
src/2pc/Makefile.am
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#LDADD=$(top_builddir)/build/libdfa.a
|
||||||
|
lib_LIBRARIES=lib2pc.a
|
||||||
|
lib2pc_a_SOURCES=2pc.c
|
||||||
|
AM_CFLAGS= -g -Wall -pedantic -std=gnu99
|
1
src/Makefile.am
Normal file
1
src/Makefile.am
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SUBDIRS = pbl lladd libdfa 2pc timing apps
|
1
src/apps/Makefile.am
Normal file
1
src/apps/Makefile.am
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SUBDIRS = cht #cyrus
|
5
src/apps/cht/Makefile.am
Normal file
5
src/apps/cht/Makefile.am
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
LDADD=$(top_builddir)/src/libdfa/libdfa.a $(top_builddir)/src/2pc/lib2pc.a
|
||||||
|
SOURCES=cht.c
|
||||||
|
lib_LIBRARIES=libcht.a
|
||||||
|
libcht_a_SOURCES=cht.c
|
||||||
|
AM_CFLAGS= -g -Wall -pedantic -std=gnu99
|
652
src/apps/cht/cht.c
Normal file
652
src/apps/cht/cht.c
Normal file
|
@ -0,0 +1,652 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 "cht.h"
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "../../2pc/2pc.h"
|
||||||
|
#include "../../libdfa/callbacks.h"
|
||||||
|
#include <pbl/jbhash.h>
|
||||||
|
#define CREATE 1
|
||||||
|
#define INSERT 2
|
||||||
|
#define LOOKUP 3
|
||||||
|
#define REMOVE 4
|
||||||
|
#define DELETE 5
|
||||||
|
/** Unimplemented: Evaluate a function call from a table provided by the library user. */
|
||||||
|
#define TSTSET 6
|
||||||
|
#define GETXID 7
|
||||||
|
/* #define COMMIT 8
|
||||||
|
#define ABORT 9 */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short key_length;
|
||||||
|
unsigned short value_length;
|
||||||
|
unsigned char request_type;
|
||||||
|
unsigned char response_type;
|
||||||
|
clusterHashTable_t hashTable;
|
||||||
|
} payload_header;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int ht_xid;
|
||||||
|
jbHashTable_t * xid_ht;
|
||||||
|
jbHashTable_t * ht_ht;
|
||||||
|
int next_hashTableId;
|
||||||
|
} CHTAppState;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define __header_ptr(m) ((payload_header*)(&((m)->payload)))
|
||||||
|
|
||||||
|
static unsigned short* _key_length(Message * m) {
|
||||||
|
return &(__header_ptr(m)->key_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned short* _value_length(Message *m) {
|
||||||
|
return &(__header_ptr(m)->value_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define getKeyLength(m) (ntohs(*_key_length(m)))
|
||||||
|
#define setKeyLength(m, x) (*_key_length(m)=htons(x))
|
||||||
|
|
||||||
|
|
||||||
|
#define getValLength(m) (ntohs(*_value_length(m)))
|
||||||
|
#define setValLength(m, x) (*_value_length(m)=htons(x))
|
||||||
|
|
||||||
|
static unsigned char * requestType(Message *m) {
|
||||||
|
return &(__header_ptr(m)->request_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char * responseType(Message *m) {
|
||||||
|
return &(__header_ptr(m)->response_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TODO: Endianness. (ICK) */
|
||||||
|
#define setup_vars \
|
||||||
|
state_name request_type =*(requestType(m)); \
|
||||||
|
state_name response_type =*(responseType(m)); \
|
||||||
|
TwoPCMachineState * machine_state_2pc = (TwoPCMachineState*) &(stateMachine->app_state); \
|
||||||
|
TwoPCAppState * app_state_2pc = ((TwoPCAppState*)(((DfaSet*)dfaSet)->app_setup)); \
|
||||||
|
CHTAppState * app_state_cht = app_state_2pc->app_state; \
|
||||||
|
jbHashTable_t * xid_ht = app_state_cht->xid_ht; \
|
||||||
|
jbHashTable_t * ht_ht = app_state_cht->ht_ht; \
|
||||||
|
int ht_xid = app_state_cht->ht_xid; \
|
||||||
|
int xid; \
|
||||||
|
int xid_exists = (-1 != jbHtLookup(ht_xid, xid_ht, &(stateMachine->machine_id), sizeof(state_machine_id), &xid)); \
|
||||||
|
jbHashTable_t ht; \
|
||||||
|
int ht_exists = (-1 != jbHtLookup(ht_xid, ht_ht, &(__header_ptr(m)->hashTable), sizeof(clusterHashTable_t), &ht))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash function generator, taken directly from pblhash
|
||||||
|
*/
|
||||||
|
static int hash( const unsigned char * key, size_t keylen , int table_length) {
|
||||||
|
int ret = 104729;
|
||||||
|
|
||||||
|
for( ; keylen-- > 0; key++ )
|
||||||
|
{
|
||||||
|
if( *key )
|
||||||
|
{
|
||||||
|
ret *= *key + keylen;
|
||||||
|
ret %= table_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return( ret % table_length );
|
||||||
|
}
|
||||||
|
|
||||||
|
void * getKeyAddr(Message *m) {
|
||||||
|
char * stuff = m->payload;
|
||||||
|
|
||||||
|
return (stuff + sizeof(payload_header)); /* Just add the header length. */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void * getValAddr(Message * m) {
|
||||||
|
return ((char*)getKeyAddr(m)) + getKeyLength(m); /* key address + key length. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
@return 1 if the payload is valid (key_length and value length do not over-run the message's memory, 0 otherwise.)
|
||||||
|
|
||||||
|
*/
|
||||||
|
int checkPayload(Message * m) {
|
||||||
|
char * a = (char*)m;
|
||||||
|
char * b = getValAddr(m);
|
||||||
|
return (a+ sizeof(Message) ) >= (b + getValLength(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TODO: multiplex_interleaved needs to return a special group for
|
||||||
|
begin/commit/abort requests. There will then be two types of
|
||||||
|
transactions. Explicit ones will create xids on all replicas, and
|
||||||
|
span multiple operations. Implcit ones will only span one replica
|
||||||
|
group, but may only contain a single operation.
|
||||||
|
*/
|
||||||
|
short multiplex_interleaved(DfaSet * dfaSet, Message * m) {
|
||||||
|
short table_length = dfaSet->networkSetup.broadcast_lists_count-2;
|
||||||
|
short bc_group;
|
||||||
|
if((*requestType(m) == CREATE) || (*requestType(m) == DELETE)) {
|
||||||
|
/* Special case: Send to all replicas...bc_group one should contain all replicas... */
|
||||||
|
bc_group = 1;
|
||||||
|
} else {
|
||||||
|
/* Need to add one so that no requests are assigned to the coordinator (bc:0) */
|
||||||
|
bc_group = hash(getKeyAddr(m), getKeyLength(m), table_length) + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("request %d bc group: %d\n", *requestType(m), bc_group);
|
||||||
|
|
||||||
|
return bc_group;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
state_name do_work(void * dfaSet, StateMachine * stateMachine, Message * m, char * from);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The client side function that 'does everything'
|
||||||
|
|
||||||
|
@param request_type The type of request to be run.
|
||||||
|
|
||||||
|
@param response_type The expected response type. Returns 1 if this
|
||||||
|
remote state is returned, 0 otherwise. (TODO:
|
||||||
|
Double check this documentation.)
|
||||||
|
|
||||||
|
@param xid The (stateMachine) transaction id. Set to a random
|
||||||
|
number when calling BEGIN. To prevent deadlock, it's
|
||||||
|
best to choose a number unlikely to correspond to an
|
||||||
|
active transaction. (A random number within 2^32 of the
|
||||||
|
highest 64-bit integer will work.)
|
||||||
|
|
||||||
|
@param reply_type When should the local call return? The choices
|
||||||
|
are AWAIT_ARRIVAL, which returns after hearing
|
||||||
|
back from the coordinator, AWAIT_COMMIT_POINT to
|
||||||
|
wait until after the transaction commits/aborts,
|
||||||
|
AWAIT_RESULT, which waits for the actual result
|
||||||
|
from one of the replicas.
|
||||||
|
|
||||||
|
@param key, key_size, value, value_size depend on the value of request_type.
|
||||||
|
|
||||||
|
@return 1 on success, 0 on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int _chtEval(DfaSet * dfaSet,
|
||||||
|
unsigned char request_type,
|
||||||
|
unsigned char response_type,
|
||||||
|
state_machine_id * xid,
|
||||||
|
clusterHashTable_t * ht,
|
||||||
|
void * key, size_t * key_size,
|
||||||
|
void * value, size_t * value_size) {
|
||||||
|
|
||||||
|
/* Fill out a message payload. */
|
||||||
|
|
||||||
|
Message m;
|
||||||
|
|
||||||
|
if(ht != NULL) {
|
||||||
|
printf("_chtEval(request=%d, response=%d, xid=%ld, ht=%d ", request_type, response_type, *xid, ht->id);
|
||||||
|
} else {
|
||||||
|
printf("_chtEval(request=%d, response=%d, xid=%ld, ht=NULL ", request_type, response_type, *xid);
|
||||||
|
}
|
||||||
|
if(key == NULL) {
|
||||||
|
printf(")\n");
|
||||||
|
} else {
|
||||||
|
printf("key=%d)\n", *(int*)key);
|
||||||
|
}
|
||||||
|
* requestType(&m) = request_type;
|
||||||
|
* responseType(&m) = response_type;
|
||||||
|
|
||||||
|
setKeyLength(&m, *key_size);
|
||||||
|
setValLength(&m, *value_size);
|
||||||
|
|
||||||
|
assert(checkPayload(&m));
|
||||||
|
if(key_size != 0) {
|
||||||
|
memcpy(getKeyAddr(&m), key, *key_size);
|
||||||
|
}
|
||||||
|
if(value_size != 0) {
|
||||||
|
memcpy(getValAddr(&m), value, *value_size);
|
||||||
|
}
|
||||||
|
if(ht != NULL) {
|
||||||
|
memcpy(&(__header_ptr(&m)->hashTable), ht, sizeof(clusterHashTable_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* printf("%s <- %s\n", __header_ptr(&m)->initiator, dfaSet->networkSetup.localhost); */
|
||||||
|
|
||||||
|
/* Synchronously run the request */
|
||||||
|
request(dfaSet, response_type, "bc:0", *xid, &m);
|
||||||
|
|
||||||
|
if(!checkPayload(&m)) {
|
||||||
|
printf("_chtEval failed: Invalid response.\n");
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy message contents back into caller's buffers, even if the
|
||||||
|
request failed. (There may be app-specific information in the
|
||||||
|
response...) */
|
||||||
|
|
||||||
|
if(ht != NULL) {
|
||||||
|
memcpy(ht, &(__header_ptr(&m)->hashTable), sizeof(clusterHashTable_t));
|
||||||
|
}
|
||||||
|
if (*key_size != 0) {
|
||||||
|
/* printf("\n+%x<-%x+, length %d value=%s and %s\n", (unsigned int) value, (unsigned int)getValAddr(&m), getValLength(&m), value, getValAddr(&m)); */
|
||||||
|
memcpy(value, getValAddr(&m), getValLength(&m));
|
||||||
|
}
|
||||||
|
if (*value_size != 0) {
|
||||||
|
memcpy(key, getKeyAddr(&m), getKeyLength(&m));
|
||||||
|
}
|
||||||
|
|
||||||
|
*xid = m.to_machine_id;
|
||||||
|
|
||||||
|
printf("+chtEval returning %d\n", m.type);
|
||||||
|
|
||||||
|
return m.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
state_name init_xact_cht(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
|
||||||
|
|
||||||
|
TwoPCMachineState * state = (TwoPCMachineState*) &(stateMachine->app_state);
|
||||||
|
TwoPCAppState * app_state_2pc = ((TwoPCAppState*)(((DfaSet*)dfaSet)->app_setup));
|
||||||
|
CHTAppState * app_state_cht = app_state_2pc->app_state;
|
||||||
|
|
||||||
|
if(m->type != *responseType(m)) {
|
||||||
|
printf("Bug in client! m->type != response_type(m).\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*requestType(m) == CREATE) {
|
||||||
|
clusterHashTable_t new_cht;
|
||||||
|
new_cht.id = app_state_cht->next_hashTableId;
|
||||||
|
app_state_cht->next_hashTableId++;
|
||||||
|
|
||||||
|
memcpy(&(__header_ptr(m)->hashTable), &new_cht, sizeof(clusterHashTable_t));
|
||||||
|
|
||||||
|
printf("Allocated hashtable %d\n", new_cht.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("requestType: %d, responseType: %d key: %d from %s:%ld\n", *requestType(m), *responseType(m), *(int*)getKeyAddr(m), m->initiator, m->initiator_machine_id);
|
||||||
|
|
||||||
|
if(*responseType(m) == AWAIT_ARRIVAL) {
|
||||||
|
state_machine_id tmp = m->from_machine_id;
|
||||||
|
|
||||||
|
/* TODO: Could the chages to from_machine_id be moved into libdfa (it does this anyway, but it does it too late.) */
|
||||||
|
m->from_machine_id = m->initiator_machine_id; /*stateMachine->machine_id;*/
|
||||||
|
|
||||||
|
printf("Responding\n");
|
||||||
|
|
||||||
|
respond_once(&((DfaSet*)dfaSet)->networkSetup, COORDINATOR_START_2PC, m, m->initiator);
|
||||||
|
|
||||||
|
m->from_machine_id = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback_fcn abort_cht;
|
||||||
|
|
||||||
|
/* Begins new transaction, does the work the transaction requests, stores the message, and returns the corresponding error code. */
|
||||||
|
state_name veto_or_prepare_cht(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
|
||||||
|
state_name ret;
|
||||||
|
setup_vars;
|
||||||
|
|
||||||
|
if(xid_exists) { printf("Warning: Stale xid found!\n"); }
|
||||||
|
assert(!xid_exists);
|
||||||
|
printf("requestType: %d, responseType: %d key: %d from %s:%ld\n", *requestType(m), *responseType(m), *(int*)getKeyAddr(m), m->initiator, m->initiator_machine_id);
|
||||||
|
|
||||||
|
/* This is the start of a new transaction */
|
||||||
|
xid = Tbegin(); // !!!!
|
||||||
|
if(xid < 0) {
|
||||||
|
|
||||||
|
printf("Tbegin failed; %d\n", xid);
|
||||||
|
|
||||||
|
} else if(jbHtInsert(ht_xid, xid_ht, &(stateMachine->machine_id), sizeof(state_machine_id), &xid, sizeof(int)) == -1) {
|
||||||
|
|
||||||
|
printf("jbHtInsert failed.\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
xid_exists = 1;
|
||||||
|
}
|
||||||
|
Tcommit(app_state_cht->ht_xid);
|
||||||
|
app_state_cht->ht_xid = Tbegin();
|
||||||
|
|
||||||
|
if(xid_exists) {
|
||||||
|
|
||||||
|
ret = do_work(dfaSet, stateMachine, m, from);
|
||||||
|
|
||||||
|
ret = ret ? SUBORDINATE_PREPARED_2PC : SUBORDINATE_VETO_2PC;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ret = SUBORDINATE_VETO_2PC;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret == SUBORDINATE_VETO_2PC) {
|
||||||
|
abort_cht(dfaSet, stateMachine, m, from);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_name abort_cht(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
setup_vars;
|
||||||
|
|
||||||
|
printf("Aborting!!\n");
|
||||||
|
|
||||||
|
if(response_type == AWAIT_COMMIT_POINT || response_type == AWAIT_RESULT) {
|
||||||
|
state_machine_id tmp = m->from_machine_id;
|
||||||
|
|
||||||
|
/* TODO: Could the chages to from_machine_id be moved into libdfa (it does this anyway, but it does it too late.) */
|
||||||
|
m->from_machine_id = m->initiator_machine_id; /*stateMachine->machine_id;*/
|
||||||
|
|
||||||
|
printf("Response being sent to: %s:%ld\n", m->initiator, m->to_machine_id);
|
||||||
|
respond_once(&((DfaSet*)dfaSet)->networkSetup, SUBORDINATE_VETO_2PC, m, m->initiator);
|
||||||
|
m->from_machine_id = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(xid_exists);
|
||||||
|
|
||||||
|
Tabort(xid); // !!!!
|
||||||
|
jbHtRemove(ht_xid, xid_ht, &(stateMachine->machine_id), sizeof(state_machine_id), &xid);
|
||||||
|
Tcommit(app_state_cht->ht_xid);
|
||||||
|
app_state_cht->ht_xid = Tbegin();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TODO For now, we ignore the possiblity that jbHashTable's functions
|
||||||
|
return error codes. Instead, we assume that they always
|
||||||
|
succeed. */
|
||||||
|
state_name do_work(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
int ret;
|
||||||
|
setup_vars;
|
||||||
|
|
||||||
|
/* printf("ht_ht = %x, ht = %x\n", ht_ht, ht); */
|
||||||
|
|
||||||
|
switch(request_type)
|
||||||
|
{
|
||||||
|
case CREATE:
|
||||||
|
{
|
||||||
|
jbHashTable_t * new = jbHtCreate(ht_xid, 79);
|
||||||
|
if(new != NULL) {
|
||||||
|
ret = (jbHtInsert(ht_xid, ht_ht, &(__header_ptr(m)->hashTable), sizeof(clusterHashTable_t), new, sizeof(jbHashTable_t)) >= 0);
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if(ret) {
|
||||||
|
printf("Created local slice of global hash table %d\n", (__header_ptr(m)->hashTable).id);
|
||||||
|
Tcommit(app_state_cht->ht_xid);
|
||||||
|
app_state_cht->ht_xid = Tbegin();
|
||||||
|
} else {
|
||||||
|
printf("Failed to insert new hash table slice!");
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case INSERT:
|
||||||
|
{
|
||||||
|
if(!ht_exists) { printf ("Hash table %d doesn't exist!\n", (__header_ptr(m)->hashTable).id); fflush(NULL); ret = 0; } else {
|
||||||
|
ret = (jbHtInsert(xid, &ht, getKeyAddr(m), getKeyLength(m), getValAddr(m), getValLength(m)) >= 0);
|
||||||
|
printf("Insert: %d ht=%d (key length %d) %d -> %s\n", ret, (__header_ptr(m)->hashTable).id, getKeyLength(m), *(int*)getKeyAddr(m), getValAddr(m));
|
||||||
|
(jbHtInsert(ht_xid, ht_ht, &(__header_ptr(m)->hashTable), sizeof(clusterHashTable_t), &ht, sizeof(jbHashTable_t)));
|
||||||
|
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case LOOKUP:
|
||||||
|
{
|
||||||
|
if(!ht_exists) { printf ("Hash table doesn't exist!\n"); fflush(NULL); ret = 0; } else {
|
||||||
|
ret = (jbHtLookup(xid, &ht, getKeyAddr(m), getKeyLength(m), getValAddr(m)) >= 0);
|
||||||
|
printf("Lookup: %d ht=%d (key length %d) %d -> %s\n", ret, (__header_ptr(m)->hashTable).id, getKeyLength(m), *(int*)getKeyAddr(m), getValAddr(m));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case REMOVE:
|
||||||
|
{
|
||||||
|
if(!ht_exists) { printf ("Hash table doesn't exist!\n"); fflush(NULL); ret = 0; } else {
|
||||||
|
ret = (jbHtRemove(xid, &ht, getKeyAddr(m), getKeyLength(m), getValAddr(m)) >= 0);
|
||||||
|
(jbHtInsert(ht_xid, ht_ht, &(__header_ptr(m)->hashTable), sizeof(clusterHashTable_t), &ht, sizeof(jbHashTable_t)));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DELETE:
|
||||||
|
{
|
||||||
|
if(!ht_exists) { printf ("Hash table doesn't exist!\n"); fflush(NULL); ret = 0; } else {
|
||||||
|
jbHtRemove(xid, ht_ht, getKeyAddr(m), getKeyLength(m), NULL);
|
||||||
|
(jbHtInsert(ht_xid, ht_ht, &(__header_ptr(m)->hashTable), sizeof(clusterHashTable_t), &ht, sizeof(jbHashTable_t)));
|
||||||
|
/* ret = (jbHtDelete(xid, &ht) >= 0); */ /* Don't need this--jbHtDelete just frees the (stack!) pointer. */
|
||||||
|
Tcommit(app_state_cht->ht_xid);
|
||||||
|
app_state_cht->ht_xid = Tbegin();
|
||||||
|
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TSTSET:
|
||||||
|
{
|
||||||
|
printf("Unimplemented request!\n");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GETXID:
|
||||||
|
{
|
||||||
|
/* int new_xid = Tbegin();
|
||||||
|
if(new_xid >= 0) {
|
||||||
|
setKeyLength(m, 0);
|
||||||
|
setValLength(m, sizeof(int));
|
||||||
|
*((int*)getValAddr(m)) = new_xid;
|
||||||
|
ret = 1;
|
||||||
|
if(jbHtInsert(ht_xid, xid_ht, &(stateMachine->machine_id), sizeof(state_machine_id), &xid, sizeof(int)) == -1) {
|
||||||
|
printf("Begin failed on jbHtInsert!\n");
|
||||||
|
} else {
|
||||||
|
printf("Created local xid for global xid: %ld\n", stateMachine->machine_id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Begin failed on Tbegin()!\n");
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
} NOOP */
|
||||||
|
} break;
|
||||||
|
|
||||||
|
/* case COMMIT:
|
||||||
|
{
|
||||||
|
ret = (Tcommit(xid) >= 0);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ABORT:
|
||||||
|
{
|
||||||
|
ret = (Tabort(xid) >= 0);
|
||||||
|
} break;
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
printf("Unknown request type: %d\n", request_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_name commit_cht(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
|
||||||
|
setup_vars;
|
||||||
|
|
||||||
|
assert(xid_exists);
|
||||||
|
Tcommit(xid);
|
||||||
|
jbHtRemove(ht_xid, xid_ht, &(stateMachine->machine_id), sizeof(state_machine_id), &xid);
|
||||||
|
Tcommit(app_state_cht->ht_xid);
|
||||||
|
app_state_cht->ht_xid = Tbegin();
|
||||||
|
/* }*/
|
||||||
|
|
||||||
|
if(response_type == AWAIT_RESULT) {
|
||||||
|
printf("commit_cht responding on an AWAIT_RESULT request.\n");
|
||||||
|
assert(0);
|
||||||
|
/* respond_once(&((DfaSet*)dfaSet)->networkSetup, SUBORDINATE_ACKING_2PC, m, __header_ptr(m)->initiator); */
|
||||||
|
}
|
||||||
|
/* TODO: Check error codes, and return accordingly... */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_name tally_cht(void * dfaSet, StateMachine * stateMachine, Message * m, char * from) {
|
||||||
|
|
||||||
|
setup_vars;
|
||||||
|
|
||||||
|
/* TODO: Make sure this is after tally forces the log. Also, need to
|
||||||
|
make sure that it increments the (currently unimplemented)
|
||||||
|
sequence number before flushing... */
|
||||||
|
|
||||||
|
if(response_type == AWAIT_COMMIT_POINT && stateMachine->current_state==COORDINATOR_START_2PC) {
|
||||||
|
state_machine_id tmp = m->from_machine_id;
|
||||||
|
|
||||||
|
/* TODO: Could the chages to from_machine_id be moved into libdfa (it does this anyway, but it does it too late.) */
|
||||||
|
m->from_machine_id = m->initiator_machine_id; /*stateMachine->machine_id;*/
|
||||||
|
|
||||||
|
printf("Coordinator responding: ? ht=? (key length %d) %d -> to %s:%ld\n", getKeyLength(m), *(int*)getKeyAddr(m), /*getValAddr(m),*/ m->initiator, m->initiator_machine_id );
|
||||||
|
respond_once(&((DfaSet*)dfaSet)->networkSetup, COORDINATOR_COMMITTING_2PC, m, m->initiator);
|
||||||
|
|
||||||
|
m->from_machine_id = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DfaSet * cHtInit(int cht_type, char * localhost,
|
||||||
|
short (* get_broadcast_group)(DfaSet *, Message *),
|
||||||
|
short port,
|
||||||
|
char *** broadcast_lists,
|
||||||
|
int broadcast_lists_count,
|
||||||
|
int* broadcast_list_host_count) {
|
||||||
|
|
||||||
|
DfaSet * dfaSet;
|
||||||
|
int xid = Tbegin();
|
||||||
|
TwoPCAppState * twoPC_state;
|
||||||
|
CHTAppState * chtApp_state;
|
||||||
|
|
||||||
|
int error;
|
||||||
|
|
||||||
|
dfaSet = dfa_malloc(DFA_MACHINE_COUNT, port, broadcast_lists, broadcast_lists_count, broadcast_list_host_count);
|
||||||
|
|
||||||
|
/* srand(time(NULL)); */
|
||||||
|
|
||||||
|
twoPC_state = calloc(1, sizeof(TwoPCAppState));
|
||||||
|
chtApp_state = calloc(1, sizeof(CHTAppState));
|
||||||
|
|
||||||
|
if(cht_type == CHT_CLIENT) {
|
||||||
|
error = dfa_reinitialize(dfaSet, localhost, client_transitions_2pc, client_transition_count_2pc, states_2pc, state_count_2pc);
|
||||||
|
} else {
|
||||||
|
error = dfa_reinitialize(dfaSet, localhost, transitions_2pc, transition_count_2pc, states_2pc, state_count_2pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(error < 0) {
|
||||||
|
perror("dfa_reinitialize failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cht_type != CHT_CLIENT) {
|
||||||
|
chtApp_state->xid_ht = jbHtCreate(xid, 79);
|
||||||
|
chtApp_state->ht_ht = jbHtCreate(xid, 79);
|
||||||
|
chtApp_state->ht_xid = Tbegin(); // !!!!
|
||||||
|
chtApp_state->next_hashTableId = 0; /* This gets incremented each time a new hashtable is allocated. */
|
||||||
|
|
||||||
|
twoPC_state->is_coordinator = (cht_type == CHT_COORDINATOR);
|
||||||
|
twoPC_state->init_xact_2pc = init_xact_cht;
|
||||||
|
twoPC_state->veto_or_prepare_2pc = veto_or_prepare_cht;
|
||||||
|
twoPC_state->abort_2pc = abort_cht;
|
||||||
|
twoPC_state->commit_2pc = commit_cht;
|
||||||
|
twoPC_state->tally_2pc = tally_cht;
|
||||||
|
if(get_broadcast_group == NULL) get_broadcast_group = multiplex_interleaved;
|
||||||
|
twoPC_state->get_broadcast_group = get_broadcast_group;
|
||||||
|
twoPC_state->app_state_record_id = Talloc(xid, sizeof(CHTAppState));
|
||||||
|
twoPC_state->app_state = chtApp_state;
|
||||||
|
|
||||||
|
Tset(xid, twoPC_state->app_state_record_id, chtApp_state);
|
||||||
|
|
||||||
|
dfaSet->app_setup = twoPC_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tcommit(xid);
|
||||||
|
|
||||||
|
return dfaSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cHtCreate(state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t * new_ht) {
|
||||||
|
size_t zero = 0;
|
||||||
|
return _chtEval(dfaSet, CREATE, AWAIT_COMMIT_POINT, &xid, new_ht, NULL, &zero, NULL, &zero) != SUBORDINATE_VETO_2PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cHtInsert(state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t * ht, void * key, size_t keylen, void * dat, size_t datlen) {
|
||||||
|
return _chtEval(dfaSet, INSERT, AWAIT_COMMIT_POINT, &xid, ht, key, &keylen, dat, &datlen) != SUBORDINATE_VETO_2PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cHtLookup(state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t * ht, void * key, size_t keylen, void * dat, size_t * datlen) {
|
||||||
|
return _chtEval(dfaSet, LOOKUP, AWAIT_COMMIT_POINT, &xid, ht, key, &keylen, dat, datlen) != SUBORDINATE_VETO_2PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cHtRemove(state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t * ht, void * key, size_t keylen, void * dat, size_t * datlen) {
|
||||||
|
return _chtEval(dfaSet, REMOVE, AWAIT_COMMIT_POINT, &xid, ht, key, &keylen, dat, datlen) != SUBORDINATE_VETO_2PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cHtDelete(state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t *ht) {
|
||||||
|
size_t zero = 0;
|
||||||
|
return _chtEval(dfaSet, DELETE, AWAIT_COMMIT_POINT, &xid, ht, NULL, &zero, NULL, &zero) != SUBORDINATE_VETO_2PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cHtGetXid(state_machine_id* xid, DfaSet * dfaSet) {
|
||||||
|
size_t zero = 0;
|
||||||
|
*xid = NULL_MACHINE; /* Will be overwritten by
|
||||||
|
_chtEval... Need a large random
|
||||||
|
value so that the request will
|
||||||
|
be serviced exactly once, but
|
||||||
|
will not conflict with real
|
||||||
|
transactions or other begins.*/
|
||||||
|
return _chtEval(dfaSet, GETXID, AWAIT_ARRIVAL, xid, NULL, NULL, &zero, NULL, &zero) != SUBORDINATE_VETO_2PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*int cHtCommit(state_machine_id xid, DfaSet * dfaSet) {
|
||||||
|
size_t zero = 0;
|
||||||
|
return _chtEval(dfaSet, COMMIT, AWAIT_COMMIT_POINT, &xid, NULL, NULL, &zero, NULL, &zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cHtAbort(state_machine_id xid, DfaSet * dfaSet) {
|
||||||
|
size_t zero = 0;
|
||||||
|
return _chtEval(dfaSet, ABORT, AWAIT_COMMIT_POINT, &xid, NULL, NULL, &zero, NULL, &zero);
|
||||||
|
}*/
|
140
src/apps/cht/cht.h
Normal file
140
src/apps/cht/cht.h
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <libdfa/libdfa.h>
|
||||||
|
|
||||||
|
#define CHT_COORDINATOR 1
|
||||||
|
#define CHT_SERVER 2
|
||||||
|
#define CHT_CLIENT 3
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int id;
|
||||||
|
} clusterHashTable_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jbHtCreate makes a new persistant hashtable
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param dfaSet The state machine set that will be used to manage the cluster hash table. (TODO: Who initializes this?)
|
||||||
|
* @param new_ht a preallocated buffer to hold the new hash table.
|
||||||
|
* @return 1 on success, 0 on error.pointer to hashtable, or NULL on error
|
||||||
|
*/
|
||||||
|
int cHtCreate(state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t * new_ht);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a key/value pair
|
||||||
|
* makes a SHALLOW COPY of the data to keep in durable storage
|
||||||
|
* will REPLACE an existing entry with the same key
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable in which to insert
|
||||||
|
* @param key pointer to data serving as key
|
||||||
|
* @param keylen how much data to use from pointer
|
||||||
|
* @param dat data to insert
|
||||||
|
* @param datlen length data
|
||||||
|
* @return -1 on error, 0 on success
|
||||||
|
*/
|
||||||
|
int cHtInsert(state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t * ht, void * key, size_t keylen, void * dat, size_t datlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup a value with a key
|
||||||
|
*
|
||||||
|
* *TODO* This api is only safe becuase value lengths are bounded!
|
||||||
|
* Need to fix API, and implementation to support arbitrary length
|
||||||
|
* keys and values.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable in which to look
|
||||||
|
* @param key pointer to key data
|
||||||
|
* @param keylen length of key
|
||||||
|
* @param dat preallocated buffer in which to put data
|
||||||
|
* @param datlen overwritten with the size of the data that was read.
|
||||||
|
* @return -1 if error occurs, including nothing found
|
||||||
|
*/
|
||||||
|
int cHtLookup(state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t *ht, void *key, size_t keylen, void *dat, size_t* datlen);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete entry associated with key
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable in which to delete
|
||||||
|
* @param key pointer to key data
|
||||||
|
* @param keylen length of key
|
||||||
|
* @param buf if non-NULL, preallocated space to copy data from deleted key
|
||||||
|
* @return -1 on errors or not found, 0 if existing entry was deleted
|
||||||
|
*/
|
||||||
|
int cHtRemove( state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t *ht, void *key, size_t keylen, void *dat, size_t * datlen );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a hashtable
|
||||||
|
* table must be empty
|
||||||
|
* @param xid transaction id
|
||||||
|
* @param ht hashtable to delete
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int cHtDelete(state_machine_id xid, DfaSet * dfaSet, clusterHashTable_t *ht);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new DfaSet that is ready to have main_loop() or
|
||||||
|
* request() called on it. Of course, the DfaSet implements a
|
||||||
|
* cluster hash table. ;)
|
||||||
|
*
|
||||||
|
* @param cht_type CHT_CLIENT, CHT_COORDINATOR, CHT_SUBORDINATE,
|
||||||
|
* depending on which portion of the CHT the dfa set should implement.
|
||||||
|
*
|
||||||
|
* @param get_broadcast_group A function that maps key values (from
|
||||||
|
* the messages key field) to broadcast groups.
|
||||||
|
*
|
||||||
|
* @see dfa_malloc for a description of the other parameters.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
DfaSet * cHtInit(int cht_type, char * localhost,
|
||||||
|
short (* get_broadcast_group)(DfaSet *, Message *),
|
||||||
|
short port,
|
||||||
|
char *** broadcast_lists,
|
||||||
|
int broadcast_lists_count,
|
||||||
|
int* broadcast_list_host_count);
|
||||||
|
|
||||||
|
int cHtGetXid(state_machine_id* xid, DfaSet * dfaSet);
|
||||||
|
/*int cHtCommit(state_machine_id xid, DfaSet * dfaSet);
|
||||||
|
int cHtAbort(state_machine_id xid, DfaSet * dfaSet);*/
|
1
src/apps/cyrus/.deps/cyrusdb_lladd.Po
Normal file
1
src/apps/cyrus/.deps/cyrusdb_lladd.Po
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# dummy
|
1
src/apps/cyrus/.deps/libcyrusdb_lladd.Po
Normal file
1
src/apps/cyrus/.deps/libcyrusdb_lladd.Po
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# dummy
|
371
src/apps/cyrus/Makefile
Normal file
371
src/apps/cyrus/Makefile
Normal file
|
@ -0,0 +1,371 @@
|
||||||
|
# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
srcdir = .
|
||||||
|
top_srcdir = ../../..
|
||||||
|
|
||||||
|
prefix = /usr/local
|
||||||
|
exec_prefix = ${prefix}
|
||||||
|
|
||||||
|
bindir = ${exec_prefix}/bin
|
||||||
|
sbindir = ${exec_prefix}/sbin
|
||||||
|
libexecdir = ${exec_prefix}/libexec
|
||||||
|
datadir = ${prefix}/share
|
||||||
|
sysconfdir = ${prefix}/etc
|
||||||
|
sharedstatedir = ${prefix}/com
|
||||||
|
localstatedir = ${prefix}/var
|
||||||
|
libdir = ${exec_prefix}/lib
|
||||||
|
infodir = ${prefix}/info
|
||||||
|
mandir = ${prefix}/man
|
||||||
|
includedir = ${prefix}/include
|
||||||
|
oldincludedir = /usr/include
|
||||||
|
|
||||||
|
DESTDIR =
|
||||||
|
|
||||||
|
pkgdatadir = $(datadir)/hello
|
||||||
|
pkglibdir = $(libdir)/hello
|
||||||
|
pkgincludedir = $(includedir)/hello
|
||||||
|
|
||||||
|
top_builddir = ../../..
|
||||||
|
|
||||||
|
ACLOCAL = aclocal-1.4
|
||||||
|
AUTOCONF = autoconf
|
||||||
|
AUTOMAKE = automake-1.4
|
||||||
|
AUTOHEADER = autoheader
|
||||||
|
|
||||||
|
INSTALL = /usr/bin/install -c
|
||||||
|
INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS)
|
||||||
|
INSTALL_DATA = ${INSTALL} -m 644
|
||||||
|
INSTALL_SCRIPT = ${INSTALL}
|
||||||
|
transform = s,x,x,
|
||||||
|
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
host_alias =
|
||||||
|
host_triplet = i686-pc-linux-gnu
|
||||||
|
AR = ar
|
||||||
|
AS = @AS@
|
||||||
|
CC = gcc
|
||||||
|
CHECK_CFLAGS =
|
||||||
|
CHECK_LIBS = -lcheck
|
||||||
|
CPP = gcc -E
|
||||||
|
CXX = g++
|
||||||
|
CXXCPP = g++ -E
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
ECHO = echo
|
||||||
|
EGREP = grep -E
|
||||||
|
EXEEXT =
|
||||||
|
F77 = g77
|
||||||
|
GCJ = @GCJ@
|
||||||
|
GCJFLAGS = @GCJFLAGS@
|
||||||
|
HAVE_LIB = @HAVE_LIB@
|
||||||
|
LIB = @LIB@
|
||||||
|
LIBTOOL = $(SHELL) $(top_builddir)/libtool
|
||||||
|
LN_S = ln -s
|
||||||
|
LTLIB = @LTLIB@
|
||||||
|
MAKEINFO = makeinfo
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = o
|
||||||
|
PACKAGE = hello
|
||||||
|
RANLIB = ranlib
|
||||||
|
RC = @RC@
|
||||||
|
STRIP = strip
|
||||||
|
VERSION = 0.1
|
||||||
|
|
||||||
|
LDADD = $(top_builddir)/build/libdfa.a $(top_builddir)/build/lib2pc.a
|
||||||
|
SOURCES = cyrusdb_lladd.c
|
||||||
|
lib_LIBRARIES = libcyrusdb_lladd.a
|
||||||
|
libcyrusdb_lladd_a_SOURCES = cyrusdb_lladd.c
|
||||||
|
AM_CFLAGS = -g -Wall -pedantic
|
||||||
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
|
CONFIG_HEADER = ../../../[config.h]
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
LIBRARIES = $(lib_LIBRARIES)
|
||||||
|
|
||||||
|
|
||||||
|
DEFS = -DHAVE_CONFIG_H -I. -I$(srcdir) -I../../..
|
||||||
|
CPPFLAGS =
|
||||||
|
LDFLAGS =
|
||||||
|
LIBS = -lpthread
|
||||||
|
libcyrusdb_lladd_a_LIBADD =
|
||||||
|
libcyrusdb_lladd_a_OBJECTS = cyrusdb_lladd.$(OBJEXT)
|
||||||
|
CFLAGS = -g -O2
|
||||||
|
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
CCLD = $(CC)
|
||||||
|
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
|
||||||
|
DIST_COMMON = Makefile.am Makefile.in
|
||||||
|
|
||||||
|
|
||||||
|
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
|
||||||
|
TAR = tar
|
||||||
|
GZIP_ENV = --best
|
||||||
|
DEP_FILES = .deps/cyrusdb_lladd.P
|
||||||
|
SOURCES = $(libcyrusdb_lladd_a_SOURCES)
|
||||||
|
OBJECTS = $(libcyrusdb_lladd_a_OBJECTS)
|
||||||
|
|
||||||
|
all: all-redirect
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .S .c .lo .o .obj .s
|
||||||
|
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||||
|
cd $(top_srcdir) && $(AUTOMAKE) --gnu src/apps/cyrus/Makefile
|
||||||
|
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||||
|
cd $(top_builddir) \
|
||||||
|
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-libLIBRARIES:
|
||||||
|
|
||||||
|
clean-libLIBRARIES:
|
||||||
|
-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
|
||||||
|
|
||||||
|
distclean-libLIBRARIES:
|
||||||
|
|
||||||
|
maintainer-clean-libLIBRARIES:
|
||||||
|
|
||||||
|
install-libLIBRARIES: $(lib_LIBRARIES)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
$(mkinstalldirs) $(DESTDIR)$(libdir)
|
||||||
|
@list='$(lib_LIBRARIES)'; for p in $$list; do \
|
||||||
|
if test -f $$p; then \
|
||||||
|
echo " $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p"; \
|
||||||
|
$(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p; \
|
||||||
|
else :; fi; \
|
||||||
|
done
|
||||||
|
@$(POST_INSTALL)
|
||||||
|
@list='$(lib_LIBRARIES)'; for p in $$list; do \
|
||||||
|
if test -f $$p; then \
|
||||||
|
echo " $(RANLIB) $(DESTDIR)$(libdir)/$$p"; \
|
||||||
|
$(RANLIB) $(DESTDIR)$(libdir)/$$p; \
|
||||||
|
else :; fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
uninstall-libLIBRARIES:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
list='$(lib_LIBRARIES)'; for p in $$list; do \
|
||||||
|
rm -f $(DESTDIR)$(libdir)/$$p; \
|
||||||
|
done
|
||||||
|
|
||||||
|
# FIXME: We should only use cygpath when building on Windows,
|
||||||
|
# and only if it is available.
|
||||||
|
.c.obj:
|
||||||
|
$(COMPILE) -c `cygpath -w $<`
|
||||||
|
|
||||||
|
.s.o:
|
||||||
|
$(COMPILE) -c $<
|
||||||
|
|
||||||
|
.S.o:
|
||||||
|
$(COMPILE) -c $<
|
||||||
|
|
||||||
|
mostlyclean-compile:
|
||||||
|
-rm -f *.o core *.core
|
||||||
|
-rm -f *.$(OBJEXT)
|
||||||
|
|
||||||
|
clean-compile:
|
||||||
|
|
||||||
|
distclean-compile:
|
||||||
|
-rm -f *.tab.c
|
||||||
|
|
||||||
|
maintainer-clean-compile:
|
||||||
|
|
||||||
|
.s.lo:
|
||||||
|
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||||
|
|
||||||
|
.S.lo:
|
||||||
|
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||||
|
|
||||||
|
mostlyclean-libtool:
|
||||||
|
-rm -f *.lo
|
||||||
|
|
||||||
|
clean-libtool:
|
||||||
|
-rm -rf .libs _libs
|
||||||
|
|
||||||
|
distclean-libtool:
|
||||||
|
|
||||||
|
maintainer-clean-libtool:
|
||||||
|
|
||||||
|
libcyrusdb_lladd.a: $(libcyrusdb_lladd_a_OBJECTS) $(libcyrusdb_lladd_a_DEPENDENCIES)
|
||||||
|
-rm -f libcyrusdb_lladd.a
|
||||||
|
$(AR) cru libcyrusdb_lladd.a $(libcyrusdb_lladd_a_OBJECTS) $(libcyrusdb_lladd_a_LIBADD)
|
||||||
|
$(RANLIB) libcyrusdb_lladd.a
|
||||||
|
|
||||||
|
tags: TAGS
|
||||||
|
|
||||||
|
ID: $(HEADERS) $(SOURCES) $(LISP)
|
||||||
|
list='$(SOURCES) $(HEADERS)'; \
|
||||||
|
unique=`for i in $$list; do echo $$i; done | \
|
||||||
|
awk ' { files[$$0] = 1; } \
|
||||||
|
END { for (i in files) print i; }'`; \
|
||||||
|
here=`pwd` && cd $(srcdir) \
|
||||||
|
&& mkid -f$$here/ID $$unique $(LISP)
|
||||||
|
|
||||||
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SOURCES) $(HEADERS)'; \
|
||||||
|
unique=`for i in $$list; do echo $$i; done | \
|
||||||
|
awk ' { files[$$0] = 1; } \
|
||||||
|
END { for (i in files) print i; }'`; \
|
||||||
|
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|
||||||
|
|| (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
|
||||||
|
|
||||||
|
mostlyclean-tags:
|
||||||
|
|
||||||
|
clean-tags:
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
-rm -f TAGS ID
|
||||||
|
|
||||||
|
maintainer-clean-tags:
|
||||||
|
|
||||||
|
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||||
|
|
||||||
|
subdir = src/apps/cyrus
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
here=`cd $(top_builddir) && pwd`; \
|
||||||
|
top_distdir=`cd $(top_distdir) && pwd`; \
|
||||||
|
distdir=`cd $(distdir) && pwd`; \
|
||||||
|
cd $(top_srcdir) \
|
||||||
|
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/apps/cyrus/Makefile
|
||||||
|
@for file in $(DISTFILES); do \
|
||||||
|
d=$(srcdir); \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||||
|
else \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
|
||||||
|
|
||||||
|
-include $(DEP_FILES)
|
||||||
|
|
||||||
|
mostlyclean-depend:
|
||||||
|
|
||||||
|
clean-depend:
|
||||||
|
|
||||||
|
distclean-depend:
|
||||||
|
-rm -rf .deps
|
||||||
|
|
||||||
|
maintainer-clean-depend:
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
@echo '$(COMPILE) -c $<'; \
|
||||||
|
$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
|
||||||
|
@-cp .deps/$(*F).pp .deps/$(*F).P; \
|
||||||
|
tr ' ' '\012' < .deps/$(*F).pp \
|
||||||
|
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
|
||||||
|
>> .deps/$(*F).P; \
|
||||||
|
rm .deps/$(*F).pp
|
||||||
|
|
||||||
|
%.lo: %.c
|
||||||
|
@echo '$(LTCOMPILE) -c $<'; \
|
||||||
|
$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
|
||||||
|
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
|
||||||
|
< .deps/$(*F).pp > .deps/$(*F).P; \
|
||||||
|
tr ' ' '\012' < .deps/$(*F).pp \
|
||||||
|
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
|
||||||
|
>> .deps/$(*F).P; \
|
||||||
|
rm -f .deps/$(*F).pp
|
||||||
|
info-am:
|
||||||
|
info: info-am
|
||||||
|
dvi-am:
|
||||||
|
dvi: dvi-am
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
installcheck-am:
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-exec-am: install-libLIBRARIES
|
||||||
|
install-exec: install-exec-am
|
||||||
|
|
||||||
|
install-data-am:
|
||||||
|
install-data: install-data-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
install: install-am
|
||||||
|
uninstall-am: uninstall-libLIBRARIES
|
||||||
|
uninstall: uninstall-am
|
||||||
|
all-am: Makefile $(LIBRARIES)
|
||||||
|
all-redirect: all-am
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||||
|
installdirs:
|
||||||
|
$(mkinstalldirs) $(DESTDIR)$(libdir)
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||||
|
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
mostlyclean-am: mostlyclean-libLIBRARIES mostlyclean-compile \
|
||||||
|
mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
|
||||||
|
mostlyclean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
clean-am: clean-libLIBRARIES clean-compile clean-libtool clean-tags \
|
||||||
|
clean-depend clean-generic mostlyclean-am
|
||||||
|
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
distclean-am: distclean-libLIBRARIES distclean-compile \
|
||||||
|
distclean-libtool distclean-tags distclean-depend \
|
||||||
|
distclean-generic clean-am
|
||||||
|
-rm -f libtool
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
|
||||||
|
maintainer-clean-am: maintainer-clean-libLIBRARIES \
|
||||||
|
maintainer-clean-compile maintainer-clean-libtool \
|
||||||
|
maintainer-clean-tags maintainer-clean-depend \
|
||||||
|
maintainer-clean-generic distclean-am
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
|
||||||
|
.PHONY: mostlyclean-libLIBRARIES distclean-libLIBRARIES \
|
||||||
|
clean-libLIBRARIES maintainer-clean-libLIBRARIES uninstall-libLIBRARIES \
|
||||||
|
install-libLIBRARIES mostlyclean-compile distclean-compile \
|
||||||
|
clean-compile maintainer-clean-compile mostlyclean-libtool \
|
||||||
|
distclean-libtool clean-libtool maintainer-clean-libtool tags \
|
||||||
|
mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \
|
||||||
|
distdir mostlyclean-depend distclean-depend clean-depend \
|
||||||
|
maintainer-clean-depend info-am info dvi-am dvi check check-am \
|
||||||
|
installcheck-am installcheck install-exec-am install-exec \
|
||||||
|
install-data-am install-data install-am install uninstall-am uninstall \
|
||||||
|
all-redirect all-am all installdirs mostlyclean-generic \
|
||||||
|
distclean-generic clean-generic maintainer-clean-generic clean \
|
||||||
|
mostlyclean distclean maintainer-clean
|
||||||
|
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
5
src/apps/cyrus/Makefile.am
Normal file
5
src/apps/cyrus/Makefile.am
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
LDADD=$(top_builddir)/build/libdfa.a $(top_builddir)/build/lib2pc.a
|
||||||
|
SOURCES=cyrusdb_lladd.c
|
||||||
|
lib_LIBRARIES=libcyrusdb_lladd.a
|
||||||
|
libcyrusdb_lladd_a_SOURCES=cyrusdb_lladd.c
|
||||||
|
AM_CFLAGS= -g -Wall -pedantic
|
492
src/apps/cyrus/cyrusdb_lladd.c
Normal file
492
src/apps/cyrus/cyrusdb_lladd.c
Normal file
|
@ -0,0 +1,492 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <config.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "cyrusdb.h"
|
||||||
|
#include "exitcodes.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
#include <lladd/transactional.h>
|
||||||
|
#include "../../pbl/jbhash.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct db {
|
||||||
|
jbHashTable_t *nameSpace;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct txn {
|
||||||
|
int tid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int dirExists(char *dir)
|
||||||
|
{
|
||||||
|
char *curDir = getcwd(NULL, 0);
|
||||||
|
int status = chdir(dir);
|
||||||
|
chdir(curDir);
|
||||||
|
free(curDir);
|
||||||
|
return (status == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *dbdirName = 0;
|
||||||
|
static int dbinit = 0;
|
||||||
|
static void openNameSpace(const char *filename, jbHashTable_t ** nameHT);
|
||||||
|
static void writeNameSpace(const char *filename, jbHashTable_t * nameHT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init() should be called once per process; no calls are legal until init() returns
|
||||||
|
*/
|
||||||
|
static int init(const char *dbdir, int myflags)
|
||||||
|
{
|
||||||
|
dbdirName = malloc(strlen(dbdir));
|
||||||
|
strcpy(dbdirName, dbdir);
|
||||||
|
if (!dirExists(dbdirName))
|
||||||
|
mkdir(dbdirName);
|
||||||
|
dbinit = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* done() should be called once per process; no calls are legal once done() starts. it is legal to call
|
||||||
|
* init() after done() returns to reset state
|
||||||
|
*/
|
||||||
|
static int done(void)
|
||||||
|
{
|
||||||
|
free(dbdirName);
|
||||||
|
dbdirName = 0;
|
||||||
|
dbinit = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* checkpoints this database environment */
|
||||||
|
static int mysync(void)
|
||||||
|
{
|
||||||
|
return 0; /* no need to checkpoint */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* archives this database environment, and specified databases into the specified directory
|
||||||
|
*/
|
||||||
|
static int archive(const char **fnames, const char *dirname)
|
||||||
|
{
|
||||||
|
/* looks like this copies the db file and the log to a new directory */
|
||||||
|
jbHashTable_t *oldHT, *newHT;
|
||||||
|
const char **list = fnames;
|
||||||
|
recordid loc;
|
||||||
|
static char archiveName[200];
|
||||||
|
static char data[600]; /* max is 600 now! should be a better system for this... */
|
||||||
|
static char curKey[80];
|
||||||
|
int xid, status, datalen, keylen;
|
||||||
|
struct txn **trans;
|
||||||
|
if (list != NULL) {
|
||||||
|
while (*list != NULL) {
|
||||||
|
openNameSpace(*list, &oldHT);
|
||||||
|
if (oldHT != 0) {
|
||||||
|
syslog(LOG_ERR, "DBERROR: error archiving database file: %s", *list);
|
||||||
|
return CYRUSDB_IOERROR;
|
||||||
|
}
|
||||||
|
/* theoretically, can use foreach here */
|
||||||
|
xid = Tbegin();
|
||||||
|
newHT = jbHtCreate(xid);
|
||||||
|
strcpy(archiveName, "archive/");
|
||||||
|
strcat(archiveName, *list);
|
||||||
|
writeNameSpace(archiveName,newHT);
|
||||||
|
for (datalen = jbHtFirst(xid, oldHT, data); datalen > 0; datalen = jbHtNext(xid, oldHT, data)) {
|
||||||
|
loc = Talloc(xid, datalen);
|
||||||
|
Tset(xid, loc, data);
|
||||||
|
keylen = jbHtCurrentKey(xid, oldHT, curKey);
|
||||||
|
jbHtInsert(xid, newHT, curKey, keylen, data, datalen);
|
||||||
|
}
|
||||||
|
Tcommit(xid);
|
||||||
|
free(newHT);
|
||||||
|
list++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pass in a filename and an unallocated hashtable, will return either a valid malloc'ed hashtable or null
|
||||||
|
* into nameHT
|
||||||
|
*/
|
||||||
|
static void openNameSpace(const char *filename, jbHashTable_t ** nameHT)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
FILE *fp = fopen(filename, "r");
|
||||||
|
recordid rid;
|
||||||
|
if (fp != 0) {
|
||||||
|
*nameHT = xmalloc(sizeof(jbHashTable_t));
|
||||||
|
for (count = 0; count < sizeof(recordid); count++)
|
||||||
|
*(char *)(&rid + count) = fgetc(fp);
|
||||||
|
fclose(fp);
|
||||||
|
Tread(69, rid, *nameHT);
|
||||||
|
if (!jbHtValid(69, *nameHT)) {
|
||||||
|
free(*nameHT);
|
||||||
|
*nameHT = NULL; /* not a valid hashtable, so return null */
|
||||||
|
}
|
||||||
|
} else { /* file does not exist */
|
||||||
|
fclose(fp);
|
||||||
|
*nameHT = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeNameSpace(const char *filename, jbHashTable_t * nameHT)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
FILE *fp = fopen(filename, "w");
|
||||||
|
if (fp != 0) {
|
||||||
|
for (count = 0; count < sizeof(recordid); count++)
|
||||||
|
fputc(*(char *)(&nameHT->store+count), fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open the specified database in the global environment */
|
||||||
|
static int myopen(const char *fname, int flags, struct db ** ret)
|
||||||
|
{
|
||||||
|
jbHashTable_t *nameHT;
|
||||||
|
static char filename[40];
|
||||||
|
struct db *newdb = xmalloc(sizeof(struct db));
|
||||||
|
int xid, i;
|
||||||
|
FILE *fp;
|
||||||
|
recordid rid;
|
||||||
|
assert(dbinit && fname && ret);
|
||||||
|
/* prepare the filename by concatenating the dbdir with the filename */
|
||||||
|
strcpy(filename, dbdirName);
|
||||||
|
strcat(filename, "/");
|
||||||
|
strncat(filename, fname, strlen(fname));
|
||||||
|
|
||||||
|
/* this is where you load the namespace for this db into memory */
|
||||||
|
openNameSpace(filename, &nameHT);
|
||||||
|
if (nameHT != NULL) {
|
||||||
|
/* that means we found a valid hashtable in the filename */
|
||||||
|
newdb->nameSpace = nameHT;
|
||||||
|
*ret = newdb;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* by this point */
|
||||||
|
|
||||||
|
|
||||||
|
/* if we've reached here, that means the HT didn't exist */
|
||||||
|
free(nameHT); /* get rid of the attempt to find the HT */
|
||||||
|
/* make a xid just for the creation of the namespace hashtable */
|
||||||
|
xid = Tbegin();
|
||||||
|
newdb->nameSpace = jbHtCreate(xid); /* make a new nameSpace just for this database */
|
||||||
|
rid = newdb->nameSpace->store; /* get the rid of this namespace to save to a file */
|
||||||
|
fp = fopen(filename, "w");
|
||||||
|
if (fp == 0) {
|
||||||
|
syslog(LOG_ERR, "DBERROR: opening %s for writing", filename);
|
||||||
|
return CYRUSDB_IOERROR;
|
||||||
|
}
|
||||||
|
for (i = 0; i < sizeof(recordid); i++)
|
||||||
|
fputc(*(char *)(&rid + i), fp);
|
||||||
|
fclose(fp); /* this flushes the location to disk */
|
||||||
|
Tcommit(xid); /* commit the transaction only when the intermediate step of recording the
|
||||||
|
* location of it has been flushed to disk */
|
||||||
|
/*
|
||||||
|
* note: this means it's possible to record an rid on disk without it actually being written there,
|
||||||
|
* so therefore check validity of HT next time
|
||||||
|
*/
|
||||||
|
*ret = newdb;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close the specified database */
|
||||||
|
static int myclose(struct db * db)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* since there are transactions, no need to do anything to them now should be all committed by this
|
||||||
|
* point just deallocate the hashtable
|
||||||
|
*/
|
||||||
|
assert(dbinit && db);
|
||||||
|
free(db->nameSpace);
|
||||||
|
free(db);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* what are the overall specifications? */
|
||||||
|
/*
|
||||||
|
* 'mydb': the database to act on 'key': the key to fetch. cyrusdb currently requires this to not have any
|
||||||
|
* of [\t\n\0] in keys 'keylen': length of the key 'data': where to put the data (generally won't have
|
||||||
|
* [\n\0]) 'datalen': how big is the data? 'mytid': may be NULL, in which case the fetch is not txn
|
||||||
|
* protected. if mytid != NULL && *mytid == NULL, begins a new txn if mytid != NULL && *mytid != NULL,
|
||||||
|
* continues an old txn
|
||||||
|
*
|
||||||
|
* transactions may lock the entire database on some backends. beware
|
||||||
|
*
|
||||||
|
* fetchlock() is identical to fetch() except gives a hint to the underlying database that the key/data being
|
||||||
|
* fetched will be modified soon. it is useless to use fetchlock() without a non-NULL mytid
|
||||||
|
*/
|
||||||
|
static int fetch(struct db * mydb,
|
||||||
|
const char *key, int keylen,
|
||||||
|
const char **data, int *datalen,
|
||||||
|
struct txn ** mytid)
|
||||||
|
{
|
||||||
|
recordid rid;
|
||||||
|
int xid, status;
|
||||||
|
assert(dbinit && mydb);
|
||||||
|
if (mytid != NULL && *mytid == NULL) { /* make a new transaction */
|
||||||
|
/* begin a new transaction */
|
||||||
|
*mytid = (struct txn *) xmalloc(sizeof(struct txn));
|
||||||
|
(*mytid)->tid = Tbegin();
|
||||||
|
xid = (*mytid)->tid;
|
||||||
|
} else if (mytid != NULL) { /* therefore *mytid!=NULL, continue an old txn */
|
||||||
|
xid = (*mytid)->tid;
|
||||||
|
} else if (mytid == NULL) {
|
||||||
|
/* not transaction protected */
|
||||||
|
xid = 69;
|
||||||
|
/*
|
||||||
|
* note, Tread shouldn't have xid needed, but it's there so put in junk xid
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
/* get the record given the key */
|
||||||
|
status = jbHtLookup(xid, mydb->nameSpace, key, keylen, &rid);
|
||||||
|
if (status == -1) {
|
||||||
|
/* invalid key! return error */
|
||||||
|
Tabort(xid);
|
||||||
|
if (mytid && *mytid)
|
||||||
|
free(*mytid);
|
||||||
|
return -1; /* what is the return for an error? */
|
||||||
|
}
|
||||||
|
Tread(xid, rid, *data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fetchlock(struct db * mydb,
|
||||||
|
const char *key, int keylen,
|
||||||
|
const char **data, int *datalen,
|
||||||
|
struct txn ** mytid)
|
||||||
|
{
|
||||||
|
/* for now, the same as fetch */
|
||||||
|
return fetch(mydb, key, keylen, data, datalen, mytid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* foreach: iterate through entries that start with 'prefix' if 'p' returns true, call 'cb'
|
||||||
|
*
|
||||||
|
* if 'cb' changes the database, these changes will only be visible if they are after the current database
|
||||||
|
* cursor. If other processes change the database (i.e. outside of a transaction) these changes may or may
|
||||||
|
* not be visible to the foreach()
|
||||||
|
*
|
||||||
|
* 'p' should be fast and should avoid blocking it should be safe to call other db routines inside of 'cb'.
|
||||||
|
* however, the "flat" backend is currently are not reentrant in this way unless you're using transactions
|
||||||
|
* and pass the same transaction to all db calls during the life of foreach()
|
||||||
|
*/
|
||||||
|
static int foreach(struct db * mydb,
|
||||||
|
char *prefix, int prefixlen,
|
||||||
|
foreach_p * p,
|
||||||
|
foreach_cb * cb, void *rock,
|
||||||
|
struct txn ** tid)
|
||||||
|
{
|
||||||
|
char data[600];
|
||||||
|
char curKey[80];
|
||||||
|
int datalen, keylen, xid, r;
|
||||||
|
if (tid && *tid)
|
||||||
|
xid = (*tid)->tid;
|
||||||
|
else
|
||||||
|
xid = 69;
|
||||||
|
assert(dbinit && mydb && cb);
|
||||||
|
for (datalen = jbHtFirst(xid, mydb->nameSpace, data); datalen > 0; datalen = jbHtNext(xid, mydb->nameSpace, data)) {
|
||||||
|
/* does this match our prefix? */
|
||||||
|
keylen = jbHtCurrentKey(xid, mydb->nameSpace, curKey);
|
||||||
|
if (prefixlen && memcmp(curKey, prefix, prefixlen))
|
||||||
|
continue;
|
||||||
|
/* else we have a match! */
|
||||||
|
if (p(rock, curKey, keylen, data, datalen)) {
|
||||||
|
/* we have a winner! */
|
||||||
|
r = cb(rock, curKey, keylen, data, datalen);
|
||||||
|
if (r != 0) {
|
||||||
|
if (r < 0) {
|
||||||
|
syslog(LOG_ERR, "DBERROR: foreach cb() failed");
|
||||||
|
}
|
||||||
|
/* don't mistake this for a db error -- WHY?? */
|
||||||
|
r = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mystore combines create and store and delete, flags: 0 = storing and nooverwrite 1 = storing and overwrite
|
||||||
|
* 2 = deleting
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int mystore(struct db * db,
|
||||||
|
const char *key, int keylen,
|
||||||
|
const char *data, int datalen,
|
||||||
|
struct txn ** tid, int flags)
|
||||||
|
{
|
||||||
|
int xid, status;
|
||||||
|
struct txn *newtxn;
|
||||||
|
recordid rid;
|
||||||
|
assert(dbinit && db && key && keylen);
|
||||||
|
/* check tid first!! if *mytid null, start a new transaction */
|
||||||
|
if (!tid) {
|
||||||
|
/* create a new transaction with no intention of committing it (ever) */
|
||||||
|
xid = Tbegin();
|
||||||
|
} else if (!*tid) {
|
||||||
|
/* make a new transaction */
|
||||||
|
newtxn = xmalloc(sizeof(struct txn));
|
||||||
|
newtxn->tid = Tbegin();
|
||||||
|
xid = newtxn->tid;
|
||||||
|
*tid = newtxn;
|
||||||
|
} else
|
||||||
|
xid = (*tid)->tid; /* transaction already exists */
|
||||||
|
/* first see if a variable of this key exists */
|
||||||
|
status = jbHtLookup(xid, db->nameSpace, key, keylen, &rid);
|
||||||
|
if (status == -1) { /* this variable doesn't exist yet */
|
||||||
|
if (flags != 2) { /* only add variable if you aren't deleting it, duh */
|
||||||
|
/* key doesn't exist, so make it and allocate space */
|
||||||
|
rid = Talloc(xid, datalen);
|
||||||
|
jbHtInsert(xid, db->nameSpace, key, keylen, &rid, sizeof(recordid));
|
||||||
|
} /* else if you are deleting this, nothing to do since variable never existed!
|
||||||
|
* yay! */
|
||||||
|
} else {
|
||||||
|
/* key exists */
|
||||||
|
switch (flags) {
|
||||||
|
case 0:
|
||||||
|
/* -- if no overwrite, return error */
|
||||||
|
Tabort(xid);
|
||||||
|
if (tid && *tid)
|
||||||
|
free(*tid);
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* delete: so remove it from namespace */
|
||||||
|
jbHtRemove(xid, db->nameSpace, key, keylen, NULL);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flags != 2)
|
||||||
|
Tset(xid, rid, data);
|
||||||
|
/* else Tdealloc(xid, rid); ** IS THERE A DEALLOC YET? ** */
|
||||||
|
if (!tid) /* was a one time transaction, commit it */
|
||||||
|
Tcommit(xid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Place entries in database create will not overwrite existing entries
|
||||||
|
*/
|
||||||
|
static int create(struct db * db,
|
||||||
|
const char *key, int keylen,
|
||||||
|
const char *data, int datalen,
|
||||||
|
struct txn ** tid)
|
||||||
|
{
|
||||||
|
return mystore(db, key, keylen, data, datalen, tid, 0); /* no overwrite, not deleting */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int store(struct db * db,
|
||||||
|
const char *key, int keylen,
|
||||||
|
const char *data, int datalen,
|
||||||
|
struct txn ** tid)
|
||||||
|
{
|
||||||
|
return mystore(db, key, keylen, data, datalen, tid, 1); /* overwrite, not deleting */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove entrys from the database */
|
||||||
|
static int delete(struct db * db,
|
||||||
|
const char *key, int keylen,
|
||||||
|
struct txn ** tid,
|
||||||
|
int force)
|
||||||
|
{ /* 1 = ignore not found errors */
|
||||||
|
return mystore(db, key, keylen, NULL, 0, tid, 2); /* overwrite (meaningless), deleting */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commit the transaction. When commit() returns, the tid will no longer be valid, regardless of if the
|
||||||
|
* commit succeeded or failed
|
||||||
|
*/
|
||||||
|
static int mycommit(struct txn * tid)
|
||||||
|
{
|
||||||
|
Tcommit(tid->tid);
|
||||||
|
assert(dbinit && tid);
|
||||||
|
free(tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mycommit_db(struct db * db, struct txn * tid)
|
||||||
|
{
|
||||||
|
return mycommit(tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Abort the transaction and invalidate the tid */
|
||||||
|
static int myabort(struct txn * tid)
|
||||||
|
{
|
||||||
|
assert(dbinit && tid);
|
||||||
|
Tabort(tid->tid);
|
||||||
|
free(tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int myabort_db(struct db * db, struct txn * tid)
|
||||||
|
{
|
||||||
|
return myabort(tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cyrusdb_backend cyrusdb_lladd =
|
||||||
|
{
|
||||||
|
"lladd", /* name */
|
||||||
|
|
||||||
|
&init,
|
||||||
|
&done,
|
||||||
|
&mysync,
|
||||||
|
&archive,
|
||||||
|
|
||||||
|
&myopen,
|
||||||
|
&myclose,
|
||||||
|
|
||||||
|
&fetch,
|
||||||
|
&fetchlock,
|
||||||
|
&foreach,
|
||||||
|
&create,
|
||||||
|
&store,
|
||||||
|
&delete,
|
||||||
|
|
||||||
|
&mycommit_db,
|
||||||
|
&myabort_db,
|
||||||
|
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
4
src/libdfa/Makefile.am
Normal file
4
src/libdfa/Makefile.am
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#LDADD=$(top_builddir)/build/transactional.a $(top_builddir)/build/libpbl.a
|
||||||
|
lib_LIBRARIES=libdfa.a
|
||||||
|
libdfa_a_SOURCES=libdfa.c monotree.c smash.c rw.c callbacks.c messages.c
|
||||||
|
AM_CFLAGS= -g -Wall -pedantic -std=gnu99
|
88
src/libdfa/callbacks.c
Normal file
88
src/libdfa/callbacks.c
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 "callbacks.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
state_name respond_once(NetworkSetup * ns, state_name type, Message * incoming_message, char * from) {
|
||||||
|
|
||||||
|
state_machine_id id;
|
||||||
|
state_name original_type = incoming_message->type;
|
||||||
|
incoming_message->type = type;
|
||||||
|
id = incoming_message->to_machine_id;
|
||||||
|
incoming_message->to_machine_id = incoming_message->from_machine_id;
|
||||||
|
incoming_message->from_machine_id = id;
|
||||||
|
|
||||||
|
send_message(ns, incoming_message, from);
|
||||||
|
|
||||||
|
incoming_message->type = original_type;
|
||||||
|
id = incoming_message->to_machine_id;
|
||||||
|
incoming_message->to_machine_id = incoming_message->from_machine_id;
|
||||||
|
incoming_message->from_machine_id = id;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
state_name tally(char ** broadcast_list, int host_count, char * bitSet, char * from) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
index= get_index(broadcast_list, host_count, from);
|
||||||
|
|
||||||
|
if(index < 0) {
|
||||||
|
printf("Received message from unknown recipient: %s\n", from);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
bitSet[index] = TRUE;
|
||||||
|
|
||||||
|
for(i = 0; i < host_count; i++) {
|
||||||
|
if(!bitSet[i]) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
75
src/libdfa/callbacks.h
Normal file
75
src/libdfa/callbacks.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <libdfa/libdfa.h>
|
||||||
|
/**
|
||||||
|
A covienence function that responds to an incoming message one
|
||||||
|
time. (Useful for sending ACK's, and then freeing a machine.)
|
||||||
|
@param ns The network setup that will be used to send the message.
|
||||||
|
@param type The 'local state' that the message should respond with
|
||||||
|
@param incoming_message The message that we're responding to. This can be a broadcast addess such as bc:1.
|
||||||
|
@param from The network address of that we're responding to.
|
||||||
|
@see NetworkSetup
|
||||||
|
*/
|
||||||
|
|
||||||
|
state_name respond_once(NetworkSetup * ns, state_name type, Message * incoming_message, char * from);
|
||||||
|
/**
|
||||||
|
A convienence function that keeps track of responses from multiple
|
||||||
|
machines. For example, this is used by two phase commit to count
|
||||||
|
PREPARED messages.
|
||||||
|
|
||||||
|
@param broadcast_list An array of strings containing the addresses
|
||||||
|
of the remote machines.
|
||||||
|
|
||||||
|
@param host_count The number of strings in broadcast_list
|
||||||
|
|
||||||
|
@param bitSet An array of host_count characters, each initialized
|
||||||
|
to zero. (as in (unsigned char)0, not '0') The application should
|
||||||
|
manage this memory, and only initializes it when its time to start
|
||||||
|
a fresh tally.
|
||||||
|
|
||||||
|
@param from The address of the remote machine we just recieved a
|
||||||
|
message from.
|
||||||
|
|
||||||
|
@return 1 if all hosts have responded, 0 otherwise.
|
||||||
|
*/
|
||||||
|
state_name tally(char ** broadcast_list, int host_count, char * bitSet, char * from);
|
||||||
|
|
765
src/libdfa/libdfa.c
Normal file
765
src/libdfa/libdfa.c
Normal file
|
@ -0,0 +1,765 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <libdfa/libdfa.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
void * run_request(DfaSet * dfaSet, state_machine_id machine_id);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DfaSet * dfaSet;
|
||||||
|
const Transition * transitions;
|
||||||
|
int transition_count;
|
||||||
|
const State * states;
|
||||||
|
state_name state_count;
|
||||||
|
rwl* lock;
|
||||||
|
} main_wrap_args;
|
||||||
|
|
||||||
|
void dfa_initialize_new(DfaSet * dfaSet, unsigned short port, int count) {
|
||||||
|
/*init_MonoTree(&(dfaSet->monoTree), count);*/
|
||||||
|
Tinit();
|
||||||
|
dfaSet->smash = init_Smash(count);
|
||||||
|
dfaSet->networkSetup.localport = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recover(DfaSet * dfaSet);
|
||||||
|
|
||||||
|
/*void nothing(int signo) {
|
||||||
|
/
|
||||||
|
This space left intentionally blank.
|
||||||
|
/
|
||||||
|
}*/
|
||||||
|
|
||||||
|
int dfa_reinitialize(DfaSet *dfaSet, char * localhost,
|
||||||
|
Transition transitions[], int transition_count,
|
||||||
|
State states[], state_name state_count) {
|
||||||
|
|
||||||
|
/* struct sigaction actions;
|
||||||
|
int rc;*/
|
||||||
|
|
||||||
|
|
||||||
|
dfaSet->lock = initlock();
|
||||||
|
dfaSet->states = states;
|
||||||
|
dfaSet->state_count = state_count;
|
||||||
|
dfaSet->transitions = transitions;
|
||||||
|
dfaSet->transition_count = transition_count;
|
||||||
|
|
||||||
|
|
||||||
|
/* memset(&actions, 0, sizeof(actions));
|
||||||
|
sigemptyset(&actions.sa_mask);
|
||||||
|
actions.sa_flags = 0;
|
||||||
|
actions.sa_handler = nothing;
|
||||||
|
|
||||||
|
rc = sigaction(SIGALRM,&actions,NULL);
|
||||||
|
if(rc < 0) {
|
||||||
|
perror("sigaction");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(init_network_broadcast(&(dfaSet->networkSetup), dfaSet->networkSetup.localport, localhost,
|
||||||
|
dfaSet->networkSetup.broadcast_lists,
|
||||||
|
dfaSet->networkSetup.broadcast_lists_count,
|
||||||
|
dfaSet->networkSetup.broadcast_list_host_count) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
writelock(dfaSet->lock, 100);
|
||||||
|
recover(dfaSet);
|
||||||
|
writeunlock(dfaSet->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Processes incoming events, and updates state machine states. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DfaSet *dfaSet;
|
||||||
|
state_machine_id machine_id;
|
||||||
|
} WorkerLoopArgs;
|
||||||
|
|
||||||
|
void * worker_loop(void * worker_loop_args);
|
||||||
|
pthread_t spawn_worker_thread(DfaSet * dfaSet, state_machine_id machine_id);
|
||||||
|
pthread_t spawn_main_thread(DfaSet * dfaSet);
|
||||||
|
|
||||||
|
void recover(DfaSet * dfaSet) {
|
||||||
|
/* int machine_count;
|
||||||
|
StateMachine* machines = enumerateMachines(&(dfaSet->monoTree), &machine_count);
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < machine_count; i++) {
|
||||||
|
machines[i].worker_thread = spawn_worker_thread(dfaSet, machines[i].machine_id);
|
||||||
|
} */
|
||||||
|
StateMachine sm_stack;
|
||||||
|
StateMachine * sm = &sm_stack;
|
||||||
|
StateMachine * this;
|
||||||
|
int ret = (jbHtFirst(dfaSet->smash->xid, dfaSet->smash->hash, sm) != -1);
|
||||||
|
|
||||||
|
|
||||||
|
while(ret) {
|
||||||
|
this = getSmash(dfaSet->smash, sm->machine_id);
|
||||||
|
printf("StateMachine %ld\n", sm->machine_id);
|
||||||
|
this->worker_thread = spawn_worker_thread(dfaSet, sm->machine_id);
|
||||||
|
ret = (jbHtNext(dfaSet->smash->xid, dfaSet->smash->hash, sm) != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void* main_loop(DfaSet *dfaSet) {
|
||||||
|
|
||||||
|
Message * message = malloc(sizeof(Message));
|
||||||
|
char * from = malloc(sizeof(char) * MAX_ADDRESS_LENGTH);
|
||||||
|
NetworkSetup * networkSetup = malloc(sizeof(NetworkSetup));
|
||||||
|
int recieved_message = 0;
|
||||||
|
|
||||||
|
/* StateMachine stateMachine_stack; */
|
||||||
|
StateMachine * stateMachine; /* = &stateMachine_stack; */
|
||||||
|
|
||||||
|
|
||||||
|
writelock(dfaSet->lock, 300);
|
||||||
|
memcpy(networkSetup, &(dfaSet->networkSetup), sizeof(NetworkSetup));
|
||||||
|
writeunlock(dfaSet->lock);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
int i;
|
||||||
|
state_name new_state, current_state;
|
||||||
|
/* int ret;*/
|
||||||
|
int new_machine = 0;
|
||||||
|
|
||||||
|
/*Listen on socket... */
|
||||||
|
if(recieved_message) {
|
||||||
|
/* if(stateMachine != NULL) {
|
||||||
|
setSmash(dfaSet->smash, stateMachine->machine_id);
|
||||||
|
} */
|
||||||
|
writeunlock(dfaSet->lock);
|
||||||
|
recieved_message = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(receive_message(networkSetup, message, from) <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
recieved_message = 1;
|
||||||
|
|
||||||
|
/* The commented out, more complex locking scheme does not work,
|
||||||
|
because freeMachine (called by worker threads) invalidates
|
||||||
|
stateMachine pointers, so this loop really needs a global
|
||||||
|
write lock. */
|
||||||
|
/* readlock(dfaSet->lock, 200); */
|
||||||
|
|
||||||
|
writelock(dfaSet->lock, 200);
|
||||||
|
|
||||||
|
stateMachine = getSmash(dfaSet->smash, message->to_machine_id);
|
||||||
|
/* printf("Lookup %ld, ret = %d\n", message->to_machine_id, ret); */
|
||||||
|
/* stateMachine = getMachine(&(dfaSet->monoTree), message->to_machine_id); */
|
||||||
|
/* if(stateMachine != NULL) {
|
||||||
|
/ * Grab the lock now. * /
|
||||||
|
pthread_mutex_lock(&(stateMachine->mutex));
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* This is the only thread that can write to the monoTree, so we
|
||||||
|
don't need to worry that someone else will create the
|
||||||
|
stateMachine, so we can safely release all locks if the
|
||||||
|
stateMachine was null, and not worry about race conditions. */
|
||||||
|
|
||||||
|
/* readunlock(dfaSet->lock); */
|
||||||
|
|
||||||
|
/* TODO: Check states to make sure they actually exist? */
|
||||||
|
|
||||||
|
if(stateMachine == NULL) {
|
||||||
|
|
||||||
|
/*writelock(dfaSet->lock, 600);*/
|
||||||
|
|
||||||
|
printf("Allocate machine %ld->", message->to_machine_id); fflush(NULL);
|
||||||
|
|
||||||
|
if(message->to_machine_id == NULL_MACHINE) {
|
||||||
|
|
||||||
|
stateMachine = allocSmash(dfaSet->smash);
|
||||||
|
|
||||||
|
/*stateMachine = allocMachine(&(dfaSet->monoTree));*/
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* TODO: Check id. */
|
||||||
|
/*stateMachine = insertMachine(&(dfaSet->monoTree), message->to_machine_id); */
|
||||||
|
|
||||||
|
stateMachine = insertSmash(dfaSet->smash, message->to_machine_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stateMachine == NULL) {
|
||||||
|
|
||||||
|
|
||||||
|
/*writeunlock(dfaSet->lock);*/
|
||||||
|
|
||||||
|
printf("Too many state machines. Dropping request for new one.\n");
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* printf("machine->id:%ld\n", stateMachine->machine_id); */
|
||||||
|
}
|
||||||
|
|
||||||
|
new_machine = 1;
|
||||||
|
|
||||||
|
|
||||||
|
/* Done with monotree for now. */
|
||||||
|
|
||||||
|
/* Grab a write lock on our machine before releasing the global
|
||||||
|
write lock, so that its worker thread doesn't get a hold of
|
||||||
|
it. */
|
||||||
|
|
||||||
|
/*pthread_mutex_lock(&(stateMachine->mutex));*/
|
||||||
|
|
||||||
|
/*writeunlock(dfaSet->lock);*/
|
||||||
|
|
||||||
|
stateMachine->worker_thread = (pid_t)NULL;
|
||||||
|
|
||||||
|
stateMachine->page = NULL;
|
||||||
|
stateMachine->page_id.page = 0; /* TODO: Is there such a thing as a null page?? */
|
||||||
|
stateMachine->page_id.slot = 0;
|
||||||
|
stateMachine->page_id.size = 0;
|
||||||
|
|
||||||
|
current_state = NULL_STATE;
|
||||||
|
} else {
|
||||||
|
current_state = stateMachine->current_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point, we hold stateMachine->mutex and no other locks. */
|
||||||
|
|
||||||
|
new_state = current_state;
|
||||||
|
|
||||||
|
/* Find the appropriate transition */
|
||||||
|
|
||||||
|
assert(message->to_machine_id == stateMachine->machine_id || message->to_machine_id == NULL_MACHINE);
|
||||||
|
|
||||||
|
for(i = 0; i< dfaSet->transition_count; i++) {
|
||||||
|
if(dfaSet->transitions[i].remote_state == message->type &&
|
||||||
|
dfaSet->transitions[i].pre_state == current_state) {
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i == dfaSet->transition_count) {
|
||||||
|
|
||||||
|
printf("%ld received: %ld-%d:%d->? (bad message)\n", stateMachine->machine_id, message->from_machine_id,
|
||||||
|
message->type, current_state);
|
||||||
|
/*pthread_mutex_unlock(&(stateMachine->mutex));*/
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(dfaSet->transitions[i].fcn_ptr == NULL) {
|
||||||
|
|
||||||
|
new_state = dfaSet->transitions[i].post_state;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Evaluate callback -- This produces a new state, and
|
||||||
|
overwrites m with a new message for the state machine. */
|
||||||
|
|
||||||
|
int ret = (dfaSet->transitions[i].fcn_ptr)(dfaSet, stateMachine, message, from);
|
||||||
|
|
||||||
|
if (dfaSet->transitions[i].post_state == OVERRIDDEN_STATE) {
|
||||||
|
if( ret != OVERRIDDEN_STATE) {
|
||||||
|
|
||||||
|
new_state = ret;
|
||||||
|
|
||||||
|
} /* else leave new_state alone; the transition failed. */
|
||||||
|
} else if (ret) {
|
||||||
|
|
||||||
|
new_state = dfaSet->transitions[i].post_state;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Update machine state. */
|
||||||
|
|
||||||
|
if(new_state == NULL_STATE) {
|
||||||
|
|
||||||
|
/* Time to de-allocate machine */
|
||||||
|
|
||||||
|
if(stateMachine->worker_thread == (pid_t)NULL) {
|
||||||
|
|
||||||
|
/* No worker thread, so just deallocate, and move on */
|
||||||
|
/* Note, that at this point, we hold the mutex on the state machine, and the global write lock. */
|
||||||
|
/*writelock(dfaSet->lock,500);
|
||||||
|
pthread_mutex_unlock(&(stateMachine->mutex));*/
|
||||||
|
|
||||||
|
/*freeMachine(&(dfaSet->monoTree),
|
||||||
|
stateMachine->machine_id); */
|
||||||
|
freeSmash(dfaSet->smash, stateMachine->machine_id);
|
||||||
|
|
||||||
|
/*writeunlock(dfaSet->lock);*/
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* NULL_STATE_TOMBSTONE tells the worker thread that it's
|
||||||
|
time to shut down. (NULL_STATE is reserved by monoTree
|
||||||
|
for machines that have already been deleted..) */
|
||||||
|
|
||||||
|
new_state = NULL_STATE_TOMBSTONE;
|
||||||
|
}
|
||||||
|
assert(!new_machine);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_state != current_state) {
|
||||||
|
|
||||||
|
printf("%ld transitioned on: %ld-%d:%d->%d from %s\n", stateMachine->machine_id, message->from_machine_id,
|
||||||
|
dfaSet->transitions[i].remote_state, dfaSet->transitions[i].pre_state, dfaSet->transitions[i].post_state, from);
|
||||||
|
printf(" -> %d %ld\n", new_state, message->from_machine_id);
|
||||||
|
|
||||||
|
assert(new_state != NULL_STATE);
|
||||||
|
stateMachine->current_state = new_state;
|
||||||
|
stateMachine->last_transition = time(NULL);
|
||||||
|
|
||||||
|
/* TODO: Is this general enough? The transition function is
|
||||||
|
able to overwrite both variables, so it should be
|
||||||
|
good enough. */
|
||||||
|
|
||||||
|
memcpy(&(stateMachine->message_recipient), from, MAX_ADDRESS_LENGTH);
|
||||||
|
memcpy(&(stateMachine->message), message, sizeof(Message));
|
||||||
|
|
||||||
|
/* We don't want to just swap the sender and recipient,
|
||||||
|
since we might have just allocated this machine. If not,
|
||||||
|
then the original message's recipient should be the
|
||||||
|
same as stateMachine->machine_id anyway.
|
||||||
|
|
||||||
|
At any rate, the transition function should overwrite
|
||||||
|
message->from_machine_id to change the machine that the
|
||||||
|
state machine will deal with.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
stateMachine->message.from_machine_id = stateMachine->machine_id;
|
||||||
|
stateMachine->message.to_machine_id = message->from_machine_id;
|
||||||
|
|
||||||
|
/* TODO: Force if necessary.*/
|
||||||
|
|
||||||
|
if(dfaSet->transitions[i].force) {
|
||||||
|
setSmash(dfaSet->smash, stateMachine->machine_id);
|
||||||
|
forceSmash(dfaSet->smash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*stateMachine->pending++; */
|
||||||
|
|
||||||
|
/* setSmash(dfaSet->smash, stateMachine->machine_id); */
|
||||||
|
|
||||||
|
|
||||||
|
/* Fork or signal the process if there already is one. */
|
||||||
|
|
||||||
|
if(stateMachine->worker_thread == (pthread_t)NULL) {
|
||||||
|
/* assert (getMachine(&(dfaSet->monoTree), stateMachine->machine_id) == stateMachine); */
|
||||||
|
assert ((stateMachine->current_state != NULL_STATE) &&
|
||||||
|
(stateMachine->current_state != NULL_STATE_TOMBSTONE));
|
||||||
|
|
||||||
|
stateMachine->worker_thread = spawn_worker_thread(dfaSet, stateMachine->machine_id);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* pthread_cond_t * cond;
|
||||||
|
pthread_cond_t cond_copy;
|
||||||
|
|
||||||
|
pthread_kill (stateMachine->worker_thread, SIGALRM);
|
||||||
|
pthread_cond_signal (&(stateMachine->sleepCond)); */
|
||||||
|
/* printf("Waking worker...\n"); */
|
||||||
|
|
||||||
|
/* memcpy(&cond_copy, &(stateMachine->sleepCond), sizeof(pthread_cond_t)); */
|
||||||
|
|
||||||
|
pthread_cond_broadcast (stateMachine->sleepCond); /* TODO: Signal should be adequate.. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* setSmash(dfaSet->smash, stateMachine->machine_id); */
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void * inner_worker_loop(void * arg_void) {
|
||||||
|
|
||||||
|
WorkerLoopArgs * arg = arg_void;
|
||||||
|
/* int ret; */
|
||||||
|
DfaSet * dfaSet = arg->dfaSet;
|
||||||
|
const state_machine_id machine_id = arg->machine_id;
|
||||||
|
/* pthread_cond_t cond_copy;
|
||||||
|
pthread_mutex_t mutex_copy; */
|
||||||
|
|
||||||
|
int timeout = 0; /* Run through the loop immediately the first time around. */
|
||||||
|
int state = 0;
|
||||||
|
/* int tries = 0; */
|
||||||
|
/* StateMachine stateMachine_stack; */
|
||||||
|
StateMachine* stateMachine; /* = &stateMachine_stack; */
|
||||||
|
|
||||||
|
|
||||||
|
free(arg_void);
|
||||||
|
|
||||||
|
readlock(dfaSet->lock, machine_id);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
stateMachine = getSmash(dfaSet->smash, machine_id);
|
||||||
|
|
||||||
|
|
||||||
|
/* stateMachine = getMachine(&(dfaSet->monoTree), machine_id); */
|
||||||
|
/* assert(stateMachine != NULL); */
|
||||||
|
/* assert(ret); */
|
||||||
|
|
||||||
|
/* memcpy(&mutex_copy, &(stateMachine->mutex), sizeof(pthread_mutex_t));
|
||||||
|
memcpy(&cond_copy, &(stateMachine->sleepCond), sizeof(pthread_cond_t)); */
|
||||||
|
|
||||||
|
pthread_mutex_lock(stateMachine->mutex);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
state_name i, state_idx;
|
||||||
|
|
||||||
|
/** SIGALRM will make sleep return immediately (I hope!)*/
|
||||||
|
|
||||||
|
/* printf("pending: %ld, %d\n", stateMachine->machine_id, stateMachine->pending); */
|
||||||
|
|
||||||
|
if(1|| !stateMachine->pending) { /* If no pending messages, go to sleep */
|
||||||
|
struct timeval now;
|
||||||
|
struct timespec timeout_spec;
|
||||||
|
|
||||||
|
pthread_cond_t * cond;
|
||||||
|
pthread_mutex_t * mutex;
|
||||||
|
|
||||||
|
long usec;
|
||||||
|
|
||||||
|
cond = stateMachine->sleepCond;
|
||||||
|
mutex = stateMachine->mutex;
|
||||||
|
|
||||||
|
/* setSmash(dfaSet->smash, stateMachine); */ /* No longer write to stateMacine in this loop..Well
|
||||||
|
, we do, but we can safely lose that change. */
|
||||||
|
readunlock(dfaSet->lock);
|
||||||
|
|
||||||
|
/* A note on locking: This loop maintains a read lock everywhere
|
||||||
|
except for this call to sleep, and upon termination when it
|
||||||
|
requires a write lock. */
|
||||||
|
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
usec = now.tv_usec + timeout;
|
||||||
|
|
||||||
|
if(usec > 1000000) {
|
||||||
|
now.tv_sec++;
|
||||||
|
usec-=1000000;
|
||||||
|
}
|
||||||
|
timeout_spec.tv_sec = now.tv_sec;/* + timeout; */
|
||||||
|
timeout_spec.tv_nsec = 1000 * usec; /*now.tv_usec * 1000; */
|
||||||
|
|
||||||
|
|
||||||
|
rc = pthread_cond_timedwait (cond, mutex, &timeout_spec );
|
||||||
|
|
||||||
|
/* rc = sleep(timeout); */
|
||||||
|
|
||||||
|
|
||||||
|
if(rc == EINVAL) {
|
||||||
|
perror("pthread");
|
||||||
|
} /*else if (rc != ETIMEDOUT) {
|
||||||
|
printf("Worker signaled.\n");
|
||||||
|
} else {
|
||||||
|
printf("Timed out.\n");
|
||||||
|
}*/
|
||||||
|
readlock(dfaSet->lock, machine_id);
|
||||||
|
|
||||||
|
/* Some other thread may have invalidated our pointer while we
|
||||||
|
were sleeping witout a lock... no longer true, *but* since
|
||||||
|
our pointer is local to this thread, we still need to re-read
|
||||||
|
from the store.*/
|
||||||
|
|
||||||
|
/*stateMachine = getMachine(&(dfaSet->monoTree), machine_id);*/
|
||||||
|
assert(stateMachine == getSmash(dfaSet->smash, machine_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stateMachine = getMachine(&(dfaSet->monoTree), machine_id); */
|
||||||
|
/* This can't happen! */
|
||||||
|
/* assert(ret); */
|
||||||
|
/* assert(stateMachine != NULL); */
|
||||||
|
|
||||||
|
/* pthread_mutex_lock(&(stateMachine->mutex)); */
|
||||||
|
|
||||||
|
/* if(stateMachine->pending > 0) {
|
||||||
|
|
||||||
|
if(stateMachine->pending > 0) {
|
||||||
|
stateMachine->pending--;
|
||||||
|
}
|
||||||
|
assert (stateMachine->pending >= 0);
|
||||||
|
|
||||||
|
}*/
|
||||||
|
/* pthread_mutex_unlock(&(stateMachine->mutex)); */
|
||||||
|
|
||||||
|
/* printf("Current State: %d, %d\n", stateMachine->current_state, NULL_STATE_TOMBSTONE); */
|
||||||
|
if(stateMachine->current_state == NULL_STATE_TOMBSTONE) {
|
||||||
|
/* printf("Breaking\n"); */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = stateMachine->current_state;
|
||||||
|
stateMachine->message.type = stateMachine->current_state;
|
||||||
|
timeout = 690000 +(int) (300000.0*rand()/(RAND_MAX+1.0));
|
||||||
|
/* timeout = 1; */
|
||||||
|
for(i = 0; i < dfaSet->state_count; i++) {
|
||||||
|
if(dfaSet->states[i].name == stateMachine->current_state) {
|
||||||
|
state_idx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if(dfaSet->states[stateMachine->current_state].abort_fcn && (time(NULL) - stateMachine->last_transition > 100)) {
|
||||||
|
if(dfaSet->states[state_idx].abort_fcn && (time(NULL) - stateMachine->last_transition > 100)) {
|
||||||
|
((callback_fcn*)dfaSet->states[state_idx].abort_fcn)(dfaSet, stateMachine, &(stateMachine->message), NULL);
|
||||||
|
freeMachine(&(dfaSet->monoTree), machine_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/ * if((time(NULL) - stateMachine->last_transition > abort_timeout) && abort_fcn!=NULL) {
|
||||||
|
abort_fcn(dfaSet, stateMachine, &(stateMachine->message), NULL); * /
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/* TODO: Copy this stuff into buffers w/ memcopy, unlock, then call send_message. */
|
||||||
|
|
||||||
|
/* printf("Worker loop for state machine: %ld still active\n", machine_id); */
|
||||||
|
|
||||||
|
send_message(&(dfaSet->networkSetup), &(stateMachine->message), stateMachine->message_recipient);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setSmash(dfaSet->smash, stateMachine->machine_id);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(stateMachine->mutex);
|
||||||
|
|
||||||
|
readunlock(dfaSet->lock);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * worker_loop(void * arg_void) {
|
||||||
|
|
||||||
|
WorkerLoopArgs * arg = arg_void;
|
||||||
|
/* StateMachine stateMachine_stack; */
|
||||||
|
StateMachine * stateMachine; /* = &stateMachine_stack; */
|
||||||
|
DfaSet * dfaSet = arg->dfaSet;
|
||||||
|
state_machine_id machine_id = arg->machine_id;
|
||||||
|
|
||||||
|
readlock(dfaSet->lock, machine_id);
|
||||||
|
|
||||||
|
/* printf("Worker loop: %ld\n", machine_id); */
|
||||||
|
|
||||||
|
stateMachine = getSmash(dfaSet->smash, machine_id);
|
||||||
|
|
||||||
|
/* stateMachine = getMachine(&(dfaSet->monoTree), machine_id); */
|
||||||
|
/* assert(stateMachine != NULL); */
|
||||||
|
assert(stateMachine->machine_id == machine_id);
|
||||||
|
|
||||||
|
/* pthread_detach gets angry if the current process recieves a
|
||||||
|
signal. How to handle this properly? Can the main thread
|
||||||
|
wait until this thread detaches successfully? (Do we need a lock somewhere?) */
|
||||||
|
if(pthread_detach(stateMachine->worker_thread) != 0) {
|
||||||
|
perror("pthread_detach");
|
||||||
|
}
|
||||||
|
|
||||||
|
readunlock(dfaSet->lock);
|
||||||
|
inner_worker_loop(arg_void);
|
||||||
|
|
||||||
|
/* fflush(NULL); */
|
||||||
|
|
||||||
|
writelock(dfaSet->lock, machine_id);
|
||||||
|
printf("Freeing machine %ld\n", machine_id);
|
||||||
|
|
||||||
|
/* pthread_mutex_lock(&(stateMachine->mutex)); */
|
||||||
|
/*freeMachine(&(dfaSet->monoTree), machine_id); */
|
||||||
|
freeSmash(dfaSet->smash, machine_id);
|
||||||
|
/* pthread_mutex_unlock(&(stateMachine->mutex)); */
|
||||||
|
writeunlock(dfaSet->lock);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t spawn_main_thread(DfaSet * dfaSet) {
|
||||||
|
pthread_t worker_thread;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pthread_create(&worker_thread, NULL, (void*(*)(void*))&main_loop, dfaSet);
|
||||||
|
|
||||||
|
if(ret != 0) {
|
||||||
|
perror("libdfa: pthread_create:");
|
||||||
|
fflush(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return worker_thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t spawn_worker_thread(DfaSet * dfaSet, state_machine_id machine_id) {
|
||||||
|
|
||||||
|
/* Do we need to malloc a new worker_loop_args for each thread?
|
||||||
|
TODO: Should this be freed? Is it already?
|
||||||
|
*/
|
||||||
|
pthread_t worker_thread;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
WorkerLoopArgs ** worker_loop_args = malloc(sizeof(WorkerLoopArgs*));
|
||||||
|
|
||||||
|
|
||||||
|
*worker_loop_args = malloc(sizeof(WorkerLoopArgs));
|
||||||
|
|
||||||
|
|
||||||
|
printf("spawn_worker_thread(state_machine_id=%ld)\n", machine_id);
|
||||||
|
|
||||||
|
(*worker_loop_args)->dfaSet = dfaSet;
|
||||||
|
(*worker_loop_args)->machine_id = machine_id;
|
||||||
|
|
||||||
|
ret = pthread_create(&worker_thread, NULL, &worker_loop, *worker_loop_args);
|
||||||
|
|
||||||
|
if(ret != 0) {
|
||||||
|
perror("libdfa: pthread_create:");
|
||||||
|
worker_thread = (pthread_t)NULL;
|
||||||
|
fflush(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return worker_thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * request(DfaSet * dfaSet, state_name start_state, char * recipient_addr, state_machine_id recipient_machine_id, Message * message) {
|
||||||
|
/* StateMachine initial_sm_stack; */
|
||||||
|
StateMachine * initial_sm; /* = &initial_sm_stack; */
|
||||||
|
state_machine_id machine_id;
|
||||||
|
int ret;
|
||||||
|
writelock(dfaSet->lock, 600);
|
||||||
|
|
||||||
|
|
||||||
|
/* initial_sm = allocMachine(&(dfaSet->monoTree)); */
|
||||||
|
initial_sm = allocSmash(dfaSet->smash);
|
||||||
|
if(initial_sm == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* if(!ret) {
|
||||||
|
return NULL;
|
||||||
|
} */
|
||||||
|
assert(start_state != NULL_STATE);
|
||||||
|
|
||||||
|
if(message != NULL) {
|
||||||
|
|
||||||
|
memcpy(&(initial_sm->message), message, sizeof(Message));
|
||||||
|
}
|
||||||
|
|
||||||
|
initial_sm->current_state = start_state;
|
||||||
|
initial_sm->message.from_machine_id = initial_sm->machine_id;
|
||||||
|
initial_sm->message.to_machine_id = recipient_machine_id;
|
||||||
|
initial_sm->message.type = start_state;
|
||||||
|
|
||||||
|
strcpy(initial_sm->message.initiator, dfaSet->networkSetup.localhost);
|
||||||
|
initial_sm->message.initiator_machine_id = initial_sm->machine_id;
|
||||||
|
|
||||||
|
strcpy(initial_sm->message_recipient, recipient_addr);
|
||||||
|
machine_id = initial_sm->machine_id;
|
||||||
|
/* setSmash(dfaSet->smash, initial_sm->machine_id); */
|
||||||
|
writeunlock(dfaSet->lock);
|
||||||
|
|
||||||
|
ret = (int)run_request(dfaSet, machine_id);
|
||||||
|
|
||||||
|
|
||||||
|
writelock(dfaSet->lock, machine_id);
|
||||||
|
assert(initial_sm == getSmash(dfaSet->smash, machine_id));
|
||||||
|
if(message != NULL) {
|
||||||
|
|
||||||
|
memcpy(message, &(initial_sm->message), sizeof(Message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* freeMachine(&(dfaSet->monoTree), initial_sm->machine_id); */
|
||||||
|
freeSmash(dfaSet->smash, initial_sm->machine_id);
|
||||||
|
writeunlock(dfaSet->lock);
|
||||||
|
|
||||||
|
return (void*)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * run_request(DfaSet * dfaSet, state_machine_id machine_id) {
|
||||||
|
void * ret;
|
||||||
|
WorkerLoopArgs * worker_loop_args = malloc(sizeof(WorkerLoopArgs));
|
||||||
|
/* StateMachine machine_stack; */
|
||||||
|
StateMachine * machine; /* = &machine_stack; */
|
||||||
|
|
||||||
|
readlock(dfaSet->lock, 600);
|
||||||
|
|
||||||
|
machine = getSmash(dfaSet->smash, machine_id);
|
||||||
|
/* machine= getMachine(&(dfaSet->monoTree), machine_id); */
|
||||||
|
|
||||||
|
worker_loop_args->dfaSet = dfaSet;
|
||||||
|
worker_loop_args->machine_id = machine_id;
|
||||||
|
|
||||||
|
machine->worker_thread = pthread_self();
|
||||||
|
/* setSmash(dfaSet->smash, machine->machine_id); */
|
||||||
|
readunlock(dfaSet->lock);
|
||||||
|
|
||||||
|
|
||||||
|
ret = inner_worker_loop(worker_loop_args);
|
||||||
|
|
||||||
|
return (void*)ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DfaSet * dfa_malloc(int count, short port,
|
||||||
|
char *** broadcast_lists,
|
||||||
|
int broadcast_lists_count,
|
||||||
|
int * broadcast_list_host_count) {
|
||||||
|
DfaSet * dfaSet = calloc(1, sizeof(DfaSet));
|
||||||
|
/* dfaSet->monoTree.buffer = calloc(count, sizeof(StateMachine)); */
|
||||||
|
dfa_initialize_new(dfaSet, port, count);
|
||||||
|
|
||||||
|
dfaSet->networkSetup.broadcast_lists = broadcast_lists;
|
||||||
|
dfaSet->networkSetup.broadcast_lists_count = broadcast_lists_count;
|
||||||
|
dfaSet->networkSetup.broadcast_list_host_count = broadcast_list_host_count;
|
||||||
|
|
||||||
|
return dfaSet;
|
||||||
|
}
|
||||||
|
|
318
src/libdfa/messages.c
Normal file
318
src/libdfa/messages.c
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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/socket.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <libdfa/messages.h>
|
||||||
|
|
||||||
|
char * parse_addr(const char * address) {
|
||||||
|
char * strtok_buf = NULL;
|
||||||
|
char * addr_copy = strdup(address);
|
||||||
|
char * addr_s;
|
||||||
|
|
||||||
|
if(addr_copy == NULL) {
|
||||||
|
perror("Out of memory in send_message");
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_s = strtok_r(addr_copy, ":", &strtok_buf);
|
||||||
|
|
||||||
|
if(addr_s == NULL) {
|
||||||
|
printf("Invalid address (%s) passed into parse_addr", address);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The caller needs to call free on the pointer we return. That's the same pointer as addr_copy. */
|
||||||
|
|
||||||
|
/* addr_copy = strdup(addr_copy); */
|
||||||
|
/* free(addr_copy); */
|
||||||
|
|
||||||
|
assert(addr_copy == addr_s);
|
||||||
|
|
||||||
|
return addr_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
short parse_port(const char * address) {
|
||||||
|
char * strtok_buf = NULL;
|
||||||
|
char * addr_copy = strdup(address);
|
||||||
|
short port;
|
||||||
|
char * port_s;
|
||||||
|
|
||||||
|
if(addr_copy == NULL) {
|
||||||
|
perror("Out of memory in send_message");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This sets port_s to addr. The next copy returns the port */
|
||||||
|
port_s = strtok_r(addr_copy, ":", &strtok_buf);
|
||||||
|
|
||||||
|
if(port_s == NULL) {
|
||||||
|
printf("Invalid address (%s) passed into parse_port", address);
|
||||||
|
assert(0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
port_s = strtok_r(NULL, ":", &strtok_buf);
|
||||||
|
|
||||||
|
if(port_s == NULL) {
|
||||||
|
printf("Invalid address (%s) passed into parse_port", address);
|
||||||
|
assert(0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
port = atoi(port_s);
|
||||||
|
free(addr_copy);
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* code to establish a socket; originally from bzs@bu-cs.bu.edu */
|
||||||
|
|
||||||
|
int establish(unsigned short portnum) {
|
||||||
|
/* char myname[HOST_NAME_MAX+1]; */
|
||||||
|
int s;
|
||||||
|
|
||||||
|
struct sockaddr_in sa;
|
||||||
|
sa.sin_family = AF_INET;
|
||||||
|
sa.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
sa.sin_port= htons(portnum); /* this is our port number */
|
||||||
|
|
||||||
|
if ((s= socket(AF_INET, SOCK_DGRAM, 0)) < 0) { /* create socket */
|
||||||
|
perror("establish:socket()");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bind address to socket */
|
||||||
|
|
||||||
|
if (bind(s,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0) {
|
||||||
|
perror("establish:bind()");
|
||||||
|
close(s);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(s, 5); /* max # of queued connects */
|
||||||
|
return(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int init_network(NetworkSetup * ns, unsigned short portnum) {
|
||||||
|
return init_network_broadcast(ns, portnum, NULL, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
int init_network_broadcast(NetworkSetup * ns, unsigned short portnum, char * localhost, char *** broadcast_lists,
|
||||||
|
int broadcast_lists_count, int * broadcast_list_host_count) {
|
||||||
|
|
||||||
|
ns->localport = portnum;
|
||||||
|
ns->localhost = localhost;
|
||||||
|
ns->broadcast_lists = broadcast_lists;
|
||||||
|
ns->broadcast_lists_count = broadcast_lists_count;
|
||||||
|
ns->broadcast_list_host_count = broadcast_list_host_count;
|
||||||
|
|
||||||
|
return (ns->socket = establish(portnum));
|
||||||
|
|
||||||
|
}
|
||||||
|
int __send_message(const NetworkSetup *ns, Message *message, const char *to) ;
|
||||||
|
|
||||||
|
int send_message(const NetworkSetup *ns, Message *message, const char *to) {
|
||||||
|
|
||||||
|
return __send_message(ns, message, to);
|
||||||
|
}
|
||||||
|
int _send_message(const NetworkSetup *ns, Message *message, const char *to);
|
||||||
|
|
||||||
|
|
||||||
|
int __send_message(const NetworkSetup *ns, Message *message, const char *to) {
|
||||||
|
|
||||||
|
|
||||||
|
printf("Sending %ld-%d: to %s:%ld\n", message->from_machine_id, message->type ,to, message->to_machine_id);
|
||||||
|
|
||||||
|
if(strncmp(to, "bc:", 3)==0) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int list_number = parse_port(to);
|
||||||
|
|
||||||
|
if(list_number < 0 || list_number >= ns->broadcast_lists_count) {
|
||||||
|
printf("Invalid list number %d passed into send_message: %s\n", list_number, to);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(ns->broadcast_list_host_count[list_number] == 0) {
|
||||||
|
printf("Sending to empty broadcast list! Address was %s\n", to);
|
||||||
|
}
|
||||||
|
for(i =0; i < ns->broadcast_list_host_count[list_number]; i++) {
|
||||||
|
int ret;
|
||||||
|
if((ret = __send_message(ns, message, ns->broadcast_lists[list_number][i])) < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return _send_message(ns, message, to);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _send_message(const NetworkSetup *ns, Message *message, const char *to) {
|
||||||
|
int ret;
|
||||||
|
char *addr;
|
||||||
|
short port;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* TODO: Right size? */
|
||||||
|
struct sockaddr_in * to_sa = malloc(sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
|
||||||
|
to_sa->sin_family = AF_INET;
|
||||||
|
|
||||||
|
addr = parse_addr(to);
|
||||||
|
port = parse_port(to);
|
||||||
|
|
||||||
|
if(addr == NULL) {
|
||||||
|
printf("Send failed. Could not parse addr.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(port == -1) {
|
||||||
|
printf("Send failed. Could not parse port.\n");
|
||||||
|
free(addr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
to_sa->sin_port = htons(port);
|
||||||
|
err=inet_aton(addr, &(to_sa->sin_addr));
|
||||||
|
|
||||||
|
if(err == 0) {
|
||||||
|
perror("inet_aton");
|
||||||
|
free(addr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(addr);
|
||||||
|
message->to_machine_id = htonl(message->to_machine_id);
|
||||||
|
message->from_machine_id = htonl(message->from_machine_id);
|
||||||
|
|
||||||
|
ret = sendto(ns->socket, message, sizeof(Message), 0, (struct sockaddr*)to_sa, sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
message->to_machine_id = ntohl(message->to_machine_id);
|
||||||
|
message->from_machine_id = ntohl(message->from_machine_id);
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
perror("send_message");
|
||||||
|
}
|
||||||
|
if(ret != sizeof(Message)) {
|
||||||
|
printf("send_message sent partial message!\n");
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Synchronously get a UDP packet. Blocks. @return 1 on success, 0
|
||||||
|
* on corrupted packet / timeout, < 0 on network erro.
|
||||||
|
*
|
||||||
|
* @param from A char array of length MAX_ADDRESS_LENGTH+1 that will
|
||||||
|
* be clobbered and set to a null terminated string.
|
||||||
|
*/
|
||||||
|
/*int recieve_message(NetworkSetup *ns, Message *m, struct sockaddr_in *from, socklen_t fromlen) { */
|
||||||
|
int receive_message(NetworkSetup *ns, Message *message, char *from) {
|
||||||
|
size_t max_len = sizeof(Message);
|
||||||
|
/* int flags = MSG_TRUNC ; */
|
||||||
|
int flags = 0 ;
|
||||||
|
ssize_t message_size ;
|
||||||
|
struct sockaddr_in from_sockaddr;
|
||||||
|
socklen_t from_len = sizeof(struct sockaddr_in);
|
||||||
|
char portstr[6];
|
||||||
|
bzero(&from_sockaddr, sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
/* printf("recv'ing\n");
|
||||||
|
fflush(NULL); */
|
||||||
|
/* FIXME! */
|
||||||
|
/* message_size = sizeof(Message); */
|
||||||
|
message_size = recvfrom(ns->socket, message, max_len, flags,
|
||||||
|
(struct sockaddr*)&from_sockaddr, &from_len);
|
||||||
|
if(message_size < 0) {
|
||||||
|
perror("recvfrom");
|
||||||
|
fflush(NULL);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
/* printf("recv'ed\n");
|
||||||
|
fflush(NULL); */
|
||||||
|
|
||||||
|
/* TODO: Check error fields from recvfrom */
|
||||||
|
|
||||||
|
/* Fix the state machine number... */
|
||||||
|
message->to_machine_id = ntohl(message->to_machine_id);
|
||||||
|
message->from_machine_id = ntohl(message->from_machine_id);
|
||||||
|
|
||||||
|
/* Fill out the address string. */
|
||||||
|
|
||||||
|
strcpy(from, inet_ntoa((from_sockaddr).sin_addr));
|
||||||
|
strcat(from, ":");
|
||||||
|
sprintf(portstr, "%d", ntohs((from_sockaddr).sin_port));
|
||||||
|
strcat(from, portstr);
|
||||||
|
|
||||||
|
if(message_size != sizeof(Message)) {
|
||||||
|
/* drop packet */
|
||||||
|
printf("Size mismatch: %d, %d\n", message_size, sizeof(Message));
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
/* TODO: Callback to security stuff / crypto here? */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_index(char ** table, int table_length, const char *address) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < table_length; i++) {
|
||||||
|
if(0 == strcmp(table[i], address)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
354
src/libdfa/monotree.c
Normal file
354
src/libdfa/monotree.c
Normal file
|
@ -0,0 +1,354 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 "monotree.h"
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define EPOCH ((time_t)0)
|
||||||
|
|
||||||
|
int getMachineIndex(MonoTree * rb, state_machine_id id);
|
||||||
|
void compactBuffer(MonoTree * rb);
|
||||||
|
/**
|
||||||
|
Called when a new MonoTree is initialized (NOT after recovery.)
|
||||||
|
|
||||||
|
This code takes a pointer to a MonoTree as an argument, since the
|
||||||
|
MonoTree should be allocated elsewhere (by the transactional
|
||||||
|
layer).
|
||||||
|
*/
|
||||||
|
|
||||||
|
void initStateMachine(StateMachine * stateMachine) {
|
||||||
|
|
||||||
|
stateMachine->machine_id = ULONG_MAX;
|
||||||
|
stateMachine->last_transition = EPOCH;
|
||||||
|
stateMachine->page = NULL;
|
||||||
|
/* stateMachine->page_id; */
|
||||||
|
stateMachine->current_state = NULL_STATE;
|
||||||
|
stateMachine->pending = 0;
|
||||||
|
|
||||||
|
/* Intentionally does not free mutexes. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_MonoTree(MonoTree * rb, int size) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < size; i++) {
|
||||||
|
StateMachine * stateMachine = &(rb->buffer[i]);
|
||||||
|
initStateMachine(stateMachine);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
rb->size = size;
|
||||||
|
rb->low_water_mark = 0;
|
||||||
|
rb->high_water_mark = 0;
|
||||||
|
rb->next_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
StateMachine * allocMachine(MonoTree * rb/*, state_machine_id id*/) {
|
||||||
|
|
||||||
|
StateMachine * new;
|
||||||
|
|
||||||
|
if(rb->high_water_mark >= rb->size) {
|
||||||
|
compactBuffer(rb);
|
||||||
|
}
|
||||||
|
if(rb->high_water_mark >= rb->size) {
|
||||||
|
return (StateMachine *)0;
|
||||||
|
}
|
||||||
|
new = &(rb->buffer[rb->high_water_mark]);
|
||||||
|
rb->high_water_mark++;
|
||||||
|
new->machine_id = rb->next_id;
|
||||||
|
new->mutex = malloc(sizeof(pthread_mutex_t));
|
||||||
|
new->sleepCond = malloc(sizeof(pthread_cond_t));
|
||||||
|
|
||||||
|
pthread_mutex_init(new->mutex, NULL);
|
||||||
|
pthread_cond_init(new->sleepCond, NULL);
|
||||||
|
|
||||||
|
rb->next_id++;
|
||||||
|
new->current_state = START_STATE;
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
StateMachine * insertMachine(MonoTree * rb, state_machine_id id) {
|
||||||
|
int new_index;
|
||||||
|
StateMachine * new;
|
||||||
|
int insertion_point;
|
||||||
|
/* allocMachine is much less expensive than insertMachine, so this
|
||||||
|
check is probably worth the trouble
|
||||||
|
|
||||||
|
I don't understand why, but this optimization was causing 2pc to
|
||||||
|
fail, so I commented it out.
|
||||||
|
|
||||||
|
-Rusty.
|
||||||
|
*/
|
||||||
|
/* if(id == rb->next_id) {
|
||||||
|
return allocMachine(rb);
|
||||||
|
} */
|
||||||
|
if(rb->high_water_mark >= rb->size) {
|
||||||
|
compactBuffer(rb);
|
||||||
|
}
|
||||||
|
if(rb->high_water_mark >= rb->size) {
|
||||||
|
return (StateMachine *)0;
|
||||||
|
}
|
||||||
|
/* Look up the new machine */
|
||||||
|
|
||||||
|
new_index = getMachineIndex(rb, id);
|
||||||
|
|
||||||
|
if(new_index < 0) {
|
||||||
|
insertion_point = -(1+new_index);
|
||||||
|
memmove(&(rb->buffer[insertion_point+1]),
|
||||||
|
&(rb->buffer[insertion_point]),
|
||||||
|
sizeof(StateMachine) * (rb->high_water_mark - insertion_point));
|
||||||
|
rb->high_water_mark++;
|
||||||
|
} else {
|
||||||
|
if(rb->buffer[new_index].current_state == NULL_STATE) {
|
||||||
|
insertion_point = new_index;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new = &(rb->buffer[insertion_point]);
|
||||||
|
new->machine_id = id;
|
||||||
|
new->current_state = START_STATE;
|
||||||
|
new->mutex = malloc(sizeof(pthread_mutex_t));
|
||||||
|
new->sleepCond = malloc(sizeof(pthread_cond_t));
|
||||||
|
pthread_mutex_init(new->mutex, NULL);
|
||||||
|
pthread_cond_init(new->sleepCond, NULL);
|
||||||
|
|
||||||
|
return new;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void freeMachine(MonoTree * rb, state_machine_id id) {
|
||||||
|
StateMachine * stateMachine;
|
||||||
|
int old_index = getMachineIndex(rb, id);
|
||||||
|
|
||||||
|
/* Needed for optimization to garbage collector. */
|
||||||
|
|
||||||
|
if (old_index < rb->low_water_mark) {
|
||||||
|
rb->low_water_mark = old_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
stateMachine = &(rb->buffer[old_index]);
|
||||||
|
|
||||||
|
/* If either of these fail, then there's a bug above this line,
|
||||||
|
or someone attempted to free a machine that doesn't exist (anymore?). */
|
||||||
|
|
||||||
|
assert(stateMachine->machine_id == id);
|
||||||
|
assert(stateMachine->current_state != NULL_STATE);
|
||||||
|
|
||||||
|
/* Leave the machine's id intact for now so that it can be used for binary search. */
|
||||||
|
stateMachine->current_state = NULL_STATE;
|
||||||
|
|
||||||
|
/* Needed so that alloc_machine can be correctly implemented. */
|
||||||
|
|
||||||
|
if ((old_index + 1) == rb->high_water_mark) {
|
||||||
|
rb->high_water_mark--;
|
||||||
|
/* Since we're at the end of the array, we can do this. */
|
||||||
|
stateMachine->machine_id = ULONG_MAX;
|
||||||
|
}
|
||||||
|
pthread_mutex_destroy(stateMachine->mutex);
|
||||||
|
pthread_cond_destroy(stateMachine->sleepCond);
|
||||||
|
free(stateMachine->mutex);
|
||||||
|
free(stateMachine->sleepCond);
|
||||||
|
|
||||||
|
|
||||||
|
/* The application is responsible for the memory management for page, so don't touch that either. */
|
||||||
|
}
|
||||||
|
|
||||||
|
StateMachine * getMachine(MonoTree * rb, state_machine_id id) {
|
||||||
|
int index = getMachineIndex(rb, id);
|
||||||
|
StateMachine * stateMachine;
|
||||||
|
if(index < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
stateMachine = &(rb->buffer[index]);
|
||||||
|
if (stateMachine->current_state == NULL_STATE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert(stateMachine->machine_id==id);
|
||||||
|
|
||||||
|
return stateMachine;
|
||||||
|
}
|
||||||
|
|
||||||
|
StateMachine * enumerateMachines(MonoTree * rb, int* count) {
|
||||||
|
compactBuffer(rb);
|
||||||
|
|
||||||
|
*count = rb->high_water_mark;
|
||||||
|
|
||||||
|
return rb->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------- PRIVATE FUNCTIONS ----------*/
|
||||||
|
|
||||||
|
/* Return the highest possible machine id if binary search
|
||||||
|
* falls off the end of the array.
|
||||||
|
*/
|
||||||
|
state_machine_id getMachineID(MonoTree * rb, int index) {
|
||||||
|
if(index >= rb->size) {
|
||||||
|
return ULONG_MAX;
|
||||||
|
} else {
|
||||||
|
return rb->buffer[index].machine_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int __round_size_up_last_in = -1;
|
||||||
|
int __round_size_up_last_out = -1;
|
||||||
|
|
||||||
|
/* Find the smallest power of 2 greater than orig_size. */
|
||||||
|
int round_size_up(int orig_size) {
|
||||||
|
int power_of_two = 0;
|
||||||
|
|
||||||
|
int size = orig_size-1;
|
||||||
|
|
||||||
|
if(orig_size == __round_size_up_last_in) {
|
||||||
|
return __round_size_up_last_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
assert(orig_size >= 0);
|
||||||
|
|
||||||
|
if(orig_size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What is the first power of two > size? */
|
||||||
|
while(size != 0) {
|
||||||
|
size /= 2;
|
||||||
|
power_of_two++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 1 << power_of_two;
|
||||||
|
__round_size_up_last_in = orig_size;
|
||||||
|
__round_size_up_last_out = size;
|
||||||
|
|
||||||
|
return (int) size;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Thanks to the spec of Java's Arrays.binarySearch() for this one. ;)
|
||||||
|
|
||||||
|
This code doesn't check to see if the index that it returns is the
|
||||||
|
correct one, or even that it contains a real machine, or even that
|
||||||
|
it's less than the size of rb's buffer.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int getMachineIndex(MonoTree * rb, state_machine_id id) {
|
||||||
|
|
||||||
|
int size = round_size_up(rb->size);
|
||||||
|
|
||||||
|
int start = 0;
|
||||||
|
int stop = size;
|
||||||
|
int index;
|
||||||
|
state_machine_id index_id;
|
||||||
|
|
||||||
|
while(stop - start > 1) {
|
||||||
|
assert(((start+stop) % 2) == 0);
|
||||||
|
index = (start + stop) / 2;
|
||||||
|
index_id = getMachineID(rb, index);
|
||||||
|
|
||||||
|
if(index_id == id) {
|
||||||
|
start = index;
|
||||||
|
break;
|
||||||
|
} else if(index_id < id) {
|
||||||
|
start = index;
|
||||||
|
} else {
|
||||||
|
stop = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
if(id == getMachineID(rb, start)) {
|
||||||
|
return start;
|
||||||
|
} else if(id == getMachineID(rb, stop)) {
|
||||||
|
return stop;
|
||||||
|
} else {
|
||||||
|
int insertionPoint;
|
||||||
|
int startID = getMachineID(rb,start);
|
||||||
|
int stopID = getMachineID(rb,stop);
|
||||||
|
if(id < startID) {
|
||||||
|
insertionPoint = start;
|
||||||
|
assert(start == 0 || getMachineID(rb, start-1) < id);
|
||||||
|
} else if(id < stopID) {
|
||||||
|
insertionPoint = stop;
|
||||||
|
} else {
|
||||||
|
assert(id < getMachineID(rb, stop+1));
|
||||||
|
insertionPoint = stop+1;
|
||||||
|
}
|
||||||
|
return (-(insertionPoint) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void compactBuffer(MonoTree * rb) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int buffer_pos = 0;
|
||||||
|
int new_buffer_count = rb->high_water_mark-rb->low_water_mark;
|
||||||
|
size_t new_buffer_size = sizeof(StateMachine)*new_buffer_count;
|
||||||
|
StateMachine * new_buffer;
|
||||||
|
int number_of_machines = rb->low_water_mark;
|
||||||
|
if(rb->high_water_mark == rb->low_water_mark) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_buffer = malloc(new_buffer_size);
|
||||||
|
for(i = rb->low_water_mark; i < rb->high_water_mark; i++) {
|
||||||
|
if(rb->buffer[i].current_state != NULL_STATE) {
|
||||||
|
memcpy(&(new_buffer[buffer_pos]), &(rb->buffer[i]), sizeof(StateMachine));
|
||||||
|
buffer_pos++;
|
||||||
|
number_of_machines++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(i = buffer_pos; i < new_buffer_count; i++) {
|
||||||
|
initStateMachine(&(new_buffer[i]));
|
||||||
|
}
|
||||||
|
memcpy(&(rb->buffer[rb->low_water_mark]), new_buffer, new_buffer_size);
|
||||||
|
free(new_buffer);
|
||||||
|
rb->low_water_mark = rb->high_water_mark = number_of_machines;
|
||||||
|
return;
|
||||||
|
}
|
92
src/libdfa/monotree.h
Normal file
92
src/libdfa/monotree.h
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
#ifndef _MONOTREE_H
|
||||||
|
#define _MONOTREE_H
|
||||||
|
/**
|
||||||
|
Provides a binary tree that provides constant time insertion, but
|
||||||
|
only accepts monotonically increasing values. It's stored in an
|
||||||
|
array, and periodically compacts itself with a little garbage
|
||||||
|
collector. Even though items must be inserted in sorted order, but
|
||||||
|
can be removed in an arbitrary order.
|
||||||
|
|
||||||
|
This data structure is hardcoded to operate on StateMachine
|
||||||
|
structs, but could be easily generalized with a small performance
|
||||||
|
hit.
|
||||||
|
|
||||||
|
This library should be stable.
|
||||||
|
|
||||||
|
TODO: If you pass NULL_STATE (ULONG_MAX) into any of these functions, the
|
||||||
|
result is undefined. This libary should check this instead of
|
||||||
|
causing arbitrary memory corruption.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libdfa/statemachine.h>
|
||||||
|
#include <libdfa/messages.h>
|
||||||
|
|
||||||
|
typedef struct monoTree {
|
||||||
|
StateMachine * buffer;
|
||||||
|
int size;
|
||||||
|
int low_water_mark;
|
||||||
|
int high_water_mark;
|
||||||
|
state_machine_id next_id;
|
||||||
|
} MonoTree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
rb = malloc (sizeof(MonoTree));
|
||||||
|
rb->buffer = malloc(sizeof(StateMachine) * rb_size);
|
||||||
|
|
||||||
|
init_MonoTree(rb, rb_size);
|
||||||
|
|
||||||
|
*/
|
||||||
|
void init_MonoTree(MonoTree * rb, int size);
|
||||||
|
/**
|
||||||
|
Returns a pointer to a new machine, or null if the
|
||||||
|
buffer is full.
|
||||||
|
*/
|
||||||
|
StateMachine * allocMachine (MonoTree * rb);
|
||||||
|
void freeMachine (MonoTree * rb, state_machine_id id);
|
||||||
|
StateMachine * getMachine (MonoTree * rb, state_machine_id id);
|
||||||
|
StateMachine * insertMachine(MonoTree * rb, state_machine_id id);
|
||||||
|
StateMachine * enumerateMachines(MonoTree * rb, int * count);
|
||||||
|
#endif
|
157
src/libdfa/rw.c
Normal file
157
src/libdfa/rw.c
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <libdfa/rw.h>
|
||||||
|
|
||||||
|
rwl *initlock (void)
|
||||||
|
{
|
||||||
|
rwl *lock;
|
||||||
|
|
||||||
|
lock = (rwl *)malloc (sizeof (rwl));
|
||||||
|
if (lock == NULL) return (NULL);
|
||||||
|
lock->mut = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
|
||||||
|
if (lock->mut == NULL) { free (lock); return (NULL); }
|
||||||
|
lock->writeOK =
|
||||||
|
(pthread_cond_t *) malloc (sizeof (pthread_cond_t));
|
||||||
|
if (lock->writeOK == NULL) { free (lock->mut); free (lock);
|
||||||
|
return (NULL); }
|
||||||
|
lock->readOK =
|
||||||
|
(pthread_cond_t *) malloc (sizeof (pthread_cond_t));
|
||||||
|
if (lock->writeOK == NULL) { free (lock->mut); free (lock->writeOK);
|
||||||
|
free (lock); return (NULL); }
|
||||||
|
|
||||||
|
pthread_mutex_init (lock->mut, NULL);
|
||||||
|
pthread_cond_init (lock->writeOK, NULL);
|
||||||
|
pthread_cond_init (lock->readOK, NULL);
|
||||||
|
lock->readers = 0;
|
||||||
|
lock->writers = 0;
|
||||||
|
lock->waiting = 0;
|
||||||
|
|
||||||
|
return (lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void readlock(rwl *lock, int d) {
|
||||||
|
writelock(lock, d);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void readlock (rwl *lock, int d)
|
||||||
|
{
|
||||||
|
/* printf("reader %d\n", d); */
|
||||||
|
fflush(NULL);
|
||||||
|
|
||||||
|
pthread_mutex_lock (lock->mut);
|
||||||
|
if (lock->writers || lock->waiting) {
|
||||||
|
do {
|
||||||
|
/* printf ("reader %d blocked. %d readers, %d writers, %d waiting\n", d, lock->readers, lock->writers, lock->waiting); */
|
||||||
|
pthread_cond_wait (lock->readOK, lock->mut);
|
||||||
|
/* printf ("reader %d unblocked.\n", d); */
|
||||||
|
} while (lock->writers);
|
||||||
|
}
|
||||||
|
lock->readers++;
|
||||||
|
pthread_mutex_unlock (lock->mut);
|
||||||
|
/* printf("reader %d done\n", d); */
|
||||||
|
fflush(NULL);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writelock (rwl *lock, int d)
|
||||||
|
{
|
||||||
|
/* printf("\nwritelock %d\n", d); */
|
||||||
|
fflush(NULL);
|
||||||
|
pthread_mutex_lock (lock->mut);
|
||||||
|
lock->waiting++;
|
||||||
|
while (lock->readers || lock->writers) {
|
||||||
|
/* printf ("writer %d blocked. %d readers, %d writers, %d waiting\n", d, lock->readers, lock->writers, lock->waiting); */
|
||||||
|
pthread_cond_wait (lock->writeOK, lock->mut);
|
||||||
|
/* printf ("writer %d unblocked.\n", d); */
|
||||||
|
}
|
||||||
|
lock->waiting--;
|
||||||
|
lock->writers++;
|
||||||
|
pthread_mutex_unlock (lock->mut);
|
||||||
|
|
||||||
|
/* printf("\nwritelock %d done\n", d); */
|
||||||
|
fflush(NULL);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void readunlock(rwl *lock) {
|
||||||
|
writeunlock(lock);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void readunlock (rwl *lock)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock (lock->mut);
|
||||||
|
lock->readers--;
|
||||||
|
pthread_cond_signal (lock->writeOK);
|
||||||
|
|
||||||
|
/* Don't need to broadcast, since only one writer can run at
|
||||||
|
once. */
|
||||||
|
|
||||||
|
/* pthread_cond_broadcast (lock->writeOK); */
|
||||||
|
|
||||||
|
pthread_mutex_unlock (lock->mut);
|
||||||
|
/* printf("readunlock done\n"); */
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeunlock (rwl *lock)
|
||||||
|
{
|
||||||
|
/* printf("writeunlock done\n"); */
|
||||||
|
fflush(NULL);
|
||||||
|
|
||||||
|
pthread_mutex_lock (lock->mut);
|
||||||
|
lock->writers--;
|
||||||
|
/* Need this as well (in case there's another writer, which is blocking the all of the readers. */
|
||||||
|
pthread_cond_signal (lock->writeOK);
|
||||||
|
pthread_cond_broadcast (lock->readOK);
|
||||||
|
pthread_mutex_unlock (lock->mut);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deletelock (rwl *lock)
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy (lock->mut);
|
||||||
|
pthread_cond_destroy (lock->readOK);
|
||||||
|
pthread_cond_destroy (lock->writeOK);
|
||||||
|
free (lock);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
226
src/libdfa/smash.c
Normal file
226
src/libdfa/smash.c
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <libdfa/smash.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
smash_t * init_Smash(int size) {
|
||||||
|
int xid = Tbegin();
|
||||||
|
recordid store = Talloc(xid, sizeof(smash_t));
|
||||||
|
smash_t * ret = calloc(1, sizeof(smash_t));
|
||||||
|
|
||||||
|
ret->size = size;
|
||||||
|
ret->contents = 0;
|
||||||
|
ret->next_sm_id = 0;
|
||||||
|
ret->store = store;
|
||||||
|
ret->hash = jbHtCreate(xid, 3499);
|
||||||
|
ret->xid = xid;
|
||||||
|
ret->lock = malloc(sizeof(pthread_mutex_t));
|
||||||
|
ret->memHash = pblHtCreate();
|
||||||
|
|
||||||
|
pthread_mutex_init(ret->lock, NULL);
|
||||||
|
|
||||||
|
Tset(xid, ret->store, ret);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void * _getSmash (smash_t * smash, state_machine_id id) {
|
||||||
|
/*extern void * pblHtLookup ( pblHashTable_t * h, void * key, size_t keylen );*/
|
||||||
|
return pblHtLookup ( smash->memHash, &(id), sizeof(state_machine_id));
|
||||||
|
/* return (-1 != jbHtLookup(smash->xid, smash->hash, &(id), sizeof(state_machine_id), machine)); */
|
||||||
|
}
|
||||||
|
|
||||||
|
StateMachine * _insertSmash(smash_t * smash, state_machine_id id) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
StateMachine * new;
|
||||||
|
|
||||||
|
if(smash->contents+1 == smash->size) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
smash->contents++;
|
||||||
|
new = malloc(sizeof (StateMachine));
|
||||||
|
new->machine_id = id;
|
||||||
|
new->mutex = malloc(sizeof(pthread_mutex_t));
|
||||||
|
new->sleepCond = malloc(sizeof(pthread_cond_t));
|
||||||
|
new->pending = 0;
|
||||||
|
pthread_mutex_init(new->mutex, NULL);
|
||||||
|
pthread_cond_init(new->sleepCond, NULL);
|
||||||
|
|
||||||
|
new->current_state = START_STATE;
|
||||||
|
/* printf("Insert %ld\n", id); */
|
||||||
|
ret = (-1 != jbHtInsert(smash->xid, smash->hash, &id, sizeof(state_machine_id), new, sizeof(StateMachine)));
|
||||||
|
pblHtInsert(smash->memHash, &id, sizeof(state_machine_id), new);
|
||||||
|
/* Tcommit(smash->xid);
|
||||||
|
smash->xid = Tbegin(); */
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** @return -1 on error, 0 if there isn't any more room, and 1 on success. */
|
||||||
|
StateMachine * allocSmash (smash_t * smash) {
|
||||||
|
void * ret;
|
||||||
|
|
||||||
|
pthread_mutex_lock(smash->lock);
|
||||||
|
|
||||||
|
/* Make sure we don't clobber an existing state machine... */
|
||||||
|
/* while(jbHtLookup(smash->xid, smash->hash, &(smash->next_sm_id), sizeof(state_machine_id), &junk) != -1) {
|
||||||
|
smash->next_sm_id++;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
while(_getSmash(smash, smash->next_sm_id) != NULL) {
|
||||||
|
smash->next_sm_id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* printf("Alloc %ld\n", smash->next_sm_id); */
|
||||||
|
|
||||||
|
ret = _insertSmash(smash, smash->next_sm_id);
|
||||||
|
smash->next_sm_id++;
|
||||||
|
pthread_mutex_unlock(smash->lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @return -1 on error, 0 if there isn't any more room, and 1 on success. */
|
||||||
|
StateMachine * insertSmash(smash_t * smash, state_machine_id id) {
|
||||||
|
void * ret;
|
||||||
|
StateMachine junk;
|
||||||
|
|
||||||
|
pthread_mutex_lock(smash->lock);
|
||||||
|
|
||||||
|
|
||||||
|
if(jbHtLookup(smash->xid, smash->hash, &(smash->next_sm_id), sizeof(state_machine_id), &junk) != -1) {
|
||||||
|
pthread_mutex_unlock(smash->lock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret= _insertSmash(smash, id);
|
||||||
|
pthread_mutex_unlock(smash->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return -1 on error, 0 if there isn't any more room, and 1 on success. */
|
||||||
|
int freeSmash (smash_t * smash, state_machine_id id) {
|
||||||
|
StateMachine * old = getSmash(smash, id);
|
||||||
|
int ret;
|
||||||
|
pthread_mutex_lock(smash->lock);
|
||||||
|
|
||||||
|
if(old == NULL) {
|
||||||
|
/* Bogus state machine id?? */
|
||||||
|
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
smash->contents--;
|
||||||
|
pthread_mutex_destroy(old->mutex);
|
||||||
|
pthread_cond_destroy(old->sleepCond);
|
||||||
|
free(old->mutex);
|
||||||
|
free(old->sleepCond);
|
||||||
|
|
||||||
|
pblHtRemove(smash->memHash, &(id), sizeof(state_machine_id));
|
||||||
|
ret = jbHtRemove(smash->xid, smash->hash, &(id), sizeof(state_machine_id), NULL) != -1;
|
||||||
|
|
||||||
|
free(old);
|
||||||
|
|
||||||
|
/* Tcommit(smash->xid);
|
||||||
|
smash->xid = Tbegin();*/
|
||||||
|
pthread_mutex_unlock(smash->lock);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void * getSmash (smash_t * smash, state_machine_id id) {
|
||||||
|
void * ret;
|
||||||
|
/* printf("Get smash: %ld\n", id); */
|
||||||
|
|
||||||
|
pthread_mutex_lock(smash->lock);
|
||||||
|
ret = _getSmash(smash, id);
|
||||||
|
pthread_mutex_unlock(smash->lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _setSmash(smash_t * smash, state_machine_id id) {
|
||||||
|
|
||||||
|
StateMachine * machine;
|
||||||
|
machine = _getSmash(smash, id);
|
||||||
|
return (-1 != jbHtInsert(smash->xid, smash->hash, &id, sizeof(state_machine_id), machine, sizeof(StateMachine)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int setSmash (smash_t * smash, state_machine_id id) {
|
||||||
|
int ret;
|
||||||
|
/* printf("Set smash: %ld\n", machine->machine_id); */
|
||||||
|
pthread_mutex_lock(smash->lock);
|
||||||
|
|
||||||
|
ret = _setSmash(smash, id);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(smash->lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int forceSmash (smash_t * smash) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pthread_mutex_lock(smash->lock);
|
||||||
|
|
||||||
|
Tcommit(smash->xid);
|
||||||
|
ret = (-1 != (smash->xid = Tbegin()));
|
||||||
|
|
||||||
|
pthread_mutex_unlock(smash->lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
4
src/lladd/1
Normal file
4
src/lladd/1
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Splint 3.1.1 --- 23 Apr 2004
|
||||||
|
|
||||||
|
2: <invalid flag>
|
||||||
|
less: <invalid flag>
|
8
src/lladd/Makefile.am
Normal file
8
src/lladd/Makefile.am
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#SUBDIRS=operations logger
|
||||||
|
#LDADD=$(top_builddir)/src/pbl/libpbl.a
|
||||||
|
lib_LIBRARIES=liblladd.a
|
||||||
|
#liblladd_a_LIBADD=logger/liblogger.a operations/liboperations.a
|
||||||
|
# removed: recovery.c transactional.c logger.c logger/logparser.c logger/logstreamer.c
|
||||||
|
liblladd_a_SOURCES=bufferManager.c linkedlist.c operations.c page.c recovery2.c transactional2.c logger/logEntry.c logger/logWriter.c logger/logHandle.c logger/logger2.c operations/decrement.c operations/increment.c operations/lladdhash.c operations/prepare.c operations/set.c operations/alloc.c
|
||||||
|
AM_CFLAGS= -g -Wall -pedantic -std=gnu99
|
||||||
|
|
439
src/lladd/bufferManager.c
Normal file
439
src/lladd/bufferManager.c
Normal file
|
@ -0,0 +1,439 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/*******************************
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* implementation of the page buffer
|
||||||
|
* *************************************************/
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <pbl/pbl.h>
|
||||||
|
#include <lladd/bufferManager.h>
|
||||||
|
#include <lladd/page.h>
|
||||||
|
#include <lladd/constants.h>
|
||||||
|
|
||||||
|
static pblHashTable_t *activePages; /* page lookup */
|
||||||
|
static unsigned int bufferSize = 1; /* < MAX_BUFFER_SIZE */
|
||||||
|
static Page *repHead, *repMiddle, *repTail; /* replacement policy */
|
||||||
|
|
||||||
|
static int stable = -1;
|
||||||
|
int blobfd0 = -1;
|
||||||
|
int blobfd1 = -1;
|
||||||
|
|
||||||
|
static void pageMap(Page *ret) {
|
||||||
|
|
||||||
|
int fileSize;
|
||||||
|
/* this was lseek(stable, SEEK_SET, pageid*PAGE_SIZE), but changed to
|
||||||
|
lseek(stable, pageid*PAGE_SIZE, SEEK_SET) by jkit (Wed Mar 24 12:59:18 PST 2004)*/
|
||||||
|
fileSize = lseek(stable, 0, SEEK_END);
|
||||||
|
|
||||||
|
if ((ret->id)*PAGE_SIZE >= fileSize) {
|
||||||
|
lseek(stable, (1 + ret->id)*PAGE_SIZE -1 , SEEK_SET);
|
||||||
|
write(stable, "", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((ret->memAddr = mmap((void *) 0, PAGE_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED, stable, (ret->id)*PAGE_SIZE)) == (void*)-1) {
|
||||||
|
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bufInit() {
|
||||||
|
|
||||||
|
Page *first;
|
||||||
|
|
||||||
|
bufferSize = 1;
|
||||||
|
stable = -1;
|
||||||
|
blobfd0 = -1;
|
||||||
|
blobfd1 = -1;
|
||||||
|
|
||||||
|
|
||||||
|
/* Create STORE_FILE, BLOB0_FILE, BLOB1_FILE if necessary,
|
||||||
|
then open it read/write
|
||||||
|
|
||||||
|
If we're creating it, then put one all-zero record at the beginning of it.
|
||||||
|
(Need to have at least one record in the PAGE file?)
|
||||||
|
|
||||||
|
It used to be that there was one file per page, and LSN needed to be set to -1.
|
||||||
|
|
||||||
|
Now, zero means uninitialized, so this could probably be replaced
|
||||||
|
with a call to open(... O_CREAT|O_RW) or something like that...
|
||||||
|
*/
|
||||||
|
if( (stable = open(STORE_FILE, O_RDWR, 0)) == -1 ) { /* file may not exist */
|
||||||
|
void *zero = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); /* zero = /dev/zero */
|
||||||
|
if( (stable = creat(STORE_FILE, 0666)) == -1 ) { /* cannot even create it */
|
||||||
|
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
/* kick off a fresh page */
|
||||||
|
if( write(stable, zero, PAGE_SIZE) != PAGE_SIZE ) { /* write zeros out */
|
||||||
|
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
if( close(stable) || ((stable = open(STORE_FILE, O_RDWR, 0)) == -1) ) { /* need to reopen with read perms */
|
||||||
|
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activePages = pblHtCreate();
|
||||||
|
assert(activePages);
|
||||||
|
|
||||||
|
first = pageAlloc(0);
|
||||||
|
pblHtInsert(activePages, &first->id, sizeof(int), first);
|
||||||
|
|
||||||
|
first->prev = first->next = NULL;
|
||||||
|
pageMap(first);
|
||||||
|
|
||||||
|
repHead = repTail = first;
|
||||||
|
repMiddle = NULL;
|
||||||
|
if( (blobfd0 = open(BLOB0_FILE, O_RDWR, 0)) == -1 ) { /* file may not exist */
|
||||||
|
if( (blobfd0 = creat(BLOB0_FILE, 0666)) == -1 ) { /* cannot even create it */
|
||||||
|
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
if( close(blobfd0) || ((blobfd0 = open(BLOB0_FILE, O_RDWR, 0)) == -1) ) { /* need to reopen with read perms */
|
||||||
|
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( (blobfd1 = open(BLOB1_FILE, O_RDWR, 0)) == -1 ) { /* file may not exist */
|
||||||
|
if( (blobfd1 = creat(BLOB1_FILE, 0666)) == -1 ) { /* cannot even create it */
|
||||||
|
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
if( close(blobfd1) || ((blobfd1 = open(BLOB1_FILE, O_RDWR, 0)) == -1) ) { /* need to reopen with read perms */
|
||||||
|
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void headInsert(Page *ret) {
|
||||||
|
|
||||||
|
assert(ret != repMiddle);
|
||||||
|
assert(ret != repTail);
|
||||||
|
assert(ret != repHead);
|
||||||
|
|
||||||
|
repHead->prev = ret;
|
||||||
|
ret->next = repHead;
|
||||||
|
ret->prev = NULL;
|
||||||
|
repHead = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void middleInsert(Page *ret) {
|
||||||
|
|
||||||
|
assert( bufferSize == MAX_BUFFER_SIZE );
|
||||||
|
|
||||||
|
assert(ret != repMiddle);
|
||||||
|
assert(ret != repTail);
|
||||||
|
assert(ret != repHead);
|
||||||
|
|
||||||
|
ret->prev = repMiddle->prev;
|
||||||
|
ret->next = repMiddle;
|
||||||
|
repMiddle->prev = ret;
|
||||||
|
ret->prev->next = ret;
|
||||||
|
ret->queue = 2;
|
||||||
|
|
||||||
|
repMiddle = ret;
|
||||||
|
assert(ret->next != ret && ret->prev != ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qRemove(Page *ret) {
|
||||||
|
|
||||||
|
assert( bufferSize == MAX_BUFFER_SIZE );
|
||||||
|
assert(ret->next != ret && ret->prev != ret);
|
||||||
|
|
||||||
|
if( ret->prev )
|
||||||
|
ret->prev->next = ret->next;
|
||||||
|
else /* is head */
|
||||||
|
repHead = ret->next; /* won't have head == tail because of test in loadPage */
|
||||||
|
if( ret->next ) {
|
||||||
|
ret->next->prev = ret->prev;
|
||||||
|
/* TODO: these if can be better organizeed for speed */
|
||||||
|
if( ret == repMiddle )
|
||||||
|
/* select new middle */
|
||||||
|
repMiddle = ret->next;
|
||||||
|
}
|
||||||
|
else /* is tail */
|
||||||
|
repTail = ret->prev;
|
||||||
|
|
||||||
|
assert(ret != repMiddle);
|
||||||
|
assert(ret != repTail);
|
||||||
|
assert(ret != repHead);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Page *kickPage(int pageid) {
|
||||||
|
/* LRU-2S from Markatos "On Caching Searching Engine Results" */
|
||||||
|
Page *ret = repTail;
|
||||||
|
|
||||||
|
assert( bufferSize == MAX_BUFFER_SIZE );
|
||||||
|
|
||||||
|
qRemove(ret);
|
||||||
|
pblHtRemove(activePages, &ret->id, sizeof(int));
|
||||||
|
if( munmap(ret->memAddr, PAGE_SIZE) )
|
||||||
|
assert( 0 );
|
||||||
|
|
||||||
|
pageRealloc(ret, pageid);
|
||||||
|
|
||||||
|
middleInsert(ret);
|
||||||
|
pblHtInsert(activePages, &pageid, sizeof(int), ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int lastPageId = -1;
|
||||||
|
Page * lastPage = 0;
|
||||||
|
|
||||||
|
static Page *loadPagePtr(int pageid) {
|
||||||
|
/* lock activePages, bufferSize */
|
||||||
|
Page *ret;
|
||||||
|
|
||||||
|
if(lastPage && lastPageId == pageid) {
|
||||||
|
return lastPage;
|
||||||
|
} else {
|
||||||
|
ret = pblHtLookup(activePages, &pageid, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ret ) {
|
||||||
|
if( bufferSize == MAX_BUFFER_SIZE ) { /* we need to worry about page sorting */
|
||||||
|
/* move to head */
|
||||||
|
if( ret != repHead ) {
|
||||||
|
qRemove(ret);
|
||||||
|
headInsert(ret);
|
||||||
|
assert(ret->next != ret && ret->prev != ret);
|
||||||
|
|
||||||
|
if( ret->queue == 2 ) {
|
||||||
|
/* keep first queue same size */
|
||||||
|
repMiddle = repMiddle->prev;
|
||||||
|
repMiddle->queue = 2;
|
||||||
|
|
||||||
|
ret->queue = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPage = ret;
|
||||||
|
lastPageId = pageid;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
} else if( bufferSize == MAX_BUFFER_SIZE ) { /* we need to kick */
|
||||||
|
ret = kickPage(pageid);
|
||||||
|
} else if( bufferSize == MAX_BUFFER_SIZE-1 ) { /* we need to setup kickPage mechanism */
|
||||||
|
int i;
|
||||||
|
Page *iter;
|
||||||
|
|
||||||
|
ret = pageAlloc(pageid);
|
||||||
|
headInsert(ret);
|
||||||
|
assert(ret->next != ret && ret->prev != ret);
|
||||||
|
|
||||||
|
pblHtInsert( activePages, &pageid, sizeof(int), ret );
|
||||||
|
|
||||||
|
bufferSize++;
|
||||||
|
|
||||||
|
/* split up queue:
|
||||||
|
* "in all cases studied ... fixing the primary region to 30% ...
|
||||||
|
* resulted in the best performance"
|
||||||
|
*/
|
||||||
|
repMiddle = repHead;
|
||||||
|
for( i = 0; i < MAX_BUFFER_SIZE / 3; i++ ) {
|
||||||
|
repMiddle->queue = 1;
|
||||||
|
repMiddle = repMiddle->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( iter = repMiddle; iter; iter = iter->next ) {
|
||||||
|
iter->queue = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { /* we are adding to an nonfull queue */
|
||||||
|
|
||||||
|
bufferSize++;
|
||||||
|
|
||||||
|
ret = pageAlloc(pageid);
|
||||||
|
headInsert(ret);
|
||||||
|
assert(ret->next != ret && ret->prev != ret);
|
||||||
|
assert(ret->next != ret && ret->prev != ret);
|
||||||
|
pblHtInsert( activePages, &pageid, sizeof(int), ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we now have a page we can dump info into */
|
||||||
|
assert( ret->id == pageid );
|
||||||
|
|
||||||
|
pageMap(ret);
|
||||||
|
|
||||||
|
lastPage = ret;
|
||||||
|
lastPageId = pageid;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Page loadPage (int pageid) {
|
||||||
|
return *loadPagePtr(pageid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*int lastGoodPageKey = 0; */
|
||||||
|
|
||||||
|
Page * lastRallocPage = 0;
|
||||||
|
|
||||||
|
recordid ralloc(int xid, size_t size) {
|
||||||
|
static unsigned int lastFreepage = 0;
|
||||||
|
Page p;
|
||||||
|
int blobSize = 0;
|
||||||
|
|
||||||
|
if (size >= BLOB_THRESHOLD_SIZE) { /* TODO combine this with if below */
|
||||||
|
blobSize = size;
|
||||||
|
size = BLOB_REC_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(freespace(p = loadPage(lastFreepage)) < size ) { lastFreepage++; }
|
||||||
|
|
||||||
|
if (blobSize >= BLOB_THRESHOLD_SIZE) {
|
||||||
|
int fileSize = (int) lseek(blobfd1, 0 , SEEK_END);
|
||||||
|
/* fstat(blobfd1, &sb);
|
||||||
|
fileSize = (int) sb.st_size; */
|
||||||
|
lseek(blobfd0, fileSize+blobSize-1, SEEK_SET);
|
||||||
|
write(blobfd0, "", 1);
|
||||||
|
lseek(blobfd1, fileSize+blobSize-1, SEEK_SET);
|
||||||
|
write(blobfd1, "", 1);
|
||||||
|
|
||||||
|
return pageBalloc(p, blobSize, fileSize);
|
||||||
|
} else {
|
||||||
|
return pageRalloc(p, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
long readLSN(int pageid) {
|
||||||
|
|
||||||
|
return pageReadLSN(loadPage(pageid));
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeLSN(long LSN, int pageid) {
|
||||||
|
Page *p = loadPagePtr(pageid);
|
||||||
|
p->LSN = LSN;
|
||||||
|
pageWriteLSN(*p);
|
||||||
|
}
|
||||||
|
void writeRecord(int xid, recordid rid, const void *dat) {
|
||||||
|
|
||||||
|
Page *p = loadPagePtr(rid.page);
|
||||||
|
assert( (p->id == rid.page) && (p->memAddr != NULL) );
|
||||||
|
|
||||||
|
pageWriteRecord(xid, *p, rid, dat); /* Used to attempt to return this. */
|
||||||
|
}
|
||||||
|
void readRecord(int xid, recordid rid, void *buf) {
|
||||||
|
pageReadRecord(xid, loadPage(rid.page), rid, buf); /* Used to attempt to return this. */
|
||||||
|
}
|
||||||
|
|
||||||
|
int flushPage(Page page) {
|
||||||
|
|
||||||
|
if( munmap(page.memAddr, PAGE_SIZE) )
|
||||||
|
return MEM_WRITE_ERROR;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bufTransCommit(int xid) {
|
||||||
|
|
||||||
|
fdatasync(blobfd0);
|
||||||
|
fdatasync(blobfd1);
|
||||||
|
|
||||||
|
pageCommit(xid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bufTransAbort(int xid) {
|
||||||
|
|
||||||
|
pageAbort(xid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bufDeinit() {
|
||||||
|
int ret;
|
||||||
|
Page *p;
|
||||||
|
|
||||||
|
for( p = (Page*)pblHtFirst( activePages ); p; p = (Page*)pblHtRemove( activePages, 0, 0 )) {
|
||||||
|
if( p->dirty && (ret = flushPage(*p))) {
|
||||||
|
printf("ERROR: flushPage on %s line %d", __FILE__, __LINE__);
|
||||||
|
exit(ret);
|
||||||
|
}
|
||||||
|
/* free(p); */
|
||||||
|
}
|
||||||
|
pblHtDelete(activePages);
|
||||||
|
|
||||||
|
if( close(stable) ) {
|
||||||
|
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(blobfd0);
|
||||||
|
close(blobfd1);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Just close file descriptors, don't do any other clean up. (For
|
||||||
|
testing.)
|
||||||
|
*/
|
||||||
|
void simulateBufferManagerCrash() {
|
||||||
|
close(blobfd0);
|
||||||
|
close(blobfd1);
|
||||||
|
close(stable);
|
||||||
|
blobfd0 = -1;
|
||||||
|
blobfd1 = -1;
|
||||||
|
stable = -1;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
162
src/lladd/linkedlist.c
Normal file
162
src/lladd/linkedlist.c
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/******************************
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* simple linked list
|
||||||
|
*****************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "linkedlist.h"
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void printList(LinkedList *l) {
|
||||||
|
LinkedListPtr tmp = l;
|
||||||
|
printf ("List is ");
|
||||||
|
while (tmp!=NULL) {
|
||||||
|
printf ("%d ", tmp->val);
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
printf (".\n");
|
||||||
|
}
|
||||||
|
void addVal(LinkedList **list, int val) {
|
||||||
|
LinkedListPtr new = (LinkedListPtr)malloc(sizeof(LinkedList));
|
||||||
|
new->val = val;
|
||||||
|
new->next = NULL;
|
||||||
|
if (*list==NULL) {
|
||||||
|
*list = new;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new->next = *list;
|
||||||
|
*list = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void removeVal(LinkedList **list, int val) {
|
||||||
|
LinkedListPtr tmp, tmpprev;
|
||||||
|
if (*list==NULL) return;
|
||||||
|
if ((*list!=NULL) && ((*list)->val==val)) {
|
||||||
|
tmp = *list;
|
||||||
|
*list = (*list)->next;
|
||||||
|
free(tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmp = (*list)->next;
|
||||||
|
tmpprev = *list;
|
||||||
|
while (tmp!=NULL) {
|
||||||
|
if (tmp->val==val) {
|
||||||
|
tmpprev->next = tmp->next;
|
||||||
|
free(tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmpprev = tmp;
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int popMaxVal(LinkedList **list) {
|
||||||
|
LinkedListPtr tmp;
|
||||||
|
int tmpval;
|
||||||
|
if (*list!=NULL) {
|
||||||
|
tmp = *list;
|
||||||
|
(*list) = (*list)->next;
|
||||||
|
tmpval = tmp->val;
|
||||||
|
free(tmp);
|
||||||
|
return tmpval;
|
||||||
|
}
|
||||||
|
else return -1; /*this should be an error! */
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSortedVal(LinkedList **list, int val) {
|
||||||
|
LinkedListPtr tmp, tmpprev;
|
||||||
|
LinkedListPtr new = (LinkedListPtr)malloc(sizeof(LinkedList));
|
||||||
|
new->val = val;
|
||||||
|
/*see if new entry should come in the beginning*/
|
||||||
|
if ((*list==NULL) || ((*list)->val<val)) {
|
||||||
|
new->next = *list;
|
||||||
|
*list = new;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*else determine where to put new entry*/
|
||||||
|
tmp = (*list)->next;
|
||||||
|
tmpprev = *list;
|
||||||
|
while (tmp!=NULL) {
|
||||||
|
if (tmp->val<val) {
|
||||||
|
tmpprev->next = new;
|
||||||
|
new->next = tmp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmpprev = tmp;
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
/*if gotten here, tmp is null so put item at the end of the list*/
|
||||||
|
new->next = NULL;
|
||||||
|
tmpprev->next = new;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
return 1 if val is in the list, 0 otherwise
|
||||||
|
*/
|
||||||
|
int findVal(LinkedList *list, int val) {
|
||||||
|
LinkedListPtr tmp = list;
|
||||||
|
while (tmp!=NULL) {
|
||||||
|
if (tmp->val==val)
|
||||||
|
return 1;
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deallocates all nodes in the list, and sets list to null
|
||||||
|
*/
|
||||||
|
void destroyList (LinkedList *list) {
|
||||||
|
LinkedListPtr tmp;
|
||||||
|
while (list!=NULL) {
|
||||||
|
tmp = list->next;
|
||||||
|
free(list);
|
||||||
|
list=tmp;
|
||||||
|
}
|
||||||
|
list = NULL;
|
||||||
|
}
|
97
src/lladd/linkedlist.h
Normal file
97
src/lladd/linkedlist.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __LINKEDLIST_H__
|
||||||
|
#define __LINKEDLIST_H__
|
||||||
|
|
||||||
|
/**
|
||||||
|
@file
|
||||||
|
|
||||||
|
Implements a simple sorted linked list. Written for LLADD's
|
||||||
|
recovery algorithms.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include <lladd/common.h>
|
||||||
|
BEGIN_C_DECLS
|
||||||
|
|
||||||
|
struct Nodetmp {
|
||||||
|
int val;
|
||||||
|
struct Nodetmp *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Nodetmp LinkedList;
|
||||||
|
typedef LinkedList *LinkedListPtr;
|
||||||
|
|
||||||
|
void printList(LinkedList *l) ;
|
||||||
|
|
||||||
|
void addVal(LinkedList **list, int val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@return 1 if val is in the list, 0 otherwise
|
||||||
|
*/
|
||||||
|
int findVal(LinkedList *list, int val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deallocates all nodes in the list, and sets list to null
|
||||||
|
*/
|
||||||
|
void destroyList (LinkedList *list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a value to the list in descending order
|
||||||
|
*/
|
||||||
|
void addSortedVal(LinkedList **list, int val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a value from the list
|
||||||
|
*/
|
||||||
|
void removeVal(LinkedList **list, int val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the max value (first on list), assuming list is not null and has been
|
||||||
|
* sorted
|
||||||
|
*/
|
||||||
|
int popMaxVal(LinkedList **list);
|
||||||
|
|
||||||
|
END_C_DECLS
|
||||||
|
|
||||||
|
#endif
|
129
src/lladd/logger/.deps/logger.Po
Normal file
129
src/lladd/logger/.deps/logger.Po
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
logger.o logger.o: logger.c /usr/include/stdlib.h /usr/include/features.h \
|
||||||
|
/usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h \
|
||||||
|
/usr/include/sys/types.h /usr/include/bits/types.h \
|
||||||
|
/usr/include/bits/wordsize.h /usr/include/bits/typesizes.h \
|
||||||
|
/usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
|
||||||
|
/usr/include/sys/select.h /usr/include/bits/select.h \
|
||||||
|
/usr/include/bits/sigset.h /usr/include/bits/time.h \
|
||||||
|
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
|
||||||
|
/usr/include/bits/sched.h /usr/include/alloca.h \
|
||||||
|
../../../lladd/transactional.h ../../../lladd/common.h \
|
||||||
|
../../../lladd/config.h /usr/include/stdio.h /usr/include/libio.h \
|
||||||
|
/usr/include/_G_config.h /usr/include/wchar.h /usr/include/bits/wchar.h \
|
||||||
|
/usr/include/gconv.h /usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h \
|
||||||
|
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
|
||||||
|
/usr/include/bits/stdio.h /usr/include/string.h \
|
||||||
|
/usr/include/bits/string.h /usr/include/bits/string2.h \
|
||||||
|
/usr/include/unistd.h /usr/include/bits/posix_opt.h \
|
||||||
|
/usr/include/bits/confname.h /usr/include/getopt.h \
|
||||||
|
../../../lladd/page.h ../../../lladd/operations.h \
|
||||||
|
../../../lladd/constants.h ../../../lladd/operations/increment.h \
|
||||||
|
../../../lladd/bufferManager.h ../../../lladd/operations/decrement.h \
|
||||||
|
../../../lladd/operations/set.h ../../../lladd/operations/prepare.h \
|
||||||
|
../../../lladd/operations/lladdhash.h ../../../lladd/logger.h \
|
||||||
|
logparser.h logstreamer.h
|
||||||
|
|
||||||
|
/usr/include/stdlib.h:
|
||||||
|
|
||||||
|
/usr/include/features.h:
|
||||||
|
|
||||||
|
/usr/include/sys/cdefs.h:
|
||||||
|
|
||||||
|
/usr/include/gnu/stubs.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h:
|
||||||
|
|
||||||
|
/usr/include/sys/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wordsize.h:
|
||||||
|
|
||||||
|
/usr/include/bits/typesizes.h:
|
||||||
|
|
||||||
|
/usr/include/time.h:
|
||||||
|
|
||||||
|
/usr/include/endian.h:
|
||||||
|
|
||||||
|
/usr/include/bits/endian.h:
|
||||||
|
|
||||||
|
/usr/include/sys/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sigset.h:
|
||||||
|
|
||||||
|
/usr/include/bits/time.h:
|
||||||
|
|
||||||
|
/usr/include/sys/sysmacros.h:
|
||||||
|
|
||||||
|
/usr/include/bits/pthreadtypes.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sched.h:
|
||||||
|
|
||||||
|
/usr/include/alloca.h:
|
||||||
|
|
||||||
|
../../../lladd/transactional.h:
|
||||||
|
|
||||||
|
../../../lladd/common.h:
|
||||||
|
|
||||||
|
../../../lladd/config.h:
|
||||||
|
|
||||||
|
/usr/include/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/libio.h:
|
||||||
|
|
||||||
|
/usr/include/_G_config.h:
|
||||||
|
|
||||||
|
/usr/include/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/gconv.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio_lim.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sys_errlist.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string2.h:
|
||||||
|
|
||||||
|
/usr/include/unistd.h:
|
||||||
|
|
||||||
|
/usr/include/bits/posix_opt.h:
|
||||||
|
|
||||||
|
/usr/include/bits/confname.h:
|
||||||
|
|
||||||
|
/usr/include/getopt.h:
|
||||||
|
|
||||||
|
../../../lladd/page.h:
|
||||||
|
|
||||||
|
../../../lladd/operations.h:
|
||||||
|
|
||||||
|
../../../lladd/constants.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/increment.h:
|
||||||
|
|
||||||
|
../../../lladd/bufferManager.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/decrement.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/set.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/prepare.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/lladdhash.h:
|
||||||
|
|
||||||
|
../../../lladd/logger.h:
|
||||||
|
|
||||||
|
logparser.h:
|
||||||
|
|
||||||
|
logstreamer.h:
|
107
src/lladd/logger/.deps/logparser.Po
Normal file
107
src/lladd/logger/.deps/logparser.Po
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
logparser.o logparser.o: logparser.c /usr/include/stdlib.h \
|
||||||
|
/usr/include/features.h /usr/include/sys/cdefs.h \
|
||||||
|
/usr/include/gnu/stubs.h \
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h \
|
||||||
|
/usr/include/sys/types.h /usr/include/bits/types.h \
|
||||||
|
/usr/include/bits/wordsize.h /usr/include/bits/typesizes.h \
|
||||||
|
/usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
|
||||||
|
/usr/include/sys/select.h /usr/include/bits/select.h \
|
||||||
|
/usr/include/bits/sigset.h /usr/include/bits/time.h \
|
||||||
|
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
|
||||||
|
/usr/include/bits/sched.h /usr/include/alloca.h /usr/include/stdio.h \
|
||||||
|
/usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
|
||||||
|
/usr/include/bits/wchar.h /usr/include/gconv.h \
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h \
|
||||||
|
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
|
||||||
|
/usr/include/bits/stdio.h /usr/include/string.h \
|
||||||
|
/usr/include/bits/string.h /usr/include/bits/string2.h logparser.h \
|
||||||
|
../../../lladd/page.h ../../../lladd/common.h ../../../lladd/config.h \
|
||||||
|
/usr/include/unistd.h /usr/include/bits/posix_opt.h \
|
||||||
|
/usr/include/bits/confname.h /usr/include/getopt.h \
|
||||||
|
../../../lladd/constants.h logstreamer.h
|
||||||
|
|
||||||
|
/usr/include/stdlib.h:
|
||||||
|
|
||||||
|
/usr/include/features.h:
|
||||||
|
|
||||||
|
/usr/include/sys/cdefs.h:
|
||||||
|
|
||||||
|
/usr/include/gnu/stubs.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h:
|
||||||
|
|
||||||
|
/usr/include/sys/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wordsize.h:
|
||||||
|
|
||||||
|
/usr/include/bits/typesizes.h:
|
||||||
|
|
||||||
|
/usr/include/time.h:
|
||||||
|
|
||||||
|
/usr/include/endian.h:
|
||||||
|
|
||||||
|
/usr/include/bits/endian.h:
|
||||||
|
|
||||||
|
/usr/include/sys/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sigset.h:
|
||||||
|
|
||||||
|
/usr/include/bits/time.h:
|
||||||
|
|
||||||
|
/usr/include/sys/sysmacros.h:
|
||||||
|
|
||||||
|
/usr/include/bits/pthreadtypes.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sched.h:
|
||||||
|
|
||||||
|
/usr/include/alloca.h:
|
||||||
|
|
||||||
|
/usr/include/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/libio.h:
|
||||||
|
|
||||||
|
/usr/include/_G_config.h:
|
||||||
|
|
||||||
|
/usr/include/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/gconv.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio_lim.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sys_errlist.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string2.h:
|
||||||
|
|
||||||
|
logparser.h:
|
||||||
|
|
||||||
|
../../../lladd/page.h:
|
||||||
|
|
||||||
|
../../../lladd/common.h:
|
||||||
|
|
||||||
|
../../../lladd/config.h:
|
||||||
|
|
||||||
|
/usr/include/unistd.h:
|
||||||
|
|
||||||
|
/usr/include/bits/posix_opt.h:
|
||||||
|
|
||||||
|
/usr/include/bits/confname.h:
|
||||||
|
|
||||||
|
/usr/include/getopt.h:
|
||||||
|
|
||||||
|
../../../lladd/constants.h:
|
||||||
|
|
||||||
|
logstreamer.h:
|
92
src/lladd/logger/.deps/logstreamer.Po
Normal file
92
src/lladd/logger/.deps/logstreamer.Po
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
logstreamer.o logstreamer.o: logstreamer.c /usr/include/stdio.h \
|
||||||
|
/usr/include/features.h /usr/include/sys/cdefs.h \
|
||||||
|
/usr/include/gnu/stubs.h \
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h \
|
||||||
|
/usr/include/bits/types.h /usr/include/bits/wordsize.h \
|
||||||
|
/usr/include/bits/typesizes.h /usr/include/libio.h \
|
||||||
|
/usr/include/_G_config.h /usr/include/wchar.h /usr/include/bits/wchar.h \
|
||||||
|
/usr/include/gconv.h /usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h \
|
||||||
|
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
|
||||||
|
/usr/include/bits/stdio.h /usr/include/assert.h /usr/include/stdlib.h \
|
||||||
|
/usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h \
|
||||||
|
/usr/include/bits/endian.h /usr/include/sys/select.h \
|
||||||
|
/usr/include/bits/select.h /usr/include/bits/sigset.h \
|
||||||
|
/usr/include/bits/time.h /usr/include/sys/sysmacros.h \
|
||||||
|
/usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h \
|
||||||
|
/usr/include/alloca.h /usr/include/unistd.h \
|
||||||
|
/usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
|
||||||
|
/usr/include/getopt.h ../../../lladd/constants.h logstreamer.h
|
||||||
|
|
||||||
|
/usr/include/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/features.h:
|
||||||
|
|
||||||
|
/usr/include/sys/cdefs.h:
|
||||||
|
|
||||||
|
/usr/include/gnu/stubs.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h:
|
||||||
|
|
||||||
|
/usr/include/bits/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wordsize.h:
|
||||||
|
|
||||||
|
/usr/include/bits/typesizes.h:
|
||||||
|
|
||||||
|
/usr/include/libio.h:
|
||||||
|
|
||||||
|
/usr/include/_G_config.h:
|
||||||
|
|
||||||
|
/usr/include/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/gconv.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio_lim.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sys_errlist.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/assert.h:
|
||||||
|
|
||||||
|
/usr/include/stdlib.h:
|
||||||
|
|
||||||
|
/usr/include/sys/types.h:
|
||||||
|
|
||||||
|
/usr/include/time.h:
|
||||||
|
|
||||||
|
/usr/include/endian.h:
|
||||||
|
|
||||||
|
/usr/include/bits/endian.h:
|
||||||
|
|
||||||
|
/usr/include/sys/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sigset.h:
|
||||||
|
|
||||||
|
/usr/include/bits/time.h:
|
||||||
|
|
||||||
|
/usr/include/sys/sysmacros.h:
|
||||||
|
|
||||||
|
/usr/include/bits/pthreadtypes.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sched.h:
|
||||||
|
|
||||||
|
/usr/include/alloca.h:
|
||||||
|
|
||||||
|
/usr/include/unistd.h:
|
||||||
|
|
||||||
|
/usr/include/bits/posix_opt.h:
|
||||||
|
|
||||||
|
/usr/include/bits/confname.h:
|
||||||
|
|
||||||
|
/usr/include/getopt.h:
|
||||||
|
|
||||||
|
../../../lladd/constants.h:
|
||||||
|
|
||||||
|
logstreamer.h:
|
3
src/lladd/logger/Makefile.am-old
Normal file
3
src/lladd/logger/Makefile.am-old
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
lib_LIBRARIES=liblogger.a
|
||||||
|
liblogger_a_SOURCES=logger.c logparser.c logstreamer.c
|
||||||
|
AM_CFLAGS= -g -Wall -pedantic
|
132
src/lladd/logger/logEntry.c
Normal file
132
src/lladd/logger/logEntry.c
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <lladd/logger/logEntry.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <lladd/operations.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
LogEntry * allocCommonLogEntry(lsn_t prevLSN, int xid, unsigned int type) {
|
||||||
|
LogEntry * ret = malloc(sizeof(struct __raw_log_entry));
|
||||||
|
ret->LSN = -1;
|
||||||
|
ret->prevLSN = prevLSN;
|
||||||
|
ret->xid = xid;
|
||||||
|
ret->type = type;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte * getUpdateArgs(const LogEntry * ret) {
|
||||||
|
assert(ret->type == UPDATELOG);
|
||||||
|
if(ret->contents.update.argSize == 0) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return ((byte*)ret) + sizeof(struct __raw_log_entry) + sizeof(UpdateLogEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte * getUpdatePreImage(const LogEntry * ret) {
|
||||||
|
assert(ret->type == UPDATELOG);
|
||||||
|
if(operationsTable[ret->contents.update.funcID].undo != NO_INVERSE) {
|
||||||
|
/* if(ret->contents.update.invertible) { */
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return ((byte*)ret) + sizeof(struct __raw_log_entry) + sizeof(UpdateLogEntry) + ret->contents.update.argSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogEntry * allocUpdateLogEntry(lsn_t prevLSN, int xid,
|
||||||
|
unsigned int funcID, recordid rid,
|
||||||
|
const byte * args, unsigned int argSize, const byte * preImage) {
|
||||||
|
int invertible = operationsTable[funcID].undo != NO_INVERSE;
|
||||||
|
|
||||||
|
LogEntry * ret = malloc(sizeof(struct __raw_log_entry) + sizeof(UpdateLogEntry) + argSize + ((!invertible) ? rid.size : 0));
|
||||||
|
ret->LSN = -1;
|
||||||
|
ret->prevLSN = prevLSN;
|
||||||
|
ret->xid = xid;
|
||||||
|
ret->type = UPDATELOG;
|
||||||
|
ret->contents.update.funcID = funcID;
|
||||||
|
/* ret->contents.update.invertible = invertible; */
|
||||||
|
ret->contents.update.rid = rid;
|
||||||
|
ret->contents.update.argSize = argSize;
|
||||||
|
|
||||||
|
if(argSize) {
|
||||||
|
memcpy((void*)getUpdateArgs(ret), args, argSize);
|
||||||
|
}
|
||||||
|
if(!invertible) {
|
||||||
|
memcpy((void*)getUpdatePreImage(ret), preImage, rid.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
LogEntry * allocCLRLogEntry (lsn_t prevLSN, int xid,
|
||||||
|
lsn_t thisUpdateLSN, recordid rid, lsn_t undoNextLSN) {
|
||||||
|
LogEntry * ret = malloc(sizeof(struct __raw_log_entry) + sizeof(CLRLogEntry));
|
||||||
|
ret->LSN = -1;
|
||||||
|
ret->prevLSN = prevLSN;
|
||||||
|
ret->xid = xid;
|
||||||
|
ret->type = CLRLOG;
|
||||||
|
|
||||||
|
ret->contents.clr.thisUpdateLSN = thisUpdateLSN;
|
||||||
|
ret->contents.clr.rid = rid;
|
||||||
|
ret->contents.clr.undoNextLSN = undoNextLSN;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t sizeofLogEntry(const LogEntry * log) {
|
||||||
|
switch (log->type) {
|
||||||
|
case CLRLOG:
|
||||||
|
return sizeof(struct __raw_log_entry) + sizeof(CLRLogEntry);
|
||||||
|
case UPDATELOG:
|
||||||
|
return sizeof(struct __raw_log_entry) + sizeof(UpdateLogEntry) + log->contents.update.argSize +
|
||||||
|
((operationsTable[log->contents.update.funcID].undo == NO_INVERSE) ? log->contents.update.rid.size : 0);
|
||||||
|
default:
|
||||||
|
return sizeof(struct __raw_log_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
125
src/lladd/logger/logHandle.c
Normal file
125
src/lladd/logger/logHandle.c
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <lladd/logger/logHandle.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the next and prev field of h, but does not set h.file_offset.
|
||||||
|
That should probably be set before calling this function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void set_offsets(LogHandle * h, LogEntry * e, lsn_t lastRead);
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
LogHandle getLogHandle() {
|
||||||
|
return getGuardedHandle(sizeof(lsn_t), NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogHandle getLSNHandle(lsn_t lsn) {
|
||||||
|
return getGuardedHandle(lsn, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogHandle getGuardedHandle(lsn_t lsn, guard_fcn_t * guard, void * guard_state) {
|
||||||
|
LogHandle ret;
|
||||||
|
ret.next_offset = lsn;
|
||||||
|
ret.prev_offset = lsn;
|
||||||
|
ret.guard = guard;
|
||||||
|
ret.guard_state = guard_state;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogEntry * nextInLog(LogHandle * h) {
|
||||||
|
LogEntry * ret = readLSNEntry(h->next_offset);
|
||||||
|
if(ret != NULL) {
|
||||||
|
set_offsets(h, ret, h->next_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(h->guard) {
|
||||||
|
if(!(h->guard(ret, h->guard_state))) {
|
||||||
|
free(ret);
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogEntry * previousInTransaction(LogHandle * h) {
|
||||||
|
LogEntry * ret = NULL;
|
||||||
|
if(h->prev_offset > 0) {
|
||||||
|
/* printf("A"); fflush(NULL); */
|
||||||
|
ret = readLSNEntry(h->prev_offset);
|
||||||
|
set_offsets(h, ret, h->prev_offset);
|
||||||
|
/*printf("B"); fflush(NULL); */
|
||||||
|
|
||||||
|
if(h->guard) {
|
||||||
|
/*printf("C"); fflush(NULL);*/
|
||||||
|
|
||||||
|
if(!h->guard(ret, h->guard_state)) {
|
||||||
|
free(ret);
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
/*printf("D"); fflush(NULL);*/
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@todo The next_offset field is set in a way that assumes a
|
||||||
|
particular layout of log entries. If we want to support other
|
||||||
|
loggers, then the lsn of the next entry should be calculated by the
|
||||||
|
logging implementation, not here. (One possibility is to have
|
||||||
|
readLSNEntry return it explicitly.)
|
||||||
|
*/
|
||||||
|
static void set_offsets(LogHandle * h, LogEntry * e, lsn_t lastRead) {
|
||||||
|
h->next_offset = lastRead + sizeofLogEntry(e)+sizeof(lsn_t);
|
||||||
|
h->prev_offset = (e->type==CLRLOG) ? e->contents.clr.undoNextLSN : e->prevLSN ;
|
||||||
|
}
|
||||||
|
|
203
src/lladd/logger/logWriter.c
Normal file
203
src/lladd/logger/logWriter.c
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <lladd/logger/logWriter.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
/**
|
||||||
|
Invariant: This file stream is at EOF, or positioned so that the
|
||||||
|
next read will pull in the size of the next log entry.
|
||||||
|
|
||||||
|
@todo Should the log file be global?
|
||||||
|
*/
|
||||||
|
static FILE * log;
|
||||||
|
|
||||||
|
|
||||||
|
int openLogWriter() {
|
||||||
|
log = fopen(LOG_FILE, "a+");
|
||||||
|
if (log==NULL) {
|
||||||
|
assert(0);
|
||||||
|
/*there was an error opening this file */
|
||||||
|
return FILE_WRITE_OPEN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that the position of the file between calls to this library
|
||||||
|
does not matter, since none of the functions in logWriter.h
|
||||||
|
assume anything about the position of the stream before they are
|
||||||
|
called.
|
||||||
|
|
||||||
|
However, we need to do this seek to check the length of the file.
|
||||||
|
|
||||||
|
*/
|
||||||
|
fseek(log, 0, SEEK_END);
|
||||||
|
|
||||||
|
if (ftell(log)==0) {
|
||||||
|
/*if file is empty, write an LSN at the 0th position. LSN 0 is
|
||||||
|
invalid, and this prevents us from using it. Also, the LSN at
|
||||||
|
this position can be used after log truncation to define a
|
||||||
|
global offset for the truncated log. (Not implemented yet)
|
||||||
|
*/
|
||||||
|
lsn_t zero = 0;
|
||||||
|
int nmemb = fwrite(&zero, sizeof(lsn_t), 1, log);
|
||||||
|
if(nmemb != 1) {
|
||||||
|
perror("Couldn't start new log file!");
|
||||||
|
assert(0);
|
||||||
|
return FILE_WRITE_OPEN_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int writeLogEntry(LogEntry * e) {
|
||||||
|
int nmemb;
|
||||||
|
const size_t size = sizeofLogEntry(e);
|
||||||
|
|
||||||
|
/* Set the log entry's LSN. */
|
||||||
|
fseek(log, 0, SEEK_END);
|
||||||
|
e->LSN = ftell(log);
|
||||||
|
|
||||||
|
/* Print out the size of this log entry. (not including this item.) */
|
||||||
|
nmemb = fwrite(&size, sizeof(size_t), 1, log);
|
||||||
|
|
||||||
|
if(nmemb != 1) {
|
||||||
|
perror("writeLog couldn't write next log entry size!");
|
||||||
|
assert(0);
|
||||||
|
return FILE_WRITE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
nmemb = fwrite(e, size, 1, log);
|
||||||
|
|
||||||
|
if(nmemb != 1) {
|
||||||
|
perror("writeLog couldn't write next log entry!");
|
||||||
|
assert(0);
|
||||||
|
return FILE_WRITE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We're done. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncLog() {
|
||||||
|
fflush(log);
|
||||||
|
#ifdef HAVE_FDATASYNC
|
||||||
|
/* Should be available in linux >= 2.4 */
|
||||||
|
fdatasync(fileno(log));
|
||||||
|
#else
|
||||||
|
/* Slow - forces fs implementation to sync the file metadata to disk */
|
||||||
|
fsync(fileno(log));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void closeLogWriter() {
|
||||||
|
/* Get the whole thing to the disk before closing it. */
|
||||||
|
syncLog();
|
||||||
|
fclose(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteLogWriter() {
|
||||||
|
remove(LOG_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LogEntry * readLogEntry() {
|
||||||
|
LogEntry * ret = NULL;
|
||||||
|
size_t size;
|
||||||
|
int nmemb;
|
||||||
|
|
||||||
|
if(feof(log)) return NULL;
|
||||||
|
|
||||||
|
nmemb = fread(&size, sizeof(size_t), 1, log);
|
||||||
|
|
||||||
|
if(nmemb != 1) {
|
||||||
|
if(feof(log)) return NULL;
|
||||||
|
if(ferror(log)) {
|
||||||
|
perror("Error reading log!");
|
||||||
|
assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = malloc(size);
|
||||||
|
|
||||||
|
nmemb = fread(ret, size, 1, log);
|
||||||
|
|
||||||
|
if(nmemb != 1) {
|
||||||
|
/* Partial log entry. */
|
||||||
|
if(feof(log)) return NULL;
|
||||||
|
if(ferror(log)) {
|
||||||
|
perror("Error reading log!");
|
||||||
|
assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sanity check -- Did we get the whole entry? */
|
||||||
|
assert(size == sizeofLogEntry(ret));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogEntry * readLSNEntry(lsn_t LSN) {
|
||||||
|
LogEntry * ret;
|
||||||
|
|
||||||
|
fseek(log, LSN, SEEK_SET);
|
||||||
|
ret = readLogEntry();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*lsn_t nextLSN() {
|
||||||
|
lsn_t orig_pos = ftell(log);
|
||||||
|
lsn_t ret;
|
||||||
|
|
||||||
|
fseek(log, 0, SEEK_END);
|
||||||
|
|
||||||
|
ret = ftell(log);
|
||||||
|
|
||||||
|
fseek(log, orig_pos, SEEK_SET);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}*/
|
142
src/lladd/logger/logger.c
Normal file
142
src/lladd/logger/logger.c
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
* @file
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* C implementation of logger.h
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* @see logger2.c
|
||||||
|
******************/
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <lladd/transactional.h>
|
||||||
|
#include <lladd/logger.h>
|
||||||
|
#include "logparser.h"
|
||||||
|
#include "logstreamer.h"
|
||||||
|
#include <lladd/bufferManager.h>
|
||||||
|
|
||||||
|
static long LogCommonWriterNoExtra(long prevLSN, int xid, int type); /*defined later*/
|
||||||
|
|
||||||
|
long LogTransBegin(Transaction t) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* jason please review and delete comment when done
|
||||||
|
* to recover: pageRalloc(loadPage(rid.page), rid.size)
|
||||||
|
*/
|
||||||
|
long LogTransAlloc(long prevLSN, int xid, recordid rid) {
|
||||||
|
char *extra;
|
||||||
|
int sizeOfExtra = allocPartsToString(&extra, rid);
|
||||||
|
return writeNewLog(prevLSN, xid, XALLOC, extra, sizeOfExtra);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long LogTransCommit(long prevLSN, int xid) {
|
||||||
|
long newLSN = LogCommonWriterNoExtra(prevLSN, xid, XCOMMIT);
|
||||||
|
flushLog();
|
||||||
|
return newLSN;
|
||||||
|
}
|
||||||
|
|
||||||
|
long LogTransAbort(long prevLSN, int xid) {
|
||||||
|
return LogCommonWriterNoExtra(prevLSN, xid, XABORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
long LogUpdate (long prevLSN, int xid, recordid rid, Operation op, const void *args) {
|
||||||
|
char *extra;
|
||||||
|
/* size_t sizeOfData, sizeOfExtra; */
|
||||||
|
int sizeOfData, sizeOfExtra;
|
||||||
|
void *preImage = 0;
|
||||||
|
int invertible;
|
||||||
|
if (op.sizeofData==SIZEOF_RECORD) {
|
||||||
|
/*then get the size of this record */
|
||||||
|
sizeOfData = rid.size;
|
||||||
|
}
|
||||||
|
else sizeOfData = op.sizeofData;
|
||||||
|
/*heck to see if op is invertible */
|
||||||
|
if (op.undo==NO_INVERSE) {
|
||||||
|
invertible = 0;
|
||||||
|
preImage = (void *)malloc(rid.size);
|
||||||
|
readRecord(xid, rid, preImage);
|
||||||
|
}
|
||||||
|
else invertible = 1;
|
||||||
|
/*will put all of the parts special to an update log record into extra */
|
||||||
|
sizeOfExtra = updatePartsToString(&extra, op.id, rid, args, sizeOfData, invertible, preImage);
|
||||||
|
/*extra has been malloced, but writeNewLog will free it*/
|
||||||
|
if(preImage) {
|
||||||
|
free(preImage);
|
||||||
|
}
|
||||||
|
return writeNewLog(prevLSN, xid, UPDATELOG, extra, sizeOfExtra);
|
||||||
|
}
|
||||||
|
|
||||||
|
long LogCLR (long prevLSN, int xid, long ulLSN, recordid ulRID, long ulPrevLSN) {
|
||||||
|
#define CLRSIZEOFEXTRA 20
|
||||||
|
char *extra;
|
||||||
|
CLRPartsToString(&extra, ulLSN, ulRID, ulPrevLSN);
|
||||||
|
/*extra has been malloced, but writeNewLog will free it*/
|
||||||
|
return writeNewLog(prevLSN, xid, CLRLOG, extra, CLRSIZEOFEXTRA);
|
||||||
|
}
|
||||||
|
|
||||||
|
long LogEnd (long prevLSN, int xid) {
|
||||||
|
return LogCommonWriterNoExtra(prevLSN, xid, XEND);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
LogCommonWriterNoExtra writes the log record in the log tail when there is no extra data
|
||||||
|
being put in the log record -- a special case, and therefore just calls the more generalized LogCommongWriter
|
||||||
|
*/
|
||||||
|
static long LogCommonWriterNoExtra(long prevLSN, int xid, int type) {
|
||||||
|
return writeNewLog(prevLSN, xid, type, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void logInit() {
|
||||||
|
startLogStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
void logDeinit() {
|
||||||
|
closeLogStream();
|
||||||
|
/** FOR NOW, don't delete the log stream at the end, even if all transactions
|
||||||
|
* are committed because we want to debug
|
||||||
|
*/
|
||||||
|
/*deleteLogStream();*/
|
||||||
|
}
|
112
src/lladd/logger/logger2.c
Normal file
112
src/lladd/logger/logger2.c
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <lladd/bufferManager.h>
|
||||||
|
#include <lladd/logger/logger2.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
TransactionLog LogTransBegin(int xid) {
|
||||||
|
TransactionLog tl;
|
||||||
|
tl.xid = xid;
|
||||||
|
|
||||||
|
DEBUG("Log Begin %d\n", xid);
|
||||||
|
tl.prevLSN = -1;
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LogTransCommon(TransactionLog * l, int type) {
|
||||||
|
LogEntry * e = allocCommonLogEntry(l->prevLSN, l->xid, type);
|
||||||
|
writeLogEntry(e);
|
||||||
|
l->prevLSN = e->LSN;
|
||||||
|
DEBUG("Log Common %d, LSN: %ld type: %ld (prevLSN %ld)\n", e->xid,
|
||||||
|
(long int)e->LSN, (long int)e->type, (long int)e->prevLSN);
|
||||||
|
free(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogTransCommit(TransactionLog * l) {
|
||||||
|
LogTransCommon(l, XCOMMIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogTransAbort(TransactionLog * l) {
|
||||||
|
LogTransCommon(l, XABORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogEntry * LogUpdate(TransactionLog * l, recordid rid, int operation, const byte * args) {
|
||||||
|
void * preImage = NULL;
|
||||||
|
size_t argSize = 0;
|
||||||
|
LogEntry * e;
|
||||||
|
|
||||||
|
if(operationsTable[operation].sizeofData == SIZEOF_RECORD) {
|
||||||
|
argSize = rid.size;
|
||||||
|
} else {
|
||||||
|
argSize = operationsTable[operation].sizeofData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(operationsTable[operation].undo == NO_INVERSE) {
|
||||||
|
preImage = malloc(rid.size);
|
||||||
|
readRecord(l->xid, rid, preImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
e = allocUpdateLogEntry(l->prevLSN, l->xid, operation, rid, args, argSize, preImage);
|
||||||
|
writeLogEntry(e);
|
||||||
|
DEBUG("Log Common %d, LSN: %ld type: %ld (prevLSN %ld)\n", e->xid,
|
||||||
|
(long int)e->LSN, (long int)e->type, (long int)e->prevLSN);
|
||||||
|
|
||||||
|
if(preImage) {
|
||||||
|
free(preImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
l->prevLSN = e->LSN;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
lsn_t LogCLR(/*TransactionLog * l,*/ LogEntry * undone) {
|
||||||
|
lsn_t ret;
|
||||||
|
LogEntry * e = allocCLRLogEntry(-1, undone->xid, undone->LSN, undone->contents.update.rid, undone->prevLSN);
|
||||||
|
writeLogEntry(e);
|
||||||
|
DEBUG("Log CLR %d, LSN: %ld type: %ld (undoing: %ld, next to undo: %ld)\n", e->xid,
|
||||||
|
(long int)e->LSN, (long int)e->type, (long int)undone->LSN, (long int)undone->prevLSN);
|
||||||
|
|
||||||
|
ret = e->LSN;
|
||||||
|
free(e);
|
||||||
|
return ret;
|
||||||
|
}
|
316
src/lladd/logger/logparser.c
Normal file
316
src/lladd/logger/logparser.c
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/*****************
|
||||||
|
* @file
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* corresponding C file of the log parser
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* @see logEntry.c
|
||||||
|
* *************/
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "logparser.h"
|
||||||
|
#include "logstreamer.h"
|
||||||
|
|
||||||
|
static CommonLog assembleLog (long prevLSN, int xid, int type, void *extra, int extraLength);
|
||||||
|
static void writeCommonLog (CommonLog comLog);
|
||||||
|
static UpdateLog assembleUpdateLog (int funcID, recordid rid, const void *args, int arglen, int invertible, const void *preimage);
|
||||||
|
static CLRLog assembleCLRLog (long thisUpdateLSN, recordid rid, long undoNextLSN);
|
||||||
|
static int updateLogToString (char **s, UpdateLog upLog);
|
||||||
|
static int CLRLogToString (char **s, CLRLog clrlog);
|
||||||
|
long writeNewLog (long prevLSN, int xid, int type, char *extra, int extraLength) {
|
||||||
|
long thisLSN = writeStreamPos();
|
||||||
|
CommonLog tmpLog;
|
||||||
|
/* printf("LogType:%d\n", type); */
|
||||||
|
tmpLog = assembleLog(prevLSN, xid, type, extra, extraLength);
|
||||||
|
writeCommonLog (tmpLog);
|
||||||
|
if (tmpLog.extraData !=0)
|
||||||
|
free(tmpLog.extraData ); /*free up any malloc'ed string if it is there*/
|
||||||
|
if (extra != 0)
|
||||||
|
free(extra); /*free up extra space that might have been malloced previously*/
|
||||||
|
return thisLSN;
|
||||||
|
}
|
||||||
|
|
||||||
|
int updatePartsToString (char **buf, int funcID, recordid rid, const char *args, int arglen, int invertible, const void *preImage) {
|
||||||
|
UpdateLog ul;
|
||||||
|
int sizeOfString;
|
||||||
|
ul = assembleUpdateLog(funcID, rid, args, arglen, invertible, preImage);
|
||||||
|
sizeOfString = updateLogToString(buf, ul);
|
||||||
|
/* if (ul.args!=0)
|
||||||
|
free(ul.args); //deallocate the update log's arg string that was malloc'ed in assembleUpdateLog (assembleupdate log no longer mallocs. )
|
||||||
|
if (!invertible)
|
||||||
|
free(ul.preImage); */
|
||||||
|
return sizeOfString;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLRPartsToString (char **txt, long thisUpdateLSN, recordid rid, long undoNextLSN) {
|
||||||
|
return CLRLogToString(txt, assembleCLRLog(thisUpdateLSN, rid, undoNextLSN));
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonLog readNextCommonLog() {
|
||||||
|
return readCommonLogFromLSN(readPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonLog readCommonLogFromLSN(long LSN) {
|
||||||
|
byte * buf;/* char *buf;*/
|
||||||
|
long junk;
|
||||||
|
int bufPos, numObjs, extraSize;
|
||||||
|
CommonLog commonStuff;
|
||||||
|
commonStuff.LSN = LSN;
|
||||||
|
commonStuff.type = 0;
|
||||||
|
/*seekandreadlog will allocate space for buffer */
|
||||||
|
junk = seekAndReadLog(LSN, &buf);
|
||||||
|
if (junk==0) {
|
||||||
|
commonStuff.valid=0;
|
||||||
|
free(buf);
|
||||||
|
return commonStuff;
|
||||||
|
}
|
||||||
|
numObjs = sscanf ((char*)buf, "%ld %d %d", &(commonStuff.prevLSN), &(commonStuff.xid), &(commonStuff.type));
|
||||||
|
|
||||||
|
if (numObjs!=3) {
|
||||||
|
commonStuff.valid = 0;
|
||||||
|
free(buf);
|
||||||
|
return commonStuff; /*if we don't have the 3 basic ingredients, invalid log entry or at end of file, etc*/
|
||||||
|
}
|
||||||
|
commonStuff.valid = 1;
|
||||||
|
/*try to read extra data, if possible (will first have a size in bytes of the future data)
|
||||||
|
check if there is data beyond the 3 fields for optional data, and if so note where to put the data in buf*/
|
||||||
|
if (sscanf((char*)buf, "%ld %*d %*d %d %n", &junk, &extraSize, &bufPos)==2) { /*note: pos does not increase the object count of sscanf*/
|
||||||
|
/*then there is an extra string*/
|
||||||
|
commonStuff.extraData = (void*)malloc(extraSize);
|
||||||
|
commonStuff.extraDataSize = extraSize;
|
||||||
|
memcpy(commonStuff.extraData, buf+bufPos, extraSize);
|
||||||
|
/*printf ("reading extradata=%d %d; extrasize=%d, bufpos=%d\n", *(int *)commonStuff.extraData, *(int *)(commonStuff.extraData+4), extraSize, bufPos);*/
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
commonStuff.extraData = NULL;
|
||||||
|
commonStuff.extraDataSize = 0;
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return commonStuff;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateLog updateStringToParts(byte *txt) {
|
||||||
|
UpdateLog thisUpdate;
|
||||||
|
int txtPos;
|
||||||
|
long int tmp_size;
|
||||||
|
/*read in the fixed size parts and get the position of where the data begins*/
|
||||||
|
sscanf ((char*)txt, "%d %d %d %ld %d %d%n", &(thisUpdate.funcID), &(thisUpdate.rid.page),
|
||||||
|
&(thisUpdate.rid.slot), &tmp_size,/*(thisUpdate.rid.size),*/ &(thisUpdate.invertible), &thisUpdate.argSize, &txtPos);
|
||||||
|
thisUpdate.rid.size = (size_t) tmp_size;
|
||||||
|
txtPos++; /*there is an additional space between the argSize and the arg data*/
|
||||||
|
thisUpdate.args = (void*)malloc(thisUpdate.argSize);
|
||||||
|
memcpy((byte*)thisUpdate.args, txt+txtPos, thisUpdate.argSize);
|
||||||
|
txtPos += 1+thisUpdate.argSize;
|
||||||
|
if (!thisUpdate.invertible) {
|
||||||
|
thisUpdate.preImage = (void*)malloc(thisUpdate.rid.size);
|
||||||
|
/* Remove the const qualifier from preImage so that we can initialize the malloced memory. */
|
||||||
|
memcpy((void*)thisUpdate.preImage, txt+txtPos, thisUpdate.rid.size);
|
||||||
|
}
|
||||||
|
return thisUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLRLog CLRStringToParts (void *txt) {
|
||||||
|
CLRLog clrlog;
|
||||||
|
long int size_tmp;
|
||||||
|
sscanf(txt, "%ld %d %d %ld %ld", &(clrlog.thisUpdateLSN), &(clrlog.rid.page), &(clrlog.rid.slot), &(size_tmp), &(clrlog.undoNextLSN));
|
||||||
|
clrlog.rid.size = (size_t) size_tmp;
|
||||||
|
return clrlog;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Fix string buffer size!!! */
|
||||||
|
int allocPartsToString (char **txt, recordid rid) {
|
||||||
|
|
||||||
|
return asprintf(txt, "%d %d %ld", rid.page, rid.slot, (long int)rid.size);
|
||||||
|
/* *txt = malloc(2*sizeof(int)+sizeof(long)+200);
|
||||||
|
sprintf (*txt, "%d %d %ld", rid.page, rid.slot, rid.size); */
|
||||||
|
/*memcpy(txt, &rid, sizeof(recordid));
|
||||||
|
printf ("writing rid=%d,%d,%ld\n", rid.page, rid.slot, rid.size);*/
|
||||||
|
/*return sizeof(recordid);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
recordid allocStringToRID (void *txt) {
|
||||||
|
recordid tmp;
|
||||||
|
long int tmp2;
|
||||||
|
sscanf(txt, "%d %d %ld", &tmp.page, &tmp.slot, &tmp2);
|
||||||
|
tmp.size = (size_t)tmp2;
|
||||||
|
/*memcpy(&tmp, txt, sizeof(recordid));
|
||||||
|
printf ("reading rid=%d,%d,%ld\n", tmp.page, tmp.slot, tmp.size);*/
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************ PRIVATE WRITING-RELATED FUNCTIONS ********************/
|
||||||
|
/*
|
||||||
|
put the pieces of a complete (common) log into the structure
|
||||||
|
*/
|
||||||
|
static CommonLog assembleLog (long prevLSN, int xid, int type, void *extra, int extraLength) {
|
||||||
|
CommonLog tmp;
|
||||||
|
tmp.prevLSN = prevLSN;
|
||||||
|
tmp.xid = xid;
|
||||||
|
tmp.type = type;
|
||||||
|
tmp.valid = 1;
|
||||||
|
tmp.extraDataSize = extraLength;
|
||||||
|
if (extraLength==0)
|
||||||
|
tmp.extraData = NULL;
|
||||||
|
else {
|
||||||
|
tmp.extraData = (void*)malloc(extraLength);
|
||||||
|
memcpy(tmp.extraData, extra, extraLength);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
marshal an common log into the log file
|
||||||
|
*/
|
||||||
|
static void writeCommonLog (CommonLog comLog) {
|
||||||
|
char *buf;
|
||||||
|
int bytesWritten;
|
||||||
|
if (comLog.extraDataSize==0) {
|
||||||
|
/*TODO: Fix buffer size! (Throughout file) */
|
||||||
|
/* buf = malloc(2*sizeof(int)+sizeof(long)+200); */
|
||||||
|
bytesWritten = asprintf (&buf, "%ld %d %d", comLog.prevLSN, comLog.xid, comLog.type);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char * buf2;
|
||||||
|
/* buf = malloc(3*sizeof(int)+sizeof(long)+200+4+comLog.extraDataSize); */
|
||||||
|
/*first print all the ordinary components plus a space, then size of extra; note the last byte put into sprintf*/
|
||||||
|
bytesWritten = asprintf (&buf, "%ld %d %d %d ", comLog.prevLSN, comLog.xid, comLog.type, comLog.extraDataSize);
|
||||||
|
buf2 = malloc(bytesWritten + comLog.extraDataSize);
|
||||||
|
memcpy (buf2, buf, bytesWritten);
|
||||||
|
free(buf);
|
||||||
|
buf = buf2;
|
||||||
|
/*directly write the data into the buffer after the rest of the stuff*/
|
||||||
|
memcpy (buf+bytesWritten, comLog.extraData, comLog.extraDataSize);
|
||||||
|
/*printf("writing extra=%d %d\n", *(int *)comLog.extraData, *(int *)(comLog.extraData+4));*/
|
||||||
|
}
|
||||||
|
writeLog(buf, bytesWritten+comLog.extraDataSize);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Given all the components of an update log, will produce an update log
|
||||||
|
|
||||||
|
Returns an UpdateLog
|
||||||
|
NOTE: mallocates the output log's args string, so must be freed after use (Not true any more.)
|
||||||
|
*/
|
||||||
|
static UpdateLog assembleUpdateLog (int funcID, recordid rid, const void *args, int arglen, int invertible, const void *preimage) {
|
||||||
|
UpdateLog tmpLog;
|
||||||
|
tmpLog.funcID = funcID;
|
||||||
|
tmpLog.rid = rid;
|
||||||
|
/* tmpLog.args = (void*)malloc(arglen); */
|
||||||
|
tmpLog.argSize = arglen;
|
||||||
|
tmpLog.invertible = invertible;
|
||||||
|
/* memcpy (tmpLog.args, args, arglen); */
|
||||||
|
|
||||||
|
tmpLog.args = args;
|
||||||
|
|
||||||
|
if (!invertible) {
|
||||||
|
/*Don't need this? Just set the pointer... */
|
||||||
|
/* tmpLog.preImage = (void*)malloc(rid.size);
|
||||||
|
memcpy(tmpLog.preImage, preimage, rid.size); */
|
||||||
|
tmpLog.preImage = preimage;
|
||||||
|
} else {
|
||||||
|
tmpLog.preImage = 0;
|
||||||
|
}
|
||||||
|
return tmpLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CLRLog assembleCLRLog (long thisUpdateLSN, recordid rid, long undoNextLSN) {
|
||||||
|
CLRLog tmpLog;
|
||||||
|
tmpLog.thisUpdateLSN = thisUpdateLSN;
|
||||||
|
tmpLog.rid = rid;
|
||||||
|
tmpLog.undoNextLSN = undoNextLSN;
|
||||||
|
return tmpLog;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
marshal an update log into a string (assume the string space has been allocated)
|
||||||
|
returns number of bytes written to the string
|
||||||
|
*/
|
||||||
|
static int updateLogToString (char **s, UpdateLog upLog) {
|
||||||
|
int bytesWritten;
|
||||||
|
/* int maxDigitsForInt = 25; //32767 is 5 digits, plus a negative
|
||||||
|
int maxDigitsForLong = 25;
|
||||||
|
int estSize = 5*maxDigitsForInt+maxDigitsForLong+6+upLog.argSize;*/
|
||||||
|
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
/* if (!upLog.invertible)
|
||||||
|
estSize+=1+upLog.rid.size; */
|
||||||
|
|
||||||
|
|
||||||
|
bytesWritten = asprintf (&tmp, "%d %d %d %ld %d %d ", upLog.funcID, upLog.rid.page, upLog.rid.slot, (long int)upLog.rid.size, upLog.invertible, upLog.argSize);
|
||||||
|
|
||||||
|
*s = malloc(bytesWritten + upLog.argSize);
|
||||||
|
memcpy(*s, tmp, bytesWritten);
|
||||||
|
free (tmp);
|
||||||
|
memcpy(*s+bytesWritten, upLog.args, upLog.argSize);
|
||||||
|
bytesWritten+=upLog.argSize;
|
||||||
|
if (!upLog.invertible) {
|
||||||
|
tmp = *s;
|
||||||
|
*s = malloc(bytesWritten+1 +upLog.rid.size);
|
||||||
|
memcpy(*s, tmp, bytesWritten);
|
||||||
|
free (tmp);
|
||||||
|
|
||||||
|
sprintf (*s+bytesWritten, " ");
|
||||||
|
memcpy(*s+bytesWritten+1, upLog.preImage, upLog.rid.size);
|
||||||
|
bytesWritten += 1 + upLog.rid.size;
|
||||||
|
}
|
||||||
|
return bytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CLRLogToString (char **s, CLRLog clrlog) {
|
||||||
|
/* int estSize = 3*sizeof(long)+2*sizeof(int)+400; */
|
||||||
|
int bytesWritten;
|
||||||
|
/* *s = malloc(estSize); */
|
||||||
|
bytesWritten = asprintf (s, "%ld %d %d %ld %ld ", clrlog.thisUpdateLSN, clrlog.rid.page, clrlog.rid.slot, (long int)clrlog.rid.size, clrlog.undoNextLSN);
|
||||||
|
/* if (bytesWritten!=estSize) {
|
||||||
|
//error!
|
||||||
|
}*/
|
||||||
|
return bytesWritten;
|
||||||
|
}
|
206
src/lladd/logger/logparser.h
Normal file
206
src/lladd/logger/logparser.h
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* logparser implements the specific formats of the log entrys to be read and
|
||||||
|
* written in the log file.
|
||||||
|
*
|
||||||
|
* All log entries have some fields in common (always) - a previous LSN, a
|
||||||
|
* transaction id, a log type, and any extra text specific to the type of entry.
|
||||||
|
* The extra text may be NULL, in which case there is no extra text! If there is
|
||||||
|
* extra text, additional public functions are written to put together and take
|
||||||
|
* apart the string into its object.
|
||||||
|
*
|
||||||
|
* This has been entirely rewritten. Don't use it.
|
||||||
|
*
|
||||||
|
* @deprecated @see logEntry.h
|
||||||
|
*
|
||||||
|
* Proposed api:
|
||||||
|
|
||||||
|
|
||||||
|
All of these return a pointer to a single malloced region that should be freed.
|
||||||
|
|
||||||
|
allocCommonLogEntry(LSN, prevLSN, xid, type);
|
||||||
|
allocUpdateLogEntry(LSN, prevLSN, xid, type=UPDATE, funcID, rid, args, argSize, preImage);
|
||||||
|
allocCLRLogEntry (LSN, prevLSN, xid, type=CLR, thisUpdateLSN, rid, undoNextLSN);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
thisUpdateLSN;
|
||||||
|
rid;
|
||||||
|
undoNextLSN;
|
||||||
|
} CLRLogEntry;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
funcID;
|
||||||
|
rid;
|
||||||
|
argSize;
|
||||||
|
/ * Implicit members:
|
||||||
|
args; @ ((byte*)ule) + sizeof(UpdateLogEntry)
|
||||||
|
preImage; @ ((byte*)ule) + sizeof(UpdateLogEntry) + ule.argSize * /
|
||||||
|
} UpdateLogEntry;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
LSN;
|
||||||
|
prevLSN;
|
||||||
|
xid;
|
||||||
|
type;
|
||||||
|
union {
|
||||||
|
UpdateLogEntry update;
|
||||||
|
CLRLogEntry clr;
|
||||||
|
} contents;
|
||||||
|
} LogEntry;
|
||||||
|
|
||||||
|
sizeofLogEntry(LogEntry *);
|
||||||
|
size_t getUpdateArgs(LogEntry *);
|
||||||
|
size_t getUpdatePreImage(LogEntry *);
|
||||||
|
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __LOGPARSER_H__
|
||||||
|
#define __LOGPARSER_H__
|
||||||
|
|
||||||
|
#include <lladd/page.h>
|
||||||
|
#include <lladd/constants.h>
|
||||||
|
|
||||||
|
/* max the log line can be is 2 pages (set redo and undo data possibly) plus
|
||||||
|
* some more log stuff */
|
||||||
|
/*#define maxLogLineLength 2*PAGE_SIZE + 100 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
fields common to all log entries
|
||||||
|
extra could be null, indicating no extra data needed
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/**LSN field is ignored when writing to log, since it is determined
|
||||||
|
by the writer */
|
||||||
|
long LSN;
|
||||||
|
long prevLSN;
|
||||||
|
int xid;
|
||||||
|
int type;
|
||||||
|
void *extraData;
|
||||||
|
int extraDataSize;
|
||||||
|
int valid;
|
||||||
|
} CommonLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update Log components (that are normally stored in the 'extra' field of a common log
|
||||||
|
|
||||||
|
The preimage is used for undos of operations with no inverses, and
|
||||||
|
the args field is used for the redo process, and inverse functions.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/**what function it is*/
|
||||||
|
int funcID;
|
||||||
|
/**page and slot number*/
|
||||||
|
recordid rid;
|
||||||
|
/**binary data of the function arguments*/
|
||||||
|
const byte *args;
|
||||||
|
int argSize;
|
||||||
|
int invertible;
|
||||||
|
/**if funcID is not invertible will store a preImage with size=rid.size*/
|
||||||
|
const byte *preImage;
|
||||||
|
} UpdateLog;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* UpdateLog ul; //has everything in an update log */
|
||||||
|
long thisUpdateLSN;
|
||||||
|
recordid rid;
|
||||||
|
long undoNextLSN;
|
||||||
|
} CLRLog;
|
||||||
|
|
||||||
|
|
||||||
|
/********* PUBLIC WRITING-RELATED FUNCTIONS **************/
|
||||||
|
/**
|
||||||
|
Given all the necessary components of a log entry, assemble it and then write it to the log file
|
||||||
|
|
||||||
|
return the LSN of this new log entry
|
||||||
|
|
||||||
|
*/
|
||||||
|
long writeNewLog (long prevLSN, int xid, int type, char *extra, int extraLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
put all of the components of the extra part of an update log into a buffer
|
||||||
|
returns the length of the string written to buf
|
||||||
|
|
||||||
|
@ todo Logparser shouldn't write to char**
|
||||||
|
*/
|
||||||
|
int updatePartsToString (char **buf, int funcID, recordid rid, const char *args, int arglen, int invertible, const void *preImage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Takes in a buffer and a record id and copies the recordid into the buffer
|
||||||
|
*/
|
||||||
|
int allocPartsToString (char **txt, recordid rid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
*/
|
||||||
|
int CLRPartsToString (char **txt, long thisUpdateLSN, recordid rid, long undoNextLSN);
|
||||||
|
/********* PUBLIC READING-RELATED FUNCTIONS **************/
|
||||||
|
/**
|
||||||
|
parse a log line that only parses entries common to all log records into its structure. Can specify an LSN
|
||||||
|
|
||||||
|
NOTE: the extra part of CommonLog might have a malloc'ed string in it; should be freed after use
|
||||||
|
*/
|
||||||
|
CommonLog readNextCommonLog();
|
||||||
|
CommonLog readCommonLogFromLSN(long LSN);
|
||||||
|
|
||||||
|
|
||||||
|
CLRLog readCLRLogFromLSN(long LSN);
|
||||||
|
/**
|
||||||
|
parse the extra part of an update log record into an UpdateLog structure
|
||||||
|
|
||||||
|
NOTE: the args part of the UpdateLog has a malloc'ed string in it; should be freed after use
|
||||||
|
*/
|
||||||
|
UpdateLog updateStringToParts(byte *txt);
|
||||||
|
|
||||||
|
CLRLog CLRStringToParts (void *txt);
|
||||||
|
/**
|
||||||
|
Read a buffer and parse it into a recordid
|
||||||
|
*/
|
||||||
|
recordid allocStringToRID (void *txt);
|
||||||
|
|
||||||
|
#endif
|
148
src/lladd/logger/logstreamer.c
Normal file
148
src/lladd/logger/logstreamer.c
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/*****************
|
||||||
|
$Id$
|
||||||
|
|
||||||
|
the C implementation of logstreamer.h
|
||||||
|
******************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <lladd/constants.h>
|
||||||
|
#include "logstreamer.h"
|
||||||
|
|
||||||
|
static FILE *log;
|
||||||
|
|
||||||
|
int startLogStream() {
|
||||||
|
log = fopen(LOG_FILE, "a+");
|
||||||
|
if (log==NULL) {
|
||||||
|
/*there was an error opening this file */
|
||||||
|
return FILE_WRITE_OPEN_ERROR;
|
||||||
|
}
|
||||||
|
/*if file is empty, write a null at the 0th character */
|
||||||
|
if (streamPos()==0)
|
||||||
|
fputs("0", log);
|
||||||
|
/*start reading at the 1st character*/
|
||||||
|
fseek(log, 1, SEEK_SET);
|
||||||
|
return 0; /*otherwise return 0 for no errors*/
|
||||||
|
}
|
||||||
|
|
||||||
|
int writeLog(void *s, int length) {
|
||||||
|
/* int i; */
|
||||||
|
fprintf(log, "%d ", length); /*print out the size of this log entry (not including this item and the \n */
|
||||||
|
|
||||||
|
if(1 != fwrite(s, length, 1, log)) {
|
||||||
|
|
||||||
|
/* for( i = 0; i < length; i++ ) {
|
||||||
|
if(fputc(*(char*)(s+i), log) == EOF) { //write the string to the log tail*/
|
||||||
|
perror("logstreamer: fputc");
|
||||||
|
assert(0);
|
||||||
|
/* } */
|
||||||
|
}
|
||||||
|
fprintf (log, "\n"); /*then write a carriage return just for our viewing pleasure*/
|
||||||
|
return 0; /*otherwise, no errors*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void flushLog() {
|
||||||
|
fflush(log);
|
||||||
|
/* fsync(fileno(log)); */
|
||||||
|
fdatasync(fileno(log));
|
||||||
|
}
|
||||||
|
|
||||||
|
void closeLogStream() {
|
||||||
|
fclose(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteLogStream() {
|
||||||
|
remove(LOG_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
long streamPos() {
|
||||||
|
return ftell(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Assumes we're already @ EOF. */
|
||||||
|
long writeStreamPos() {
|
||||||
|
/* long cur = ftell(log);
|
||||||
|
fseek(log, 0, SEEK_END);
|
||||||
|
assert(cur == ftell(log));*/
|
||||||
|
return ftell(log);
|
||||||
|
/* long curPos = streamPos();
|
||||||
|
long returnVal;
|
||||||
|
fseek(log, 0, SEEK_END);
|
||||||
|
returnVal = ftell(log);
|
||||||
|
fseek(log, curPos, SEEK_SET);
|
||||||
|
return returnVal;*/
|
||||||
|
}
|
||||||
|
int readLog(byte **buffer) {
|
||||||
|
int length, i;
|
||||||
|
*buffer = 0;
|
||||||
|
if (feof(log)) return 0;
|
||||||
|
fscanf(log, "%d ", &length);
|
||||||
|
if (feof(log)) return 0;
|
||||||
|
/*get length characters from the log at this point and put them
|
||||||
|
into the buffer */
|
||||||
|
*buffer = malloc(length+5); /*5 extra just to be safe*/
|
||||||
|
for (i=0; i<length; i++)
|
||||||
|
*(char*)(*buffer+i) = fgetc(log);
|
||||||
|
/*experiment: null terminate the buffer to avoid read leaks over the memory just in case */
|
||||||
|
*(char*)(*buffer+i) = '\0';
|
||||||
|
/*then read in the newline that was put in to be nice */
|
||||||
|
fgetc(log);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int seekAndReadLog(long pos, byte **buffer) {
|
||||||
|
fseek(log, pos, 0); /*seek to pos positions from the beginning of the file*/
|
||||||
|
return readLog(buffer);
|
||||||
|
}
|
||||||
|
void seekInLog(long pos) {
|
||||||
|
fseek(log, pos, 0);
|
||||||
|
}
|
||||||
|
long readPos () {
|
||||||
|
return ftell(log);
|
||||||
|
}
|
135
src/lladd/logger/logstreamer.h
Normal file
135
src/lladd/logger/logstreamer.h
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/** ***************
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* 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 ot 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.
|
||||||
|
*
|
||||||
|
* @deprecated @see logWriter.h logHandle.h
|
||||||
|
*
|
||||||
|
* *************/
|
||||||
|
|
||||||
|
#ifndef __LOGSTREAMER_H__
|
||||||
|
#define __LOGSTREAMER_H__
|
||||||
|
|
||||||
|
#include <lladd/constants.h>
|
||||||
|
#include <lladd/common.h>
|
||||||
|
/*
|
||||||
|
start a new log stream by opening the log file for reading
|
||||||
|
|
||||||
|
returns 0 on success, or an error code define above
|
||||||
|
*/
|
||||||
|
int startLogStream();
|
||||||
|
|
||||||
|
/*
|
||||||
|
passed an address with data in it, writes it out to the log tail (not yet
|
||||||
|
flushed)
|
||||||
|
|
||||||
|
returns 0 on success, or an error code defined above
|
||||||
|
*/
|
||||||
|
int writeLog(void *s, int length);
|
||||||
|
|
||||||
|
/*
|
||||||
|
flush the entire log (tail) that is currently in memory to disk
|
||||||
|
*/
|
||||||
|
void flushLog();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Close the log stream
|
||||||
|
*/
|
||||||
|
void closeLogStream();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the current position of the stream (in terms of bytes)
|
||||||
|
*/
|
||||||
|
long getFilePos();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Actually deletes the log file that may have been written to disk! Danger!!
|
||||||
|
Only use after calling closeLogStream AND you are sure there are no active (or
|
||||||
|
future active) transactions!
|
||||||
|
*/
|
||||||
|
void deleteLogStream();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the current position of the stream no matter where it is
|
||||||
|
*/
|
||||||
|
long streamPos();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the position of the stream if it were to read.
|
||||||
|
*/
|
||||||
|
long writeStreamPos();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* readLog reads a line from the log puts it in a string
|
||||||
|
*
|
||||||
|
* returns the number of bytes read and put into buffer
|
||||||
|
* */
|
||||||
|
int readLog(byte **buffer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* seek to a position in the log file and read it into the buffer
|
||||||
|
*
|
||||||
|
* returns the number of bytes read and put into buffer
|
||||||
|
* */
|
||||||
|
int seekAndReadLog(long pos, byte **buffer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tell the current position in the log file
|
||||||
|
* */
|
||||||
|
long readPos ();
|
||||||
|
|
||||||
|
void seekInLog(long pos);
|
||||||
|
#endif
|
113
src/lladd/operations.c
Normal file
113
src/lladd/operations.c
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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 <lladd/operations.h>
|
||||||
|
|
||||||
|
#include <lladd/logger/logWriter.h>
|
||||||
|
#include <lladd/bufferManager.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
Operation operationsTable[MAX_OPERATIONS];
|
||||||
|
|
||||||
|
void doUpdate(const LogEntry * e) {
|
||||||
|
operationsTable[e->contents.update.funcID].run(e->xid, e->contents.update.rid, getUpdateArgs(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
void redoUpdate(const LogEntry * e) {
|
||||||
|
if(e->type == UPDATELOG) {
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
recordid rid = e->contents.update.rid;
|
||||||
|
#endif
|
||||||
|
if(e->LSN > readLSN(e->contents.update.rid.page)) {
|
||||||
|
DEBUG("Redo, %ld {%d %d %d}\n", e->LSN, rid.page, rid.slot, rid.size);
|
||||||
|
doUpdate(e);
|
||||||
|
} else {
|
||||||
|
DEBUG("Skipping redo, %ld {%d %d %d}\n", e->LSN, rid.page, rid.slot, rid.size);
|
||||||
|
}
|
||||||
|
} else if(e->type == CLRLOG) {
|
||||||
|
LogEntry * f = readLSNEntry(e->contents.clr.thisUpdateLSN);
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
recordid rid = f->contents.update.rid;
|
||||||
|
#endif
|
||||||
|
/* See if the page contains the result of the undo that this CLR is supposed to perform. If it
|
||||||
|
doesn't, then undo the original operation. */
|
||||||
|
if(f->LSN > readLSN(e->contents.update.rid.page)) {
|
||||||
|
|
||||||
|
DEBUG("Undoing for clr, %ld {%d %d %d}\n", f->LSN, rid.page, rid.slot, rid.size);
|
||||||
|
undoUpdate(f);
|
||||||
|
} else {
|
||||||
|
DEBUG("Skiping undo for clr, %ld {%d %d %d}\n", f->LSN, rid.page, rid.slot, rid.size);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void undoUpdate(const LogEntry * e) {
|
||||||
|
|
||||||
|
int undo = operationsTable[e->contents.update.funcID].undo;
|
||||||
|
/* printf("FuncID: %d Undo op: %d\n",e->contents.update.funcID, undo); fflush(NULL); */
|
||||||
|
if(e->LSN <= readLSN(e->contents.update.rid.page)) {
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
recordid rid = e->contents.update.rid;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Actually execute the undo */
|
||||||
|
if(undo == NO_INVERSE) {
|
||||||
|
/* Physical undo */
|
||||||
|
|
||||||
|
DEBUG("Physical undo, %ld {%d %d %d}\n", e->LSN, rid.page, rid.slot, rid.size);
|
||||||
|
/** @todo Why were we passing in RECOVERY_XID? */
|
||||||
|
writeRecord(e->xid, e->contents.update.rid, getUpdatePreImage(e));
|
||||||
|
} else {
|
||||||
|
/* @see doUpdate() */
|
||||||
|
/* printf("Logical undo"); fflush(NULL); */
|
||||||
|
DEBUG("Logical undo, %ld {%d %d %d}\n", e->LSN, rid.page, rid.slot, rid.size);
|
||||||
|
operationsTable[undo].run(e->xid, e->contents.update.rid, getUpdateArgs(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* printf("Undo done."); fflush(NULL); */
|
||||||
|
|
||||||
|
}
|
122
src/lladd/operations/.deps/decrement.Po
Normal file
122
src/lladd/operations/.deps/decrement.Po
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
decrement.o decrement.o: decrement.c \
|
||||||
|
../../../lladd/operations/decrement.h ../../../lladd/constants.h \
|
||||||
|
../../../lladd/operations.h ../../../lladd/common.h \
|
||||||
|
../../../lladd/config.h /usr/include/stdio.h /usr/include/features.h \
|
||||||
|
/usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h \
|
||||||
|
/usr/include/bits/types.h /usr/include/bits/wordsize.h \
|
||||||
|
/usr/include/bits/typesizes.h /usr/include/libio.h \
|
||||||
|
/usr/include/_G_config.h /usr/include/wchar.h /usr/include/bits/wchar.h \
|
||||||
|
/usr/include/gconv.h /usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h \
|
||||||
|
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
|
||||||
|
/usr/include/bits/stdio.h /usr/include/sys/types.h /usr/include/time.h \
|
||||||
|
/usr/include/endian.h /usr/include/bits/endian.h \
|
||||||
|
/usr/include/sys/select.h /usr/include/bits/select.h \
|
||||||
|
/usr/include/bits/sigset.h /usr/include/bits/time.h \
|
||||||
|
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
|
||||||
|
/usr/include/bits/sched.h /usr/include/stdlib.h /usr/include/alloca.h \
|
||||||
|
/usr/include/string.h /usr/include/bits/string.h \
|
||||||
|
/usr/include/bits/string2.h /usr/include/unistd.h \
|
||||||
|
/usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
|
||||||
|
/usr/include/getopt.h ../../../lladd/page.h \
|
||||||
|
../../../lladd/operations/increment.h ../../../lladd/bufferManager.h \
|
||||||
|
../../../lladd/operations/set.h ../../../lladd/operations/prepare.h \
|
||||||
|
../../../lladd/operations/lladdhash.h ../../../lladd/transactional.h
|
||||||
|
|
||||||
|
../../../lladd/operations/decrement.h:
|
||||||
|
|
||||||
|
../../../lladd/constants.h:
|
||||||
|
|
||||||
|
../../../lladd/operations.h:
|
||||||
|
|
||||||
|
../../../lladd/common.h:
|
||||||
|
|
||||||
|
../../../lladd/config.h:
|
||||||
|
|
||||||
|
/usr/include/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/features.h:
|
||||||
|
|
||||||
|
/usr/include/sys/cdefs.h:
|
||||||
|
|
||||||
|
/usr/include/gnu/stubs.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h:
|
||||||
|
|
||||||
|
/usr/include/bits/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wordsize.h:
|
||||||
|
|
||||||
|
/usr/include/bits/typesizes.h:
|
||||||
|
|
||||||
|
/usr/include/libio.h:
|
||||||
|
|
||||||
|
/usr/include/_G_config.h:
|
||||||
|
|
||||||
|
/usr/include/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/gconv.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio_lim.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sys_errlist.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/sys/types.h:
|
||||||
|
|
||||||
|
/usr/include/time.h:
|
||||||
|
|
||||||
|
/usr/include/endian.h:
|
||||||
|
|
||||||
|
/usr/include/bits/endian.h:
|
||||||
|
|
||||||
|
/usr/include/sys/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sigset.h:
|
||||||
|
|
||||||
|
/usr/include/bits/time.h:
|
||||||
|
|
||||||
|
/usr/include/sys/sysmacros.h:
|
||||||
|
|
||||||
|
/usr/include/bits/pthreadtypes.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sched.h:
|
||||||
|
|
||||||
|
/usr/include/stdlib.h:
|
||||||
|
|
||||||
|
/usr/include/alloca.h:
|
||||||
|
|
||||||
|
/usr/include/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string2.h:
|
||||||
|
|
||||||
|
/usr/include/unistd.h:
|
||||||
|
|
||||||
|
/usr/include/bits/posix_opt.h:
|
||||||
|
|
||||||
|
/usr/include/bits/confname.h:
|
||||||
|
|
||||||
|
/usr/include/getopt.h:
|
||||||
|
|
||||||
|
../../../lladd/page.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/increment.h:
|
||||||
|
|
||||||
|
../../../lladd/bufferManager.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/set.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/prepare.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/lladdhash.h:
|
||||||
|
|
||||||
|
../../../lladd/transactional.h:
|
122
src/lladd/operations/.deps/increment.Po
Normal file
122
src/lladd/operations/.deps/increment.Po
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
increment.o increment.o: increment.c \
|
||||||
|
../../../lladd/operations/increment.h ../../../lladd/constants.h \
|
||||||
|
../../../lladd/operations.h ../../../lladd/common.h \
|
||||||
|
../../../lladd/config.h /usr/include/stdio.h /usr/include/features.h \
|
||||||
|
/usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h \
|
||||||
|
/usr/include/bits/types.h /usr/include/bits/wordsize.h \
|
||||||
|
/usr/include/bits/typesizes.h /usr/include/libio.h \
|
||||||
|
/usr/include/_G_config.h /usr/include/wchar.h /usr/include/bits/wchar.h \
|
||||||
|
/usr/include/gconv.h /usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h \
|
||||||
|
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
|
||||||
|
/usr/include/bits/stdio.h /usr/include/sys/types.h /usr/include/time.h \
|
||||||
|
/usr/include/endian.h /usr/include/bits/endian.h \
|
||||||
|
/usr/include/sys/select.h /usr/include/bits/select.h \
|
||||||
|
/usr/include/bits/sigset.h /usr/include/bits/time.h \
|
||||||
|
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
|
||||||
|
/usr/include/bits/sched.h /usr/include/stdlib.h /usr/include/alloca.h \
|
||||||
|
/usr/include/string.h /usr/include/bits/string.h \
|
||||||
|
/usr/include/bits/string2.h /usr/include/unistd.h \
|
||||||
|
/usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
|
||||||
|
/usr/include/getopt.h ../../../lladd/page.h \
|
||||||
|
../../../lladd/operations/decrement.h ../../../lladd/bufferManager.h \
|
||||||
|
../../../lladd/operations/set.h ../../../lladd/operations/prepare.h \
|
||||||
|
../../../lladd/operations/lladdhash.h ../../../lladd/transactional.h
|
||||||
|
|
||||||
|
../../../lladd/operations/increment.h:
|
||||||
|
|
||||||
|
../../../lladd/constants.h:
|
||||||
|
|
||||||
|
../../../lladd/operations.h:
|
||||||
|
|
||||||
|
../../../lladd/common.h:
|
||||||
|
|
||||||
|
../../../lladd/config.h:
|
||||||
|
|
||||||
|
/usr/include/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/features.h:
|
||||||
|
|
||||||
|
/usr/include/sys/cdefs.h:
|
||||||
|
|
||||||
|
/usr/include/gnu/stubs.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h:
|
||||||
|
|
||||||
|
/usr/include/bits/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wordsize.h:
|
||||||
|
|
||||||
|
/usr/include/bits/typesizes.h:
|
||||||
|
|
||||||
|
/usr/include/libio.h:
|
||||||
|
|
||||||
|
/usr/include/_G_config.h:
|
||||||
|
|
||||||
|
/usr/include/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/gconv.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio_lim.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sys_errlist.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/sys/types.h:
|
||||||
|
|
||||||
|
/usr/include/time.h:
|
||||||
|
|
||||||
|
/usr/include/endian.h:
|
||||||
|
|
||||||
|
/usr/include/bits/endian.h:
|
||||||
|
|
||||||
|
/usr/include/sys/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sigset.h:
|
||||||
|
|
||||||
|
/usr/include/bits/time.h:
|
||||||
|
|
||||||
|
/usr/include/sys/sysmacros.h:
|
||||||
|
|
||||||
|
/usr/include/bits/pthreadtypes.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sched.h:
|
||||||
|
|
||||||
|
/usr/include/stdlib.h:
|
||||||
|
|
||||||
|
/usr/include/alloca.h:
|
||||||
|
|
||||||
|
/usr/include/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string2.h:
|
||||||
|
|
||||||
|
/usr/include/unistd.h:
|
||||||
|
|
||||||
|
/usr/include/bits/posix_opt.h:
|
||||||
|
|
||||||
|
/usr/include/bits/confname.h:
|
||||||
|
|
||||||
|
/usr/include/getopt.h:
|
||||||
|
|
||||||
|
../../../lladd/page.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/decrement.h:
|
||||||
|
|
||||||
|
../../../lladd/bufferManager.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/set.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/prepare.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/lladdhash.h:
|
||||||
|
|
||||||
|
../../../lladd/transactional.h:
|
127
src/lladd/operations/.deps/lladdhash.Po
Normal file
127
src/lladd/operations/.deps/lladdhash.Po
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
lladdhash.o lladdhash.o: lladdhash.c \
|
||||||
|
../../../lladd/operations/lladdhash.h ../../../lladd/transactional.h \
|
||||||
|
../../../lladd/common.h ../../../lladd/config.h /usr/include/stdio.h \
|
||||||
|
/usr/include/features.h /usr/include/sys/cdefs.h \
|
||||||
|
/usr/include/gnu/stubs.h \
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h \
|
||||||
|
/usr/include/bits/types.h /usr/include/bits/wordsize.h \
|
||||||
|
/usr/include/bits/typesizes.h /usr/include/libio.h \
|
||||||
|
/usr/include/_G_config.h /usr/include/wchar.h /usr/include/bits/wchar.h \
|
||||||
|
/usr/include/gconv.h /usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h \
|
||||||
|
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
|
||||||
|
/usr/include/bits/stdio.h /usr/include/sys/types.h /usr/include/time.h \
|
||||||
|
/usr/include/endian.h /usr/include/bits/endian.h \
|
||||||
|
/usr/include/sys/select.h /usr/include/bits/select.h \
|
||||||
|
/usr/include/bits/sigset.h /usr/include/bits/time.h \
|
||||||
|
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
|
||||||
|
/usr/include/bits/sched.h /usr/include/stdlib.h /usr/include/alloca.h \
|
||||||
|
/usr/include/string.h /usr/include/bits/string.h \
|
||||||
|
/usr/include/bits/string2.h /usr/include/unistd.h \
|
||||||
|
/usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
|
||||||
|
/usr/include/getopt.h ../../../lladd/page.h ../../../lladd/operations.h \
|
||||||
|
../../../lladd/constants.h ../../../lladd/operations/increment.h \
|
||||||
|
../../../lladd/bufferManager.h ../../../lladd/operations/decrement.h \
|
||||||
|
../../../lladd/operations/set.h ../../../lladd/operations/prepare.h \
|
||||||
|
/usr/include/assert.h /usr/include/memory.h
|
||||||
|
|
||||||
|
../../../lladd/operations/lladdhash.h:
|
||||||
|
|
||||||
|
../../../lladd/transactional.h:
|
||||||
|
|
||||||
|
../../../lladd/common.h:
|
||||||
|
|
||||||
|
../../../lladd/config.h:
|
||||||
|
|
||||||
|
/usr/include/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/features.h:
|
||||||
|
|
||||||
|
/usr/include/sys/cdefs.h:
|
||||||
|
|
||||||
|
/usr/include/gnu/stubs.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h:
|
||||||
|
|
||||||
|
/usr/include/bits/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wordsize.h:
|
||||||
|
|
||||||
|
/usr/include/bits/typesizes.h:
|
||||||
|
|
||||||
|
/usr/include/libio.h:
|
||||||
|
|
||||||
|
/usr/include/_G_config.h:
|
||||||
|
|
||||||
|
/usr/include/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/gconv.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio_lim.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sys_errlist.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/sys/types.h:
|
||||||
|
|
||||||
|
/usr/include/time.h:
|
||||||
|
|
||||||
|
/usr/include/endian.h:
|
||||||
|
|
||||||
|
/usr/include/bits/endian.h:
|
||||||
|
|
||||||
|
/usr/include/sys/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sigset.h:
|
||||||
|
|
||||||
|
/usr/include/bits/time.h:
|
||||||
|
|
||||||
|
/usr/include/sys/sysmacros.h:
|
||||||
|
|
||||||
|
/usr/include/bits/pthreadtypes.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sched.h:
|
||||||
|
|
||||||
|
/usr/include/stdlib.h:
|
||||||
|
|
||||||
|
/usr/include/alloca.h:
|
||||||
|
|
||||||
|
/usr/include/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string2.h:
|
||||||
|
|
||||||
|
/usr/include/unistd.h:
|
||||||
|
|
||||||
|
/usr/include/bits/posix_opt.h:
|
||||||
|
|
||||||
|
/usr/include/bits/confname.h:
|
||||||
|
|
||||||
|
/usr/include/getopt.h:
|
||||||
|
|
||||||
|
../../../lladd/page.h:
|
||||||
|
|
||||||
|
../../../lladd/operations.h:
|
||||||
|
|
||||||
|
../../../lladd/constants.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/increment.h:
|
||||||
|
|
||||||
|
../../../lladd/bufferManager.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/decrement.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/set.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/prepare.h:
|
||||||
|
|
||||||
|
/usr/include/assert.h:
|
||||||
|
|
||||||
|
/usr/include/memory.h:
|
125
src/lladd/operations/.deps/prepare.Po
Normal file
125
src/lladd/operations/.deps/prepare.Po
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
prepare.o prepare.o: prepare.c ../../../lladd/operations/prepare.h \
|
||||||
|
../../../lladd/constants.h ../../../lladd/operations.h \
|
||||||
|
../../../lladd/common.h ../../../lladd/config.h /usr/include/stdio.h \
|
||||||
|
/usr/include/features.h /usr/include/sys/cdefs.h \
|
||||||
|
/usr/include/gnu/stubs.h \
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h \
|
||||||
|
/usr/include/bits/types.h /usr/include/bits/wordsize.h \
|
||||||
|
/usr/include/bits/typesizes.h /usr/include/libio.h \
|
||||||
|
/usr/include/_G_config.h /usr/include/wchar.h /usr/include/bits/wchar.h \
|
||||||
|
/usr/include/gconv.h /usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h \
|
||||||
|
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
|
||||||
|
/usr/include/bits/stdio.h /usr/include/sys/types.h /usr/include/time.h \
|
||||||
|
/usr/include/endian.h /usr/include/bits/endian.h \
|
||||||
|
/usr/include/sys/select.h /usr/include/bits/select.h \
|
||||||
|
/usr/include/bits/sigset.h /usr/include/bits/time.h \
|
||||||
|
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
|
||||||
|
/usr/include/bits/sched.h /usr/include/stdlib.h /usr/include/alloca.h \
|
||||||
|
/usr/include/string.h /usr/include/bits/string.h \
|
||||||
|
/usr/include/bits/string2.h /usr/include/unistd.h \
|
||||||
|
/usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
|
||||||
|
/usr/include/getopt.h ../../../lladd/page.h \
|
||||||
|
../../../lladd/operations/increment.h ../../../lladd/bufferManager.h \
|
||||||
|
../../../lladd/operations/decrement.h ../../../lladd/operations/set.h \
|
||||||
|
../../../lladd/operations/lladdhash.h ../../../lladd/transactional.h \
|
||||||
|
../logger/logstreamer.h
|
||||||
|
|
||||||
|
../../../lladd/operations/prepare.h:
|
||||||
|
|
||||||
|
../../../lladd/constants.h:
|
||||||
|
|
||||||
|
../../../lladd/operations.h:
|
||||||
|
|
||||||
|
../../../lladd/common.h:
|
||||||
|
|
||||||
|
../../../lladd/config.h:
|
||||||
|
|
||||||
|
/usr/include/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/features.h:
|
||||||
|
|
||||||
|
/usr/include/sys/cdefs.h:
|
||||||
|
|
||||||
|
/usr/include/gnu/stubs.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h:
|
||||||
|
|
||||||
|
/usr/include/bits/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wordsize.h:
|
||||||
|
|
||||||
|
/usr/include/bits/typesizes.h:
|
||||||
|
|
||||||
|
/usr/include/libio.h:
|
||||||
|
|
||||||
|
/usr/include/_G_config.h:
|
||||||
|
|
||||||
|
/usr/include/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/gconv.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio_lim.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sys_errlist.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/sys/types.h:
|
||||||
|
|
||||||
|
/usr/include/time.h:
|
||||||
|
|
||||||
|
/usr/include/endian.h:
|
||||||
|
|
||||||
|
/usr/include/bits/endian.h:
|
||||||
|
|
||||||
|
/usr/include/sys/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sigset.h:
|
||||||
|
|
||||||
|
/usr/include/bits/time.h:
|
||||||
|
|
||||||
|
/usr/include/sys/sysmacros.h:
|
||||||
|
|
||||||
|
/usr/include/bits/pthreadtypes.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sched.h:
|
||||||
|
|
||||||
|
/usr/include/stdlib.h:
|
||||||
|
|
||||||
|
/usr/include/alloca.h:
|
||||||
|
|
||||||
|
/usr/include/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string2.h:
|
||||||
|
|
||||||
|
/usr/include/unistd.h:
|
||||||
|
|
||||||
|
/usr/include/bits/posix_opt.h:
|
||||||
|
|
||||||
|
/usr/include/bits/confname.h:
|
||||||
|
|
||||||
|
/usr/include/getopt.h:
|
||||||
|
|
||||||
|
../../../lladd/page.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/increment.h:
|
||||||
|
|
||||||
|
../../../lladd/bufferManager.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/decrement.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/set.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/lladdhash.h:
|
||||||
|
|
||||||
|
../../../lladd/transactional.h:
|
||||||
|
|
||||||
|
../logger/logstreamer.h:
|
123
src/lladd/operations/.deps/set.Po
Normal file
123
src/lladd/operations/.deps/set.Po
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
set.o set.o: set.c ../../../lladd/operations/set.h \
|
||||||
|
../../../lladd/constants.h ../../../lladd/operations.h \
|
||||||
|
../../../lladd/common.h ../../../lladd/config.h /usr/include/stdio.h \
|
||||||
|
/usr/include/features.h /usr/include/sys/cdefs.h \
|
||||||
|
/usr/include/gnu/stubs.h \
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h \
|
||||||
|
/usr/include/bits/types.h /usr/include/bits/wordsize.h \
|
||||||
|
/usr/include/bits/typesizes.h /usr/include/libio.h \
|
||||||
|
/usr/include/_G_config.h /usr/include/wchar.h /usr/include/bits/wchar.h \
|
||||||
|
/usr/include/gconv.h /usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h \
|
||||||
|
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
|
||||||
|
/usr/include/bits/stdio.h /usr/include/sys/types.h /usr/include/time.h \
|
||||||
|
/usr/include/endian.h /usr/include/bits/endian.h \
|
||||||
|
/usr/include/sys/select.h /usr/include/bits/select.h \
|
||||||
|
/usr/include/bits/sigset.h /usr/include/bits/time.h \
|
||||||
|
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
|
||||||
|
/usr/include/bits/sched.h /usr/include/stdlib.h /usr/include/alloca.h \
|
||||||
|
/usr/include/string.h /usr/include/bits/string.h \
|
||||||
|
/usr/include/bits/string2.h /usr/include/unistd.h \
|
||||||
|
/usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
|
||||||
|
/usr/include/getopt.h ../../../lladd/page.h \
|
||||||
|
../../../lladd/operations/increment.h ../../../lladd/bufferManager.h \
|
||||||
|
../../../lladd/operations/decrement.h \
|
||||||
|
../../../lladd/operations/prepare.h \
|
||||||
|
../../../lladd/operations/lladdhash.h ../../../lladd/transactional.h
|
||||||
|
|
||||||
|
../../../lladd/operations/set.h:
|
||||||
|
|
||||||
|
../../../lladd/constants.h:
|
||||||
|
|
||||||
|
../../../lladd/operations.h:
|
||||||
|
|
||||||
|
../../../lladd/common.h:
|
||||||
|
|
||||||
|
../../../lladd/config.h:
|
||||||
|
|
||||||
|
/usr/include/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/features.h:
|
||||||
|
|
||||||
|
/usr/include/sys/cdefs.h:
|
||||||
|
|
||||||
|
/usr/include/gnu/stubs.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stddef.h:
|
||||||
|
|
||||||
|
/usr/include/bits/types.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wordsize.h:
|
||||||
|
|
||||||
|
/usr/include/bits/typesizes.h:
|
||||||
|
|
||||||
|
/usr/include/libio.h:
|
||||||
|
|
||||||
|
/usr/include/_G_config.h:
|
||||||
|
|
||||||
|
/usr/include/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/bits/wchar.h:
|
||||||
|
|
||||||
|
/usr/include/gconv.h:
|
||||||
|
|
||||||
|
/usr/lib/gcc-lib/i486-linux/3.3.3/include/stdarg.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio_lim.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sys_errlist.h:
|
||||||
|
|
||||||
|
/usr/include/bits/stdio.h:
|
||||||
|
|
||||||
|
/usr/include/sys/types.h:
|
||||||
|
|
||||||
|
/usr/include/time.h:
|
||||||
|
|
||||||
|
/usr/include/endian.h:
|
||||||
|
|
||||||
|
/usr/include/bits/endian.h:
|
||||||
|
|
||||||
|
/usr/include/sys/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/select.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sigset.h:
|
||||||
|
|
||||||
|
/usr/include/bits/time.h:
|
||||||
|
|
||||||
|
/usr/include/sys/sysmacros.h:
|
||||||
|
|
||||||
|
/usr/include/bits/pthreadtypes.h:
|
||||||
|
|
||||||
|
/usr/include/bits/sched.h:
|
||||||
|
|
||||||
|
/usr/include/stdlib.h:
|
||||||
|
|
||||||
|
/usr/include/alloca.h:
|
||||||
|
|
||||||
|
/usr/include/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string.h:
|
||||||
|
|
||||||
|
/usr/include/bits/string2.h:
|
||||||
|
|
||||||
|
/usr/include/unistd.h:
|
||||||
|
|
||||||
|
/usr/include/bits/posix_opt.h:
|
||||||
|
|
||||||
|
/usr/include/bits/confname.h:
|
||||||
|
|
||||||
|
/usr/include/getopt.h:
|
||||||
|
|
||||||
|
../../../lladd/page.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/increment.h:
|
||||||
|
|
||||||
|
../../../lladd/bufferManager.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/decrement.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/prepare.h:
|
||||||
|
|
||||||
|
../../../lladd/operations/lladdhash.h:
|
||||||
|
|
||||||
|
../../../lladd/transactional.h:
|
3
src/lladd/operations/Makefile.am-old
Normal file
3
src/lladd/operations/Makefile.am-old
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
lib_LIBRARIES=liboperations.a
|
||||||
|
liboperations_a_SOURCES=decrement.c increment.c lladdhash.c prepare.c set.c
|
||||||
|
AM_CFLAGS= -g -Wall -pedantic
|
69
src/lladd/operations/alloc.c
Normal file
69
src/lladd/operations/alloc.c
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#include <lladd/operations/alloc.h>
|
||||||
|
#include <lladd/page.h>
|
||||||
|
#include <lladd/bufferManager.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Implementation of Talloc() as an operation
|
||||||
|
|
||||||
|
This is a bit strange compared to other operations, as it happens
|
||||||
|
in two phases. The buffer manager reserves space for a record
|
||||||
|
before the log entry is allocated. Then, the recordid of this
|
||||||
|
space is written to the log. Finally, alloc tells bufferManager
|
||||||
|
that it will use the space.
|
||||||
|
|
||||||
|
@todo Currently, if the system crashes during an alloc, (before the
|
||||||
|
log is flushed, but after bufferManager returns a rid), then the
|
||||||
|
space alloced during the crash is leaked. This doesn't seem to be
|
||||||
|
too big of a deal, but it should be fixed someday.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int operate(int xid, recordid rid, const void * dat) {
|
||||||
|
Page loadedPage = loadPage(rid.page);
|
||||||
|
/** Has no effect during normal operation. */
|
||||||
|
pageSlotRalloc(loadedPage, rid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @todo Currently, we just lead store space on dealloc. */
|
||||||
|
static int deoperate(int xid, recordid rid, const void * dat) {
|
||||||
|
Page loadedPage = loadPage(rid.page);
|
||||||
|
/** Has no effect during normal operation. */
|
||||||
|
pageSlotRalloc(loadedPage, rid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operation getAlloc() {
|
||||||
|
Operation o = {
|
||||||
|
OPERATION_ALLOC, /* ID */
|
||||||
|
0,
|
||||||
|
OPERATION_DEALLOC,
|
||||||
|
&operate
|
||||||
|
};
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
recordid Talloc(int xid, size_t size) {
|
||||||
|
recordid rid;
|
||||||
|
|
||||||
|
rid = ralloc(xid, size);
|
||||||
|
|
||||||
|
Tupdate(xid,rid, NULL, OPERATION_ALLOC);
|
||||||
|
|
||||||
|
return rid;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Operation getDealloc() {
|
||||||
|
Operation o = {
|
||||||
|
OPERATION_DEALLOC,
|
||||||
|
0,
|
||||||
|
OPERATION_ALLOC,
|
||||||
|
&deoperate
|
||||||
|
};
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tdealloc(int xid, recordid rid) {
|
||||||
|
Tupdate(xid, rid, NULL, OPERATION_DEALLOC);
|
||||||
|
}
|
69
src/lladd/operations/decrement.c
Normal file
69
src/lladd/operations/decrement.c
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/**********************************************
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Decrements the given reference by one
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
#include <lladd/operations/decrement.h>
|
||||||
|
#include <lladd/bufferManager.h>
|
||||||
|
|
||||||
|
static int operate(int xid, recordid r, const void *d) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
readRecord(xid, r, &i);
|
||||||
|
i--;
|
||||||
|
writeRecord(xid, r, &i);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operation getDecrement() {
|
||||||
|
Operation o = {
|
||||||
|
OPERATION_DECREMENT, /* id */
|
||||||
|
0, /* sizeofData (this doesn't take any args) */
|
||||||
|
OPERATION_INCREMENT, /* we're not doing undo functions yet */
|
||||||
|
&operate /* Function */
|
||||||
|
};
|
||||||
|
return o;
|
||||||
|
}
|
68
src/lladd/operations/increment.c
Normal file
68
src/lladd/operations/increment.c
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*---
|
||||||
|
This software is copyrighted by the Regents of the University of
|
||||||
|
California, and other parties. The following terms apply to all files
|
||||||
|
associated with the software unless explicitly disclaimed in
|
||||||
|
individual files.
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose,
|
||||||
|
provided that existing copyright notices are retained in all copies
|
||||||
|
and that this notice is included verbatim in any distributions. No
|
||||||
|
written agreement, license, or royalty fee is required for any of the
|
||||||
|
authorized uses. Modifications to this software may be copyrighted by
|
||||||
|
their authors and need not follow the licensing terms described here,
|
||||||
|
provided that the new terms are clearly indicated on the first page of
|
||||||
|
each file where they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
|
||||||
|
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||||
|
U.S. government, the Government shall have only "Restricted Rights" in
|
||||||
|
the software and related documentation as defined in the Federal
|
||||||
|
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
|
||||||
|
acquiring the software on behalf of the Department of Defense, the
|
||||||
|
software shall be classified as "Commercial Computer Software" and the
|
||||||
|
Government shall have only "Restricted Rights" as defined in Clause
|
||||||
|
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||||
|
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.
|
||||||
|
---*/
|
||||||
|
/**********************************************
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Increments the given reference by one
|
||||||
|
**********************************************/
|
||||||
|
|
||||||
|
#include <lladd/operations/increment.h>
|
||||||
|
#include <lladd/bufferManager.h>
|
||||||
|
static int operate(int xid, recordid r, const void *d) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
readRecord(xid, r, &i);
|
||||||
|
i++;
|
||||||
|
writeRecord(xid, r, &i);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operation getIncrement() {
|
||||||
|
Operation o = {
|
||||||
|
OPERATION_INCREMENT, /* id */
|
||||||
|
0, /* sizeofData (this doesn't take any args) */
|
||||||
|
OPERATION_DECREMENT, /* we're not doing undo functions yet */
|
||||||
|
&operate /* Function */
|
||||||
|
};
|
||||||
|
return o;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue