Initial revision

This commit is contained in:
Sears Russell 2004-06-24 21:10:31 +00:00
commit d1f76f0b4a
323 changed files with 46021 additions and 0 deletions

4
AUTHORS Normal file
View 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
View 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
View file

9
Makefile.am Normal file
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,2 @@
autoscan: warning: missing AC_PROG_RANLIB wanted by:
ltmain.sh:6370

11
bootstrap Executable file
View 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
View 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
View 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
View 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
View 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
View file

160
libdfa/libdfa.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

288
lladd/bufferManager.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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

View 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

View 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

View 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
View 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
View 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
View 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
View file

1
lladd/stamp-h1 Normal file
View file

@ -0,0 +1 @@
timestamp for lladd/config.h

186
lladd/transactional.h Normal file
View 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
View 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
View 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
View file

176
pbl/jbhash.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1 @@
SUBDIRS = pbl lladd libdfa 2pc timing apps

1
src/apps/Makefile.am Normal file
View file

@ -0,0 +1 @@
SUBDIRS = cht #cyrus

5
src/apps/cht/Makefile.am Normal file
View 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
View 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
View 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);*/

View file

@ -0,0 +1 @@
# dummy

View file

@ -0,0 +1 @@
# dummy

371
src/apps/cyrus/Makefile Normal file
View 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:

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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:

View 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:

View 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:

View 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
View 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);
}
}

View 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 ;
}

View 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
View 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
View 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;
}

View 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;
}

View 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

View 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);
}

View 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
View 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); */
}

View 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:

View 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:

View 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:

View 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:

View 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:

View 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

View 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);
}

View 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;
}

View 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