You are viewing a plain text version of this content. The canonical link for it is here.
Posted to triplesoup-commits@incubator.apache.org by le...@apache.org on 2007/04/13 08:56:16 UTC
svn commit: r528394 [4/35] - in
/incubator/triplesoup/donations/TRIPLES-3-RDFStore: ./ dbms/ dbms/client/
dbms/client/t/ dbms/dbmsproxy/ dbms/deamon/ dbms/doc/ dbms/include/
dbms/libdbms/ dbms/utils/ doc/ include/ lib/ lib/DBD/ lib/RDFStore/
lib/RDFSto...
Added: incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_bdb_store.c
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_bdb_store.c?view=auto&rev=528394
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_bdb_store.c (added)
+++ incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_bdb_store.c Fri Apr 13 01:56:01 2007
@@ -0,0 +1,1272 @@
+/*
+##############################################################################
+# Copyright (c) 2000-2006 All rights reserved
+# Alberto Reggiori <ar...@webweaving.org>
+# Dirk-Willem van Gulik <di...@webweaving.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# 3. The end-user documentation included with the redistribution,
+# if any, must include the following acknowledgment:
+# "This product includes software developed by
+# Alberto Reggiori <ar...@webweaving.org> and
+# Dirk-Willem van Gulik <di...@webweaving.org>."
+# Alternately, this acknowledgment may appear in the software itself,
+# if and wherever such third-party acknowledgments normally appear.
+#
+# 4. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+#
+# 5. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# 6. Products derived from this software may not be called "RDFStore"
+# nor may "RDFStore" appear in their names without prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ====================================================================
+#
+# This software consists of work developed by Alberto Reggiori and
+# Dirk-Willem van Gulik. The RDF specific part is based based on public
+# domain software written at the Stanford University Database Group by
+# Sergey Melnik. For more information on the RDF API Draft work,
+# please see <http://www-db.stanford.edu/~melnik/rdf/api.html>
+# The DBMS TCP/IP server part is based on software originally written
+# by Dirk-Willem van Gulik for Web Weaving Internet Engineering m/v Enschede,
+# The Netherlands.
+#
+##############################################################################
+#
+# $Id: backend_bdb_store.c,v 1.21 2006/06/19 10:10:21 areggiori Exp $
+*/
+
+#include "dbms.h"
+#include "dbms_compat.h"
+#include "dbms_comms.h"
+
+#include "rdfstore_flat_store.h"
+#include "rdfstore_log.h"
+#include "rdfstore.h"
+
+#include "backend_store.h"
+
+#include "backend_bdb_store.h"
+#include "backend_bdb_store_private.h"
+
+#include <sys/stat.h>
+
+static char *mkpath(char *base, char *infile);
+
+/*
+ * Some default call back functions.
+ */
+static void
+default_myfree(void *adr)
+{
+ RDFSTORE_FREE(adr);
+}
+static void *
+default_mymalloc(size_t x)
+{
+ return RDFSTORE_MALLOC(x);
+}
+static void
+default_myerror(char *err, int erx)
+{
+ fprintf(stderr, "backend_bdb Error[%d]: %s\n", erx, err);
+}
+
+/* backend_bdb error management */
+static char _backend_bdb_erm[256] = "\0";
+
+/* human-readable error codes */
+static char *backend_bdb_error[] = {
+ /* FLAT_STORE_E_UNDEF 2000 */
+ "Not defined",
+ /* FLAT_STORE_E_NONNUL 2001 */
+ "Undefined Error",
+ /* FLAT_STORE_E_NOMEM 2002 */
+ "Out of memory",
+ /* FLAT_STORE_E_NOPE 2003 */
+ "No such database",
+ /* FLAT_STORE_E_KEYEMPTY 2004 */
+ "Key/data deleted or never created",
+ /* FLAT_STORE_E_KEYEXIST 2005 */
+ "The key/data pair already exists",
+ /* FLAT_STORE_E_NOTFOUND 2006 */
+ "Key/data pair not found",
+ /* FLAT_STORE_E_OLD_VERSION 2007 */
+ "Out-of-date version",
+ /* FLAT_STORE_E_DBMS 2008 */
+ "DBMS error",
+ /* FLAT_STORE_E_CANNOTOPEN 2009 */
+ "Cannot open database",
+ /* FLAT_STORE_E_BUG 2010 */
+ "Conceptual error"
+};
+
+void
+backend_bdb_set_error(void *eme, char *msg, rdfstore_flat_store_error_t erx)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ bzero(me->err, sizeof(me->err));
+ if (erx == FLAT_STORE_E_DBMS) {
+ snprintf(me->err, sizeof(me->err), "DBMS Error %s: %s\n", msg,
+ errno == 0 ? "" : (strlen(strerror(errno)) <= sizeof(me->err)) ? strerror(errno) : ""); /* not enough... */
+ } else {
+ if ((erx > FLAT_STORE_E_UNDEF) && (erx <= FLAT_STORE_E_BUG)) {
+ strcpy(me->err, backend_bdb_error[erx - FLAT_STORE_E_UNDEF]);
+ } else {
+ if (strlen(strerror(erx)) <= sizeof(me->err))
+ strcpy(me->err, strerror(erx));
+ };
+ };
+ if (strlen(me->err) <= sizeof(_backend_bdb_erm))
+ strcpy(_backend_bdb_erm, me->err);
+
+#ifdef VERBOSE
+ if (me->error)
+ (*(me->error)) (me->err, erx);
+#endif
+}
+
+
+char *
+backend_bdb_get_error(void *eme)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ if (me == NULL)
+ return _backend_bdb_erm;
+ else
+ return me->err;
+};
+
+/* clone a key or value for older BDB */
+DBT
+backend_bdb_kvdup(void *eme, DBT data)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ DBT dup;
+
+ memset(&dup, 0, sizeof(dup));
+
+ if (data.size == 0) {
+ dup.data = NULL;
+ return dup;
+ };
+
+ dup.size = data.size;
+
+ if ((dup.data = (char *) me->malloc(data.size + 1)) == NULL) {
+ perror("Out of memory");
+ exit(1);
+ };
+
+
+ memcpy(dup.data, data.data, data.size);
+ memcpy(dup.data + data.size, "\0", 1);
+
+ return dup;
+};
+
+void
+backend_bdb_reset_debuginfo(
+ void *eme
+)
+{
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ me->num_store = 0;
+ me->num_fetch = 0;
+ me->num_inc = 0;
+ me->num_dec = 0;
+ me->num_sync = 0;
+ me->num_next = 0;
+ me->num_from = 0;
+ me->num_first = 0;
+ me->num_delete = 0;
+ me->num_clear = 0;
+ me->num_exists = 0;
+#endif
+};
+
+#ifdef BERKELEY_DB_1_OR_2
+static int rdfstore_backend_bdb_compare_int(
+ const DBT *a,
+ const DBT *b );
+#else
+static int rdfstore_backend_bdb_compare_int(
+ DB *file,
+ const DBT *a,
+ const DBT *b );
+#endif
+
+#ifdef BERKELEY_DB_1_OR_2
+static int rdfstore_backend_bdb_compare_double(
+ const DBT *a,
+ const DBT *b );
+#else
+static int rdfstore_backend_bdb_compare_double(
+ DB *file,
+ const DBT *a,
+ const DBT *b );
+#endif
+
+/*
+ * NOTE: all the functions return 0 on success and non zero value if error
+ * (see above and include/backend_bdb.h for known error codes)
+ */
+rdfstore_flat_store_error_t
+backend_bdb_open(
+ int remote,
+ int ro,
+ void **emme,
+ char *dir,
+ char *name,
+ unsigned int local_hash_flags,
+ char *host,
+ int port,
+ void *(*_my_malloc) (size_t size),
+ void (*_my_free) (void *),
+ void (*_my_report) (dbms_cause_t cause, int count),
+ void (*_my_error) (char *err, int erx),
+ int bt_compare_fcn_type
+)
+{
+ backend_bdb_t **mme = (backend_bdb_t **) emme;
+ backend_bdb_t *me;
+ char *buff;
+ struct stat s;
+#if 0
+ HASHINFO priv = {
+ 16 * 1024, /* bsize; hash bucked size */
+ 8, /* ffactor, # keys/bucket */
+ 3000, /* nelements, guestimate */
+ 512 * 1024, /* cache size */
+ NULL, /* hash function */
+ 0 /* use current host order */
+ };
+#endif
+
+#ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
+#ifdef DB_VERSION_MAJOR
+ DB_INFO btreeinfo;
+ memset(&btreeinfo, 0, sizeof(btreeinfo));
+ btreeinfo.bt_compare = ( bt_compare_fcn_type == FLAT_STORE_BT_COMP_INT ) ? rdfstore_backend_bdb_compare_int : ( bt_compare_fcn_type == FLAT_STORE_BT_COMP_DOUBLE ) ? rdfstore_backend_bdb_compare_double : NULL ;
+#else
+ BTREEINFO btreeinfo;
+ memset(&btreeinfo, 0, sizeof(btreeinfo));
+ btreeinfo.compare = ( bt_compare_fcn_type == FLAT_STORE_BT_COMP_INT ) ? rdfstore_backend_bdb_compare_int : ( bt_compare_fcn_type == FLAT_STORE_BT_COMP_DOUBLE ) ? rdfstore_backend_bdb_compare_double : NULL ;
+#endif
+#endif
+
+ *mme = NULL;
+
+ if (_my_error == NULL)
+ _my_error = default_myerror;
+
+ if (_my_malloc == NULL)
+ _my_malloc = default_mymalloc;
+
+ if (_my_free == NULL)
+ _my_free = default_myfree;
+
+ me = (backend_bdb_t *) _my_malloc(sizeof(backend_bdb_t));
+ if (me == NULL) {
+ perror("backend_bdb_open");
+ return FLAT_STORE_E_NOMEM;
+ };
+
+ me->error = _my_error;
+ me->malloc = _my_malloc;
+ me->free = _my_free;
+
+ me->bt_compare_fcn_type = bt_compare_fcn_type;
+
+ bzero(me->err, sizeof(me->err));
+
+ if (_my_report != NULL)
+ me->callback = _my_report;
+
+ backend_bdb_reset_debuginfo(me);
+
+ if (remote) {
+ backend_bdb_set_error(me, "BDB backend does not do remote storage", FLAT_STORE_E_DBMS);
+ perror("backend_bdb_open");
+ _my_free(me);
+ return FLAT_STORE_E_CANNOTOPEN;
+ };
+
+ /* use local Berkeley DB either in-memory or physical files on disk */
+ if ((dir) &&
+ (name)) {
+ if(ro==1) { /* do not even try to go further if open read-only */
+ if ( (stat(dir, &s) != 0) ||
+ ((s.st_mode & S_IFDIR) == 0) ) {
+ backend_bdb_set_error(me, "Could not open database", FLAT_STORE_E_NOPE);
+ perror("backend_bdb_open");
+ fprintf(stderr, "Could not open database'%s'\n", dir);
+ _my_free(me);
+ return FLAT_STORE_E_CANNOTOPEN;
+ };
+ };
+ /* make path */
+ if (!(buff = mkpath(dir, name))) {
+ backend_bdb_set_error(me, "Could not create or open database", FLAT_STORE_E_NOPE);
+ perror("backend_bdb_open");
+ fprintf(stderr, "Could not create or open database'%s'\n", dir);
+ _my_free(me);
+ return FLAT_STORE_E_CANNOTOPEN;
+ };
+ strcpy(me->filename, buff);
+ umask(0);
+ } else {
+ strcpy(me->filename, "\0");
+ buff = NULL;
+ };
+
+ /* something strange with BDB - it gives 'Bus error' if DB file not there and open in DB_RDONLY - why seg fault? must be DB_ENV stuff... */
+ if( (buff!=NULL) &&
+ (ro==1) ) {
+ if ( (stat(buff, &s) != 0) ||
+ ((s.st_mode & S_IFREG) == 0) ) {
+ backend_bdb_set_error(me, "Could not open database", FLAT_STORE_E_NOPE);
+ perror("backend_bdb_open");
+ fprintf(stderr, "Could not open database '%s'\n", dir);
+ _my_free(me);
+ return FLAT_STORE_E_CANNOTOPEN;
+ };
+ };
+
+#ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
+
+#ifdef DB_VERSION_MAJOR
+ if ( (db_open( buff,
+ DB_BTREE, ((ro==0 || buff==NULL) ? ( DB_CREATE ) : ( DB_RDONLY ) ),
+ 0666, NULL, &btreeinfo, &me->bdb )) ||
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
+ ((me->bdb->cursor)(me->bdb, NULL, &me->cursor))
+#else
+ ((me->bdb->cursor)(me->bdb, NULL, &me->cursor, 0))
+#endif
+ ) {
+#else
+
+#if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
+ if (!(me->bdb = (DB *)__db185_open( buff,
+ ((ro==0 || buff==NULL) ? (O_RDWR | O_CREAT) : ( O_RDONLY ) ),
+ 0666, DB_BTREE, &btreeinfo ))) {
+#else
+ /* for unpatched db-1.85 when use in-memory DB_BTREE due to mkstemp() call in hash/hash_page.c open_temp()
+ i.e. HASHVERSION==2 we use DB_BTREE instead in CGI/mod_perl environments to avoid problems with errors
+ like 'Permission denied' due the Web server running in a different user under a different directory */
+
+#if DIRKX_DEBUG
+BTREEINFO openinfo = {
+ 0,
+ 32 * 1024 * 1024,
+ 0,
+ atoi(getenv("PSIZE")),
+ 64 * 1024,
+ NULL, NULL, 0
+};
+#endif
+ if (!(me->bdb = (DB *)dbopen( buff,
+ ((ro==0 || buff==NULL) ? (O_RDWR | O_CREAT) : ( O_RDONLY ) ),
+ 0666,
+#if HASHVERSION == 2
+ ( ( (buff==NULL) && (getenv("GATEWAY_INTERFACE") != NULL) ) ? DB_BTREE : DB_BTREE ),
+#else
+ DB_BTREE,
+#endif
+#if DIRKX_DEBUG
+ &openinfo))) {
+#else
+ &btreeinfo ))) {
+#endif
+
+#endif /* DB_LIBRARY_COMPATIBILITY_API */
+
+#endif
+
+#else /* Berkeley DB Version > 2 */
+ if (db_create(&me->bdb, NULL,0)) {
+ rdfstore_flat_store_set_error((void*)me,"Could not create environment",FLAT_STORE_E_CANNOTOPEN);
+ perror("rdfstore_flat_store_open");
+ fprintf(stderr,"Could not open/create '%s':\n",buff);
+ _my_free(me);
+ return FLAT_STORE_E_CANNOTOPEN;
+ };
+
+ /* set the b-tree comparinson function to the one passed */
+ if( bt_compare_fcn_type != 0 ) {
+ me->bdb->set_bt_compare(me->bdb, ( bt_compare_fcn_type == FLAT_STORE_BT_COMP_INT ) ?
+ rdfstore_backend_bdb_compare_int : ( bt_compare_fcn_type == FLAT_STORE_BT_COMP_DOUBLE ) ?
+ rdfstore_backend_bdb_compare_double : NULL );
+ };
+
+ me->bdb->set_errfile(me->bdb,stderr);
+ me->bdb->set_errpfx(me->bdb,"BerkelyDB");
+#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 3
+ me->bdb->set_malloc( me->bdb, me->malloc );
+#elif DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR >= 3
+ /* This interface appeared in 3.3 */
+ me->bdb->set_alloc( me->bdb, me->malloc, NULL, NULL ); /* could also pass me->free as 4th param but not sure how memoeyr is managed still */
+#endif
+
+#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR > 0 && DB_VERSION_PATCH >= 17
+ if ( (me->bdb->open( me->bdb,
+ NULL,
+ buff,
+ NULL,
+ DB_BTREE, ((ro==0 || buff==NULL) ? ( DB_CREATE ) : ( DB_RDONLY ) ),
+ 0666 )) ||
+#else
+ if ( (me->bdb->open( me->bdb,
+ buff,
+ NULL,
+ DB_BTREE, ((ro==0 || buff==NULL) ? ( DB_CREATE ) : ( DB_RDONLY ) ),
+ 0666 )) ||
+#endif
+ ((me->bdb->cursor)(me->bdb, NULL, &me->cursor, 0)) ) {
+#endif /* Berkeley DB Version > 2 */
+
+ rdfstore_flat_store_set_error((void*)me,"Could not open/create database",FLAT_STORE_E_CANNOTOPEN);
+ perror("rdfstore_flat_store_open");
+ fprintf(stderr,"Could not open/create '%s':\n",buff);
+ _my_free(me);
+ return FLAT_STORE_E_CANNOTOPEN;
+ };
+
+#ifndef BERKELEY_DB_1_OR_2 /* Berkeley DB Version > 2 */
+/*
+ (void)me->bdb->set_h_ffactor(me->bdb, 1024);
+ (void)me->bdb->set_h_nelem(me->bdb, (u_int32_t)6000);
+*/
+#endif
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr,"rdfstore_flat_store_open '%s'\n",me->filename);
+#endif
+
+ *mme = me;
+ return 0;
+}
+
+rdfstore_flat_store_error_t
+backend_bdb_close(
+ void *eme
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ void (*_my_free) (void *) = me->free;
+ int retval = 0;
+
+#ifdef DB_VERSION_MAJOR
+ me->cursor->c_close(me->cursor);
+ (me->bdb->close) (me->bdb, 0);
+#else
+ (me->bdb->close) (me->bdb);
+#endif
+ _my_free(me);
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_close '%s'\n", me->filename);
+#endif
+
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_bdb_fetch(
+ void * eme,
+ DBT key,
+ DBT * val
+)
+{
+ backend_bdb_t * me = (backend_bdb_t *) eme;
+ int retval = 0;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_fetch num=%d from '%s'\n", ++(me->num_fetch), me->filename);
+#endif
+
+#if DB_VERSION_MAJOR >= 2
+ memset(val, 0, sizeof(*val));
+ (*val).flags = DB_DBT_MALLOC;
+ retval = ((me->bdb)->get) (me->bdb, NULL, &key, val, 0);
+#else
+ retval = ((me->bdb)->get) (me->bdb, &key, val, 0);
+#endif
+
+ /* need to add proper client side BDB error management */
+ if (retval != 0) {
+#if DB_VERSION_MAJOR >= 2
+ if ((*val).data && (*val).size)
+ me->free((*val).data);
+#endif
+ memset(val, 0, sizeof(*val));
+ (*val).data = NULL;
+
+#ifdef DB_VERSION_MAJOR
+ if (retval == DB_NOTFOUND)
+#else
+ if (retval == 1)
+#endif
+ {
+ backend_bdb_set_error(me, "Could not fetch key/value", FLAT_STORE_E_NOTFOUND);
+ return FLAT_STORE_E_NOTFOUND;
+ } else {
+ backend_bdb_set_error(me, "Could not fetch key/value", FLAT_STORE_E_NOTFOUND);
+ perror("backend_bdb_fetch");
+ fprintf(stderr, "Could not fetch '%s': %s\n", me->filename, (char *) key.data);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+ } else {
+#if DB_VERSION_MAJOR < 2
+ /*
+ * Berkeley DB 1.85 don't malloc the data for the caller
+ * application duplicate the returned value to ensure
+ * reentrancy
+ */
+ (*val) = backend_bdb_kvdup(me, *val);
+#endif
+ return retval;
+ };
+}
+
+rdfstore_flat_store_error_t
+backend_bdb_fetch_compressed(
+ void * eme,
+ void (*func_decode)(unsigned int,unsigned char*, unsigned int *, unsigned char *),
+ DBT key,
+ unsigned int * outsize_p, unsigned char * outchar
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval = 0;
+ DBT val;
+ memset(&val,0,sizeof(val));
+
+ if ((retval = backend_bdb_fetch(eme,key,&val)))
+ return retval;
+
+ (*func_decode)(val.size,val.data,outsize_p,outchar);
+ (me->free)(val.data);
+
+ return retval;
+}
+
+rdfstore_flat_store_error_t
+backend_bdb_store(
+ void *eme,
+ DBT key,
+ DBT val
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval = 0;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_store num=%d in '%s'\n", ++(me->num_store), me->filename);
+#endif
+
+#ifdef DB_VERSION_MAJOR
+ retval = ((me->bdb)->put) (me->bdb, NULL, &key, &val, 0);
+#else
+ retval = ((me->bdb)->put) (me->bdb, &key, &val, 0);
+#endif
+ if (retval != 0) {
+#ifdef DB_VERSION_MAJOR
+ if (retval == DB_KEYEXIST)
+#else
+ if (retval == 1)
+#endif
+ {
+ backend_bdb_set_error(me, "Could not store key/value", FLAT_STORE_E_KEYEXIST);
+ return FLAT_STORE_E_KEYEXIST;
+ };
+
+ backend_bdb_set_error(me, "Could not store key/value", FLAT_STORE_E_NONNUL);
+ fprintf(stderr, "Could not store '%s': %s(%d) = %s(%d) E=%d\n", me->filename,
+ (char *) key.data, (int)key.size,
+ (char *) val.data, (int)val.size,
+ retval);
+ return FLAT_STORE_E_NONNUL;
+ }
+ return 0;
+}
+
+rdfstore_flat_store_error_t
+backend_bdb_store_compressed(
+ void * eme,
+ void (*func_encode)(unsigned int,unsigned char*, unsigned int *, unsigned char *),
+ DBT key,
+ unsigned int insize , unsigned char * inchar,
+ unsigned char * outbuff
+)
+{
+ unsigned int outsize;
+ DBT val;
+ memset(&val,0,sizeof(val));
+
+ (*func_encode)(insize, inchar, &outsize, outbuff);
+
+ val.data = outbuff;
+ val.size = outsize;
+
+ return backend_bdb_store(eme,key,val);
+}
+
+rdfstore_flat_store_error_t
+backend_bdb_exists(
+ void *eme,
+ DBT key
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval;
+ DBT val;
+ memset(&val,0,sizeof(val));
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_exists num=%d from '%s'\n", ++(me->num_exists), me->filename);
+#endif
+
+
+ memset(&val, 0, sizeof(val));
+
+ /*
+ * here we do not care about memory management due that we just want
+ * to know whether or not the given key exists
+ */
+
+#if DB_VERSION_MAJOR >= 2
+ retval = ((me->bdb)->get) (me->bdb, NULL, &key, &val, 0);
+#else
+ retval = ((me->bdb)->get) (me->bdb, &key, &val, 0);
+#endif
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_bdb_delete(
+ void *eme,
+ DBT key
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_delete num=%d from '%s'\n", ++(me->num_delete), me->filename);
+#endif
+
+#ifdef DB_VERSION_MAJOR
+ retval = ((me->bdb)->del) (me->bdb, NULL, &key, 0);
+ if( retval == DB_NOTFOUND )
+ return FLAT_STORE_E_NOTFOUND;
+#else
+ retval = ((me->bdb)->del) (me->bdb, &key, 0);
+ if ( retval == 1 )
+ return FLAT_STORE_E_NOTFOUND;
+#endif
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_bdb_clear(
+ void *eme
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ char *buff;
+
+#ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
+#ifdef DB_VERSION_MAJOR
+ DB_INFO btreeinfo;
+ memset(&btreeinfo, 0, sizeof(btreeinfo));
+ btreeinfo.bt_compare = ( me->bt_compare_fcn_type == FLAT_STORE_BT_COMP_INT ) ? rdfstore_backend_bdb_compare_int : ( me->bt_compare_fcn_type == FLAT_STORE_BT_COMP_DOUBLE ) ? rdfstore_backend_bdb_compare_double : NULL ;
+#else
+ BTREEINFO btreeinfo;
+ memset(&btreeinfo, 0, sizeof(btreeinfo));
+ btreeinfo.compare = ( me->bt_compare_fcn_type == FLAT_STORE_BT_COMP_INT ) ? rdfstore_backend_bdb_compare_int : ( me->bt_compare_fcn_type == FLAT_STORE_BT_COMP_DOUBLE ) ? rdfstore_backend_bdb_compare_double : NULL ;
+#endif
+#endif
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ me->num_store = 0;
+ me->num_fetch = 0;
+ me->num_inc = 0;
+ me->num_dec = 0;
+ me->num_sync = 0;
+ me->num_next = 0;
+ me->num_from = 0;
+ me->num_first = 0;
+ me->num_delete = 0;
+ me->num_exists = 0;
+ fprintf(stderr, "backend_bdb_clear num=%d in '%s'\n", ++(me->num_clear), me->filename);
+#endif
+
+
+ /* close the database, remove the file, and repoen... ? */
+ /* close */
+#ifdef DB_VERSION_MAJOR
+ me->cursor->c_close(me->cursor);
+ (me->bdb->close) (me->bdb, 0);
+#else
+ (me->bdb->close) (me->bdb);
+#endif
+
+ if (strcmp(me->filename, "\0") != 0) {
+ /* remove db file (not the directory!) */
+ if (unlink(me->filename)) {
+ perror("backend_bdb_clear");
+ fprintf(stderr, "Could not remove '%s' while clearing\n", me->filename);
+ return -1;
+ };
+ buff = me->filename;
+ umask(0);
+ } else {
+ buff = NULL;
+ };
+
+ /* re-open */
+
+#ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
+
+#ifdef DB_VERSION_MAJOR
+ if ((db_open(buff,
+ DB_BTREE, DB_CREATE,
+ 0666, NULL, &btreeinfo, &me->bdb)) ||
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
+ ((me->bdb->cursor) (me->bdb, NULL, &me->cursor))
+#else
+ ((me->bdb->cursor) (me->bdb, NULL, &me->cursor, 0))
+#endif
+ ) {
+#else
+
+#if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
+ if (!(me->bdb = (DB *) __db185_open(buff,
+ O_RDWR | O_CREAT,
+ 0666, DB_BTREE, &btreeinfo))) {
+#else
+ if (!(me->bdb = (DB *) dbopen(buff,
+ O_RDWR | O_CREAT,
+ 0666, DB_BTREE, &btreeinfo))) {
+#endif /* DB_LIBRARY_COMPATIBILITY_API */
+
+#endif
+
+#else /* Berkeley DB Version > 2 */
+ if (db_create(&me->bdb, NULL, 0)) {
+ backend_bdb_set_error(me, "Could not open/create database", FLAT_STORE_E_CANNOTOPEN);
+ perror("backend_bdb_open");
+ fprintf(stderr, "Could not open/create '%s':\n", buff);
+ return FLAT_STORE_E_CANNOTOPEN;
+ };
+
+ /* set the b-tree comparinson function to the one passed */
+ if( me->bt_compare_fcn_type != 0 ) {
+ me->bdb->set_bt_compare(me->bdb, ( me->bt_compare_fcn_type == FLAT_STORE_BT_COMP_INT ) ?
+ rdfstore_backend_bdb_compare_int : ( me->bt_compare_fcn_type == FLAT_STORE_BT_COMP_DOUBLE ) ?
+ rdfstore_backend_bdb_compare_double : NULL );
+ };
+
+ me->bdb->set_errfile(me->bdb,stderr);
+ me->bdb->set_errpfx(me->bdb,"BerkelyDB");
+#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 3
+ me->bdb->set_malloc(me->bdb, me->malloc);
+#elif DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR >= 3
+ /* This interface appeared in 3.3 */
+ me->bdb->set_alloc(me->bdb, me->malloc, NULL, NULL); /* could also pass
+ * me->free as 4th param
+ * but not sure how
+ * memoeyr is managed
+ * still */
+#endif
+
+#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR > 0 && DB_VERSION_PATCH >= 17
+ if ((me->bdb->open(me->bdb,
+ NULL,
+ buff,
+ NULL,
+ DB_BTREE, DB_CREATE,
+ 0666)) ||
+#else
+ if ((me->bdb->open(me->bdb,
+ buff,
+ NULL,
+ DB_BTREE, DB_CREATE,
+ 0666)) ||
+#endif
+ ((me->bdb->cursor) (me->bdb, NULL, &me->cursor, 0))) {
+#endif /* Berkeley DB Version > 2 */
+
+ perror("backend_bdb_clear");
+ fprintf(stderr, "Could not open/create '%s' while clearing\n", buff);
+ return -1;
+ };
+ return 0;
+};
+
+rdfstore_flat_store_error_t
+backend_bdb_from(
+ void *eme,
+ DBT closest_key,
+ DBT * key
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval;
+ DBT val;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_from num=%d from '%s'\n", ++(me->num_from), me->filename);
+#endif
+
+ memset(&val, 0, sizeof(val));
+
+ /* seek to closest_key and discard val */
+ memcpy(key, &closest_key, sizeof(closest_key));
+
+#if DB_VERSION_MAJOR >= 2
+ retval = (me->cursor->c_get) (me->cursor, key, &val, DB_SET_RANGE);
+#else
+ retval = (me->bdb->seq) (me->bdb, key, &val, R_CURSOR);
+#endif
+
+ if (retval == 0) {
+ /*
+ * to ensure reentrancy we do a copy into caller space of what BDB layer returns
+ */
+ (*key) = backend_bdb_kvdup(me, *key);
+ };
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_bdb_first(
+ void *eme,
+ DBT * first_key
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval;
+ DBT val;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_first num=%d from '%s'\n", ++(me->num_first), me->filename);
+#endif
+
+ memset(first_key, 0, sizeof(*first_key));
+ memset(&val, 0, sizeof(val));
+
+#if DB_VERSION_MAJOR >= 2
+ retval = (me->cursor->c_get) (me->cursor, first_key, &val, DB_FIRST);
+#else
+ retval = (me->bdb->seq) (me->bdb, first_key, &val, R_FIRST);
+#endif
+
+ if (retval == 0) {
+ /*
+ * to ensure reentrancy we do a copy into caller space of what BDB layer returns
+ */
+ (*first_key) = backend_bdb_kvdup(me, *first_key);
+ };
+
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_bdb_next(
+ void *eme,
+ DBT previous_key,
+ DBT * next_key
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval;
+ DBT val;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_next num=%d from '%s'\n", ++(me->num_next), me->filename);
+#endif
+
+ memset(next_key, 0, sizeof(*next_key));
+ memset(&val, 0, sizeof(val));
+
+ /* we really do not use/consider previous_key to carry out next_key - val is discarded */
+
+#if DB_VERSION_MAJOR >= 2
+ retval = (me->cursor->c_get) (me->cursor, next_key, &val, DB_NEXT);
+#else
+ retval = (me->bdb->seq) (me->bdb, next_key, &val, R_NEXT);
+#endif
+
+ if (retval == 0) {
+ /*
+ * to ensure reentrancy we do a copy into caller space of what BDB layer returns
+ */
+ (*next_key) = backend_bdb_kvdup(me, *next_key);
+ };
+
+ return retval;
+};
+
+/* packed rdf_store_counter_t increment */
+rdfstore_flat_store_error_t
+backend_bdb_inc(
+ void *eme,
+ DBT key,
+ DBT * new_value
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval;
+ rdf_store_counter_t l = 0;
+ unsigned char outbuf[256];
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_inc num=%d in '%s'\n", ++(me->num_inc), me->filename);
+#endif
+
+
+ /* it should be atomic with locking here... */
+#if DB_VERSION_MAJOR >= 2
+ memset(new_value, 0, sizeof(*new_value));
+ (*new_value).flags = DB_DBT_MALLOC;
+ if ((((me->bdb)->get) (me->bdb, NULL, &key, new_value, 0)) != 0) {
+ return -1;
+ };
+#else
+ if ((((me->bdb)->get) (me->bdb, &key, new_value, 0)) != 0) {
+ return -1;
+ };
+#endif
+ unpackInt(new_value->data, &l);
+ l++;
+#if DB_VERSION_MAJOR >= 2
+ if ((*new_value).data && (*new_value).size)
+ me->free((*new_value).data);
+#endif
+ (*new_value).data = outbuf;
+ (*new_value).size = sizeof(rdf_store_counter_t);
+ packInt(l, new_value->data);
+
+#ifdef DB_VERSION_MAJOR
+ retval = ((me->bdb)->put) (me->bdb, NULL, &key, new_value, 0);
+#else
+ retval = ((me->bdb)->put) (me->bdb, &key, new_value, 0);
+#endif
+
+ if (retval != 0) {
+ memset(new_value, 0, sizeof(*new_value));
+ (*new_value).data = NULL;
+ } else {
+ (*new_value) = backend_bdb_kvdup(me, *new_value);
+ };
+ return retval;
+};
+
+/* packed rdf_store_counter_t decrement */
+rdfstore_flat_store_error_t
+backend_bdb_dec(
+ void *eme,
+ DBT key,
+ DBT * new_value
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval;
+ rdf_store_counter_t l = 0;
+ unsigned char outbuf[256];
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_dec num=%d from '%s'\n", ++(me->num_dec), me->filename);
+#endif
+
+
+ /* it should be atomic with locking here... */
+#if DB_VERSION_MAJOR >= 2
+ memset(new_value, 0, sizeof(*new_value));
+ (*new_value).flags = DB_DBT_MALLOC;
+ if ((((me->bdb)->get) (me->bdb, NULL, &key, new_value, 0)) != 0) {
+ return -1;
+ };
+#else
+ if ((((me->bdb)->get) (me->bdb, &key, new_value, 0)) != 0) {
+ return -1;
+ };
+#endif
+ unpackInt(new_value->data, &l);
+ assert(l > 0);
+ l--;
+#if DB_VERSION_MAJOR >= 2
+ if ((*new_value).data && (*new_value).size)
+ me->free((*new_value).data);
+#endif
+ (*new_value).data = outbuf;
+ (*new_value).size = sizeof(rdf_store_counter_t);
+ packInt(l, new_value->data);
+
+#ifdef DB_VERSION_MAJOR
+ retval = ((me->bdb)->put) (me->bdb, NULL, &key, new_value, 0);
+#else
+ retval = ((me->bdb)->put) (me->bdb, &key, new_value, 0);
+#endif
+
+ if (retval != 0) {
+ memset(new_value, 0, sizeof(*new_value));
+ (*new_value).data = NULL;
+ } else {
+ (*new_value) = backend_bdb_kvdup(me, *new_value);
+ };
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_bdb_sync(
+ void *eme
+)
+{
+ backend_bdb_t *me = (backend_bdb_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_bdb_sync num=%d in '%s'\n", ++(me->num_sync), me->filename);
+#endif
+
+ retval = (me->bdb->sync) (me->bdb, 0);
+#ifdef DB_VERSION_MAJOR
+ if (retval > 0)
+ retval = -1;
+#endif
+ return retval;
+}
+
+int
+backend_bdb_isremote(
+ void *eme
+)
+{
+ return 0;
+}
+
+/* misc subroutines */
+
+/*
+ * The following compare function are used for btree(s) for basic
+ * XML-Schema data types xsd:integer, xsd:double (and will xsd:date)
+ *
+ * They return:
+ * < 0 if a < b
+ * = 0 if a = b
+ * > 0 if a > b
+ */
+#ifdef BERKELEY_DB_1_OR_2
+static int rdfstore_backend_bdb_compare_int(
+ const DBT *a,
+ const DBT *b ) {
+#else
+static int rdfstore_backend_bdb_compare_int(
+ DB *file,
+ const DBT *a,
+ const DBT *b ) {
+#endif
+ long ai, bi;
+
+ memcpy(&ai, a->data, sizeof(long));
+ memcpy(&bi, b->data, sizeof(long));
+
+ return (ai - bi);
+ };
+
+#ifdef BERKELEY_DB_1_OR_2
+static int rdfstore_backend_bdb_compare_double(
+ const DBT *a,
+ const DBT *b ) {
+#else
+static int rdfstore_backend_bdb_compare_double(
+ DB *file,
+ const DBT *a,
+ const DBT *b ) {
+#endif
+ double ad,bd;
+
+ memcpy(&ad, a->data, sizeof(double));
+ memcpy(&bd, b->data, sizeof(double));
+
+ if ( ad < bd ) {
+ return -1;
+ } else if ( ad > bd) {
+ return 1;
+ };
+
+ return 0;
+ };
+
+/*
+ * returns null and/or full path to a hashed directory tree. the final
+ * filename is hashed out within that three. Way to complex by now. Lifted
+ * from another project which needed more.
+ */
+static char *
+mkpath(char *base, char *infile)
+{
+ char *file;
+ int i, j;
+ int last;
+ struct stat s;
+ char *slash, *dirname;
+ char *inpath;
+ static char tmp[MAXPATHLEN];
+ char tmp2[MAXPATHLEN];
+#define MAXHASH 2
+ static char hash[MAXHASH + 1];
+
+ tmp[0] = '\0';
+
+ strcpy(inpath = tmp2, infile);
+
+ memset(hash, '_', MAXHASH);
+ hash[MAXHASH] = '\0';
+
+ if (base == NULL)
+ base = "./";
+
+ if (inpath == NULL || inpath[0] == '\0') {
+ fprintf(stderr, "No filename or path for the database specified\n");
+ return NULL;
+ };
+
+ /*
+ * remove our standard docroot if present so we can work with
+ * something relative. really a legacy thing from older perl DBMS.pm
+ * versions. Can go now.
+ */
+ if (!(strncmp(base, inpath, strlen(base))))
+ inpath += strlen(base);
+
+ /*
+ * fetch the last leaf name
+ */
+ if ((file = strrchr(inpath, '/')) != NULL) {
+ *file = '\0';
+ file++;
+ } else {
+ file = inpath;
+ inpath = "/";
+ };
+
+ if (!strlen(file)) {
+ fprintf(stderr, "No filename for the database specified\n");
+ return NULL;
+ };
+
+ strncpy(hash, file, MIN(strlen(file), MAXHASH));
+
+ /*
+ strcpy(tmp,"./");
+ */
+ strcat(tmp, base);
+ strcat(tmp, "/");
+ strcat(tmp, inpath);
+ strcat(tmp, "/");
+ strcat(tmp, hash);
+ strcat(tmp, "/");
+ strcat(tmp, file);
+
+ if ((slash = strrchr(tmp, '.')) != NULL) {
+ if ((!strcasecmp(slash + 1, "db")) ||
+ (!strcasecmp(slash + 1, "dbm")) ||
+ (!strcasecmp(slash + 1, "gdb"))
+ )
+ *slash = '\0';
+ };
+
+ strcat(tmp, ".db");
+
+ for (i = 0, j = 0; tmp[i]; i++) {
+ if (i && tmp[i] == '/' && tmp[i - 1] == '/')
+ continue;
+ if (i != j)
+ tmp[j] = tmp[i];
+ j++;
+ };
+ tmp[j] = '\0';
+
+ dirname = tmp;
+
+ /* Skip leading './'. */
+ if (dirname[0] == '.')
+ ++dirname;
+ if (dirname[0] == '/')
+ ++dirname;
+
+ for (last = 0; !last; ++dirname) {
+ if (dirname[0] == '\0')
+ break;
+ else if (dirname[0] != '/')
+ continue;
+ *dirname = '\0';
+ if (dirname[1] == '\0')
+ last = 1;
+
+ /*
+ * check if tmp exists and is a directory (or a link to one..
+ * if not, create it, else give an error
+ */
+ if (stat(tmp, &s) == 0) {
+ /*
+ * something exists.. it must be a directory
+ */
+ if ((s.st_mode & S_IFDIR) == 0) {
+ fprintf(stderr, "Creation of %s failed; path element not directory\n", tmp);
+ return NULL;
+ };
+ } else if (errno == ENOENT) {
+ if ((mkdir(tmp, (S_IRWXU | S_IRWXG | S_IRWXO))) != 0) {
+ fprintf(stderr, "Creation of %s failed; %s\n", tmp, strerror(errno));
+ return NULL;
+ };
+ } else {
+ fprintf(stderr, "Path creation to failed at %s:%s\n", tmp, strerror(errno));
+ return NULL;
+ };
+ if (!last)
+ *dirname = '/';
+ }
+
+ return tmp;
+}
+
+#define BDB_VERSION (100)
+DECLARE_MODULE_BACKEND(backend_bdb, "BerkelyDB", BDB_VERSION)
Added: incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_caching_store.c
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_caching_store.c?view=auto&rev=528394
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_caching_store.c (added)
+++ incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_caching_store.c Fri Apr 13 01:56:01 2007
@@ -0,0 +1,1055 @@
+/*
+##############################################################################
+# Copyright (c) 2000-2006 All rights reserved
+# Alberto Reggiori <ar...@webweaving.org>
+# Dirk-Willem van Gulik <di...@webweaving.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# 3. The end-user documentation included with the redistribution,
+# if any, must include the following acknowledgment:
+# "This product includes software developed by
+# Alberto Reggiori <ar...@webweaving.org> and
+# Dirk-Willem van Gulik <di...@webweaving.org>."
+# Alternately, this acknowledgment may appear in the software itself,
+# if and wherever such third-party acknowledgments normally appear.
+#
+# 4. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+#
+# 5. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# 6. Products derived from this software may not be called "RDFStore"
+# nor may "RDFStore" appear in their names without prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ====================================================================
+#
+# This software consists of work developed by Alberto Reggiori and
+# Dirk-Willem van Gulik. The RDF specific part is based based on public
+# domain software written at the Stanford University Database Group by
+# Sergey Melnik. For more information on the RDF API Draft work,
+# please see <http://www-db.stanford.edu/~melnik/rdf/api.html>
+# The DBMS TCP/IP server part is based on software originally written
+# by Dirk-Willem van Gulik for Web Weaving Internet Engineering m/v Enschede,
+# The Netherlands.
+#
+##############################################################################
+#
+# $Id: backend_caching_store.c,v 1.13 2006/06/19 10:10:21 areggiori Exp $
+*/
+#include "dbms.h"
+#include "dbms_compat.h"
+#include "dbms_comms.h"
+
+#include "rdfstore_flat_store.h"
+#include "rdfstore_log.h"
+#include "rdfstore.h"
+
+#include "backend_store.h"
+#include "backend_caching_store.h"
+
+#include "backend_bdb_store.h"
+#include "backend_dbms_store.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+typedef struct backend_caching_struct {
+ char * name; /* name - for debugging */
+ backend_store_t * store; /* the real store */
+ void * instance; /* instance of the real store */
+ struct caching_store_rec * cache; /* My cache */
+
+ void (* free)(void * adr);
+ void * (* malloc)(size_t size);
+ } backend_caching_t;
+
+typedef enum { UNDEF, EXISTS, CHANGED, NOTFOUND, DELETED } cstate;
+
+/* as refered to above as * data */
+typedef struct data_rec { /* Payload of the cache */
+ DBT key,val;
+ cstate state; /* Cache positives and negatives */
+} data_t;
+
+/* forward declarations */
+static int _dup(void * conf, void * from, void * * to);
+static int _store(void * conf, void * data);
+static int _delete(void * conf, void * data);
+static int _fetch(void * conf, void * data, void ** dout);
+static int _cmp(const void *a, const void *b);
+
+
+/* Caching infrastructure:
+ *
+ * Up to maxcache keys are cached.
+ *
+ * --> head->*cdll_t
+ * circular double linked list - element pointed to by head
+ * was the most recently used.
+ * --> idx
+ * sorted list circular double linked list elements - sorted
+ * by their 'data's key.
+ */
+
+/* START of Fairly generic caching section.. */
+
+#ifndef DEFAULTMAXCACHE
+#define DEFAULTMAXCACHE (1000)
+#endif
+
+/* Element in a circular double linked list */
+typedef struct cdll_rec {
+ void * data; /* data payload -- actual stuff we cache */
+
+ unsigned int cnt; /* counter - for debugging */
+
+ struct cdll_rec * prev;
+ struct cdll_rec * nxt;
+} cdll_t;
+
+typedef struct caching_store_rec {
+ char * name; /* name - for debugging */
+ void * conf; /* Callee's own book keeping */
+
+ int hit,miss,drop;
+
+ unsigned int maxcache; /* Max numer of keys to cache. */
+ unsigned int cached; /* Currently cached */
+ cdll_t * * idx; /* Sorted list (on keys) */
+
+ struct cdll_rec * head; /* Start of the circular double linked list. */
+
+ void (* free)(void * adr);
+ void * (* malloc)(size_t size);
+
+ /* Comparison functions specific to the data
+ */
+ int (*cmp)(const void * a, const void * b);
+
+ /* fetch/store functions specific to the data
+ */
+ int (*fetch)(void * conf, void * data, void ** out); /* implies dup into new out */
+ int (*store)(void * conf, void * data);
+ int (*delete)(void * conf, void * data);
+
+ /* Create a copy into existence, or drop it. */
+ int (*dup)(void * conf, void * from, void * * to); /* malloc and cpy */
+ int (*cpy)(void * conf, void * from, void * to); /* just copy refs */
+ int (*drp)(backend_caching_t * me, void * conf, void * data);
+
+ } caching_store_t;
+
+typedef enum { BC_READ, BC_WRITE, BC_EXISTS, BC_DELETE } bc_ops;
+
+static int cmp_pair(const void * a, const void * b);
+static int cmp_key(const void * in, const void * pair);
+
+static int init_cachingstore(
+ caching_store_t *me,
+ int max_cache_nelems,
+ void * conf,
+ char * name,
+ int (*cmp)(const void * a, const void * b),
+ int (*fetch)(void * conf, void * data, void ** out),
+ int (*store)(void * conf, void * data),
+ int (*delete)(void * conf, void * data),
+ int (*dup)(void * conf, void * from, void * * to),
+ int (*cpy)(void * conf, void * from, void * to),
+ int (*drp)(backend_caching_t * me, void * conf, void * data),
+ void (* cachingfree)(void * adr),
+ void * (* cachingmalloc)(size_t size)
+ )
+{
+ me->maxcache = max_cache_nelems ? max_cache_nelems : DEFAULTMAXCACHE;
+
+ me->idx = (cdll_t **) (*cachingmalloc)( sizeof((*(me->idx))) * me->maxcache );
+ if (me->idx == NULL)
+ return -1;
+
+ memset(me->idx, 0, sizeof((*(me->idx))) * me->maxcache );
+
+ me->cached = 0;
+ me->head = NULL;
+
+ me->hit = me->miss = me->drop = 0;
+
+ me->cmp = cmp;
+ me->fetch = fetch;
+ me->store = store;
+ me->delete = delete;
+ me->dup = dup;
+ me->cpy = cpy;
+ me->drp = drp;
+ me->name = (char *)(*cachingmalloc)( strlen(name)+1 );
+ if( me->name == NULL )
+ return -1;
+ strcpy( me->name, name );
+ me->conf = conf;
+
+ me->free = cachingfree;
+ me->malloc = cachingmalloc;
+
+ return 0;
+}
+
+/* iswrite == 1
+ * cache key+val
+ * iswrite == 0
+ * if cached - update val
+ * otherwise fetch from backend
+ * and cache - update val
+ */
+
+const char * _x(DBT v) {
+ int i;
+ if (v.size == 4) return "<int>";
+ for(i=0;i<v.size;i++)
+ if ((((char *)(v.data))[i]) && (((((char *)(v.data))[i])< 32) || ( ((((char *)(v.data))[i])>126))))
+ return "<bin>";
+ return (char *)(v.data);
+}
+
+int cachekey(backend_caching_t * mme, caching_store_t * me, void * data, void ** out, bc_ops op)
+{
+ cdll_t * * i = NULL;
+ int e = 0;
+
+#if 0
+if(0)fprintf(stderr,"Working on %s[%d,%d]\n",_x(((data_t *)data)->key),((data_t *)data)->key.size,((data_t *)data)->val.size);
+#endif
+ /* Check if this key is already cached */
+ if (me->cached > 0)
+ i = (cdll_t **)bsearch( (void *) data, me->idx, me->cached, sizeof(cdll_t *), &cmp_key);
+#if 0
+if (0) { int i; fprintf(stderr," PRE --- %d\n",me->cached); for(i=0;i < me->cached;i++) { data_t * p = (data_t *)(me->idx[i]->data); fprintf(stderr," # %d %p %p '%s'[%d] %d\n",i,me->idx[i],p,p->key.data,p->key.size,p->state); }; fprintf(stderr,"--- end\n"); };
+#endif
+
+ /* Add this to the cache if it is a new key */
+ if (!i) {
+ /* Remove last key if cache is already full. */
+#if 0
+fprintf(stderr,"Cache miss\n");
+#endif
+ me->miss++;
+ if (me->cached >= me->maxcache) {
+ /* Remove from the tail */
+ cdll_t * last = me->head->prev;
+ me->head = last->nxt;
+ me->head->prev = last->prev;
+ me->head->prev->nxt = me->head;
+
+ /* find the corresponding entry in the idx - as this is the slot which we will
+ * reuse (to save a malloc) for the new key.
+ */
+ i = (cdll_t **)bsearch((void *)(last->data), me->idx, me->cached, sizeof(cdll_t *), &cmp_key);
+ assert(i);
+
+ /* allow the backend to store and drop it */
+ me->store(me->conf,last->data);
+ me->drp(mme, me->conf,last->data);
+ me->drop++;
+ } else {
+ /* Still space - add it to the end of the IDX */
+ if ((me->idx[ me->cached ] = me->malloc(sizeof(cdll_t))) == NULL) {
+ return -1;
+ };
+ i = &(me->idx[ me->cached ]);
+ me->cached ++;
+ };
+
+ switch(op) {
+ case BC_WRITE: /* DUP our new item into it */
+ me->dup(me->conf, data, &((*i)->data));
+ break;
+ case BC_DELETE:
+ me->dup(me->conf, data, &((*i)->data));
+ e = me->delete(me->conf, (*i)->data);
+ break;
+ case BC_READ:
+ case BC_EXISTS:
+ e = me->fetch(me->conf, data, &((*i)->data));
+ break;
+ default:
+ assert(0);
+ break;
+ };
+
+ /* virig item. */
+ (*i)->cnt = 0;
+
+ /* And insert our item at the head */
+ if( me->head ) {
+ (*i)->nxt = me->head;
+ (*i)->prev = me->head->prev;
+ me->head->prev->nxt = *i;
+ me->head->prev = *i;
+ } else {
+ (*i)->nxt = *i;
+ (*i)->prev= *i;
+ }
+ /* And update the head pointer */
+ me->head = *i;
+
+ /* and sort the list again -- XXXX note this should be replaced
+ * by a binary search and a N-shift/insert (ordered insertion search)
+ * at some point.
+ */
+ if (me->cached > 1)
+ qsort(me->idx,me->cached,sizeof(cdll_t*),&cmp_pair);
+ } else {
+#if 0
+fprintf(stderr,"Cache hit\n");
+#endif
+ me->hit++;
+ /* if not already in front - move to the front
+ */
+ if (me->head && (me->head != *i)) {
+ /* remove item from the list */
+ (*i)->nxt->prev = (*i)->prev;
+ (*i)->prev->nxt = (*i)->nxt;
+
+ /* squeeze it in at head */
+ (*i)->nxt = me->head;
+ (*i)->prev = me->head->prev;
+ me->head->prev->nxt = *i;
+ me->head->prev = *i;
+
+ /* move head to the right place */
+ me->head = *i;
+ }
+ /* If it is a write through - update the value if it has changed.
+ */
+ switch(op) {
+ case BC_WRITE:
+if (0) fprintf(stderr,"Write through\n");
+if (0) if (((data_t *)data)->val.size == 4) fprintf(stderr,"%s == %d\n",_x(((data_t *)data)->key),*((int *)(((data_t *)data)->val.data)));
+
+ me->drp(mme, me->conf, (*i)->data); /* drop the old value */
+ me->dup(me->conf, data, &((*i)->data)); /* replace by the new one */
+ break;
+ case BC_DELETE:
+ me->dup(me->conf, data, &((*i)->data));
+ e = me->delete(me->conf, (*i)->data);
+ break;
+ case BC_EXISTS:
+ case BC_READ:
+ break;
+ default:
+ assert(0);
+ }
+ (*i)->cnt ++;
+ }
+
+ switch(op) {
+ case BC_EXISTS: /* exists */
+ me->cpy(me->conf,me->head->data,data);
+ break;
+ case BC_DELETE: /* no need to update */
+ case BC_WRITE: /* no need to update */
+ break;
+ case BC_READ: /* update data - so the callee can use it */
+ me->dup(me->conf,me->head->data,out);
+ break;
+ default:
+ /* error really */
+ assert(0);
+ break;
+ }
+#if 0
+if (0) { int i; fprintf(stderr,"POST --- %d\n",me->cached); for(i=0;i < me->cached;i++) { data_t * p = (data_t *)(me->idx[i]->data); fprintf(stderr," %d '%s'[%d] %d\n",i,p->key.data,p->key.size,p->state); }; fprintf(stderr,"--- end\n"); };
+#endif
+ return e;
+}
+
+void stats(caching_store_t *me)
+{
+ fprintf(stderr,"%s: hit: %d miss: %d drop: %d\n",me->name,me->hit,me->miss,me->drop);
+}
+
+void purgecache(backend_caching_t *me, caching_store_t *c)
+{
+ cdll_t * p;
+ if (c->head == NULL)
+ return;
+
+ for(p=c->head;;) {
+ cdll_t * q = p;
+ p=p->nxt;
+ c->store(c->conf,q->data);
+ c->drp(me, c->conf,q->data);
+ (*(me->free))(q);
+ if (p == c->head)
+ break;
+ }
+ c->head = NULL;
+ c->cached = 0;
+}
+
+static int cmp_pair(const void * a, const void * b)
+{
+ return _cmp((*(cdll_t**) a)->data,(*(cdll_t**) b)->data);
+}
+
+static int cmp_key(const void * in, const void * pair)
+{
+ return _cmp(in, (*((cdll_t**) pair))->data );
+}
+/* END of caching code */
+
+static int _cmp(const void *a, const void *b)
+{
+ DBT * k = &(((data_t *)a)->key);
+ DBT * l = &(((data_t *)b)->key);
+
+ int c;
+
+ if ((a == NULL) || (b == NULL)) {
+ if (a == NULL)
+ return (b == NULL) ? 0 : -1;
+ else
+ return (b == NULL) ? 0 : +1;
+ };
+
+ c = memcmp(k->data,l->data,MIN(k->size,l->size));
+
+ if (c)
+ return c;
+
+ if (k->size < l->size)
+ return -1;
+
+ if (k->size > l->size)
+ return +1;
+
+ return 0;
+}
+
+static int _fetch(void * conf, void * data, void ** dout)
+{
+ backend_caching_t *me = (backend_caching_t *) conf;
+ data_t * in = (data_t *) data;
+ data_t ** out = (data_t **) dout;
+ int e;
+
+ if (_dup(conf, (void *)in, (void **)out))
+ return -1;
+
+ e = (me->store->fetch)(me->instance,in->key,&((*out)->val));
+
+ /* Cache both positives and negatives. */
+ switch(e) {
+ case 0: /* found - no error */
+ (*out)->state = EXISTS;
+ break;
+ case FLAT_STORE_E_NOTFOUND: /* not found - but not an error */
+ (*out)->state = NOTFOUND;
+ e = 0;
+ break;
+ default:
+ /* keep error code */
+ fprintf(stderr,"DEBUG -- error %d\n",e);
+ }
+if (0) fprintf(stderr,"BE fetch %s - returning %d - and exists is %d\n",
+ _x((*out)->key),e,(*out)->state);
+ return e;
+}
+
+static int _store(void * conf, void * data)
+{
+ backend_caching_t *me = (backend_caching_t *) conf;
+ data_t * in = (data_t *) data;
+ int e;
+
+ if (in->state != CHANGED)
+ return 0;
+
+ e = (me->store->store)(me->instance,in->key,in->val);
+ switch(e) {
+ case 0:
+ /* ignore */
+ break;
+ case FLAT_STORE_E_KEYEXIST:
+ /* XXXXXXXXXXXXXXXXXXXXXXXXX we lose track of this ****XXXXXXXXXXXXXXXXX */
+ e = 0;
+ break;
+ default:
+ /* keep error code */
+ break;
+ }
+ return e;
+}
+
+static int _delete(void * conf, void * data)
+{
+ backend_caching_t *me = (backend_caching_t *) conf;
+ data_t * in = (data_t *) data;
+ int e = (me->store->delete)(me->instance,in->key); /* xxx we could also do this on a purge.. */
+ switch(e) {
+ case 0:
+ /* ignore */
+ break;
+ case FLAT_STORE_E_KEYEXIST:
+ e = 0;
+ break;
+ default:
+ /* keep error code */
+ break;
+ }
+ in->state = NOTFOUND; /* set to DELETE and do later on purge ?? */
+ return e;
+}
+
+static int _cpy(void * conf, void * from, void * to)
+{
+ *(data_t *)to = *(data_t *)from;
+ return 0;
+}
+
+static int _dup(void * conf, void * from, void * * to)
+{
+ backend_caching_t *me = (backend_caching_t *) conf;
+ data_t * p = (data_t *) from;
+ data_t * q;
+
+ if (!(q = me->malloc(sizeof(data_t))))
+ return -1;
+
+ memset(&(q->key),0,sizeof(q->key));
+ memset(&(q->val),0,sizeof(q->val));
+
+ if (p->key.data) {
+ if (!(q->key.data = me->malloc(p->key.size)))
+ return -1;
+ bcopy(p->key.data,q->key.data,p->key.size);
+ q->key.size = p->key.size;
+ } else {
+ q->key.data = NULL;
+ q->key.size = 0;
+ }
+
+ if (p->val.data) {
+ if (!(q->val.data = me->malloc(p->val.size)))
+ return -1;
+ bcopy(p->val.data,q->val.data,p->val.size);
+ q->val.size = p->val.size;
+ } else {
+ q->val.data = NULL;
+ q->val.size = 0;
+ }
+
+ q->state = p->state ;
+
+#if 0
+if (0) fprintf(stderr,"DUPed %s(%d,%d)==%s(%d,%d) exists=%d/%d\n",
+ _x(p->key), p->key.size,p->val.size,
+ _x(q->key), q->key.size,q->val.size,
+ p->state, q->state);
+#endif
+
+ *to = q;
+ return 0;
+}
+
+static int _drp(backend_caching_t * me, void * conf, void * data)
+{
+ data_t * p = (data_t *) data;
+ if (p->key.data)
+ (*(me->free))(p->key.data);
+ if (p->val.data)
+ (*(me->free))(p->val.data);
+ (*(me->free))(p);
+ return 0;
+}
+
+/*
+ * Some default call back functions.
+ */
+static void
+default_myfree(void *adr)
+{
+ RDFSTORE_FREE(adr);
+}
+static void *
+default_mymalloc(size_t x)
+{
+ return RDFSTORE_MALLOC(x);
+}
+static void
+default_myerror(char *err, int erx)
+{
+ fprintf(stderr, "backend_caching_ Error[%d]: %s\n", erx, err);
+}
+
+void
+backend_caching_set_error(
+ void *eme,
+ char *msg,
+ rdfstore_flat_store_error_t erx)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ (me->store->set_error)(me->instance,msg,erx);
+}
+
+char *
+backend_caching_get_error(void *eme)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ return (me->store->get_error)(me->instance);
+}
+
+/* clone a key or value for older BDB */
+DBT
+backend_caching_kvdup(
+ void *eme,
+ DBT data)
+{
+ backend_caching_t * me = (backend_caching_t *) eme;
+ return (me->store->kvdup)(me->instance,data);
+}
+
+void
+backend_caching_reset_debuginfo(
+ void *eme
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ (me->store->reset_debuginfo)(me->instance);
+}
+
+/*
+ * NOTE: all the functions return 0 on success and non zero value if error
+ * (see above and include/backend_caching_.h for known error codes)
+ */
+rdfstore_flat_store_error_t
+backend_caching_open(
+ int remote,
+ int ro,
+ void **emme,
+ char *dir,
+ char *name,
+ unsigned int local_hash_flags,
+ char *host,
+ int port,
+ void *(*_my_malloc) (size_t size),
+ void (*_my_free) (void *),
+ void (*_my_report) (dbms_cause_t cause, int count),
+ void (*_my_error) (char *err, int erx),
+ int bt_compare_fcn_type
+)
+{
+ backend_caching_t **mme = (backend_caching_t **) emme;
+ backend_caching_t *me;
+ char buff[1024];
+ int err;
+
+ *mme = NULL;
+
+ if (_my_error == NULL)
+ _my_error = default_myerror;
+
+ if (_my_malloc == NULL)
+ _my_malloc = default_mymalloc;
+
+ if (_my_free == NULL)
+ _my_free = default_myfree;
+
+ me = (backend_caching_t *) _my_malloc(sizeof(backend_caching_t));
+ if (me == NULL) {
+ perror("backend_caching_open");
+ return FLAT_STORE_E_NOMEM;
+ };
+
+ snprintf(buff,sizeof(buff)-1,"%p@%s:%d/%s/%s",
+ me,
+ host ? host : "<nohost>",
+ port ? port : 0,
+ dir ? dir : "<nodir>",
+ name ? name : "<inmemory>"
+ );
+ me->name = (char *)(*_my_malloc)( strlen(buff)+1 );
+ if( me->name == NULL )
+ return -1;
+ strcpy( me->name, buff );
+
+ me->malloc = _my_malloc;
+ me->free = _my_free;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ backend_caching_reset_debuginfo(me);
+#endif
+
+ switch (remote & 0xF) {
+ case 0:
+ me->store = backend_bdb;
+ break;
+ case 1:
+ me->store = backend_dbms;
+ break;
+ default:
+ perror("Backend type is not available");
+ return FLAT_STORE_E_NOMEM;
+ break;
+ };
+
+ /* Map to the real backend. */
+ err = (*(me->store->open)) (
+ remote & 0xF, ro, (void **) &(me->instance),
+ dir, name, local_hash_flags, host, port,
+ _my_malloc, _my_free, _my_report, _my_error,
+ bt_compare_fcn_type
+ );
+ if (err) {
+ (*_my_free) (me);
+ return err;
+ }
+ me->free = _my_free;
+
+ me->cache = (caching_store_t *)me->malloc(sizeof(caching_store_t));
+
+ /* Init with default cache size */
+ init_cachingstore(me->cache,0,
+ /* Functions to manage 'my' data */
+ me,
+ buff,
+ &_cmp,
+ &_fetch,
+ &_store,
+ &_delete,
+ &_dup,
+ &_cpy,
+ &_drp,
+ me->free,
+ me->malloc
+ );
+
+ * mme = me;
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ if (0) fprintf(stderr, "backend_caching_open '%s'\n", me->filename);
+#endif
+ return 0;
+}
+
+rdfstore_flat_store_error_t
+backend_caching_close(
+ void *eme
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ int e;
+if (0) fprintf(stderr,"%s: close\n",me->name);
+ purgecache(me, me->cache);
+ stats(me->cache);
+ e = (me->store->close)(me->instance);
+
+ me->free(me->name);
+ me->free(me->cache);
+ me->free(me);
+
+ return e;
+};
+
+rdfstore_flat_store_error_t
+backend_caching_fetch(
+ void *eme,
+ DBT key,
+ DBT * val
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ data_t d, * out = NULL;
+ int e;
+
+#if 0
+fprintf(stderr,"%s: fetch %s(%d,%d)\n",me->name,_x(key),(int)key.size,(int)val->size);
+#endif
+
+ /* Build a record */
+ d.key = key;
+ memset(&(d.val),0,sizeof(d.val));
+ d.val.data =NULL;
+ d.val.size = 0;
+ d.state = UNDEF; /* unkown */
+
+ if ((e = cachekey(me, me->cache,&d,(void **)&out, BC_READ))) {
+ return e;
+ }
+
+ val->data = out->val.data;
+ val->size = out->val.size;
+
+#if 0
+if (0) fprintf(stderr,"Cachekey returned e=%d and exits=%d val=%p,%d\n",e,out->state,val->data,val->size);
+#endif
+
+ if (out->state == NOTFOUND) {
+ me->free(out);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+
+ if (out->key.data)
+ me->free(out->key.data);
+ me->free(out);
+
+ return 0;
+}
+
+rdfstore_flat_store_error_t
+backend_caching_fetch_compressed(
+ void * eme,
+ void (*func_decode)(unsigned int,unsigned char*, unsigned int *, unsigned char *),
+ DBT key,
+ unsigned int * outsize_p, unsigned char * outchar
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ return (me->store->fetch_compressed)(me->instance,func_decode,key,outsize_p,outchar);
+}
+
+rdfstore_flat_store_error_t
+backend_caching_store(
+ void *eme,
+ DBT key,
+ DBT val
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ data_t d;
+ int e;
+
+ d.key = key;
+ d.val = val;
+ d.state = CHANGED;
+
+ e = cachekey(me, me->cache,&d,NULL,BC_WRITE);
+#if 0
+fprintf(stderr,"%s: store %s(%d,%d) E=%d\n",me->name,_x(key),(int)key.size,(int)val.size,e);
+#endif
+ return e;
+}
+
+rdfstore_flat_store_error_t
+backend_caching_store_compressed(
+ void * eme,
+ void (*func_decode)(unsigned int,unsigned char*, unsigned int *, unsigned char *),
+ DBT key,
+ unsigned int insize , unsigned char * inchar,
+ unsigned char * outbuff
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ return (me->store->store_compressed)(me->instance,func_decode,key,insize,inchar,outbuff);
+}
+
+rdfstore_flat_store_error_t
+backend_caching_exists(
+ void *eme,
+ DBT key
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ data_t d;
+ int e;
+
+ /* Build a record */
+ d.key = key;
+ memset(&(d.val),0,sizeof(d.val));
+ d.val.data =NULL;
+ d.val.size = 0;
+ d.state = UNDEF; /* unkown */
+
+ e = cachekey(me, me->cache,&d,NULL, BC_EXISTS);
+
+if (0) fprintf(stderr,"%s: exists %s ==> e=%d and d.exists=%d\n",me->name,_x(key),e,d.state);
+
+ if (e)
+ return e;
+
+
+ return (d.state == EXISTS || d.state == CHANGED) ? 0 : FLAT_STORE_E_NOTFOUND;
+}
+
+rdfstore_flat_store_error_t
+backend_caching_delete(
+ void *eme,
+ DBT key
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ data_t d;
+if (0) fprintf(stderr,"%s: delete\n",me->name);
+
+ d.key = key;
+ memset(&(d.val),0,sizeof(d.val));
+ d.state = UNDEF;
+
+ return cachekey(me, me->cache,&d,NULL, BC_DELETE);
+};
+
+rdfstore_flat_store_error_t
+backend_caching_clear(
+ void *eme
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+if (0) fprintf(stderr,"%s: clear\n",me->name);
+assert(0);
+ return (me->store->clear)(me->instance);
+}
+
+rdfstore_flat_store_error_t
+backend_caching_from(
+ void *eme,
+ DBT closest_key,
+ DBT * key
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+if (0) fprintf(stderr,"%s: from\n",me->name);
+ purgecache(me, me->cache);
+ return (me->store->from)(me->instance,closest_key,key);
+}
+
+rdfstore_flat_store_error_t
+backend_caching_first(
+ void *eme,
+ DBT * first_key
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+if (0) fprintf(stderr,"%s: first\n",me->name);
+ purgecache(me, me->cache);
+ return (me->store->first)(me->instance,first_key);
+}
+
+rdfstore_flat_store_error_t
+backend_caching_next(
+ void *eme,
+ DBT previous_key,
+ DBT * next_key
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+if (0) fprintf(stderr,"%s: next\n",me->name);
+ purgecache(me, me->cache);
+ return (me->store->next)(me->instance,previous_key,next_key);
+}
+
+/* packed rdf_store_counter_t increment */
+rdfstore_flat_store_error_t
+backend_caching_inc(
+ void *eme,
+ DBT key,
+ DBT * new_value
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ rdf_store_counter_t l = 0;
+ int e;
+ memset(new_value, 0, sizeof(*new_value));
+#if 0
+fprintf(stderr,"%s: inc %s\n",me->name,_x(key));
+#endif
+
+ e = backend_caching_fetch(eme,key,new_value);
+ if (e)
+ return e;
+
+ unpackInt(new_value->data, &l);
+ l++;
+ packInt(l, new_value->data);
+
+ if ((e = backend_caching_store(eme,key,*new_value))) {
+ memset(new_value, 0, sizeof(*new_value));
+ } else {
+ (*new_value) = backend_caching_kvdup(me, *new_value);
+ }
+ return e;
+}
+
+/* packed rdf_store_counter_t decrement */
+rdfstore_flat_store_error_t
+backend_caching_dec(
+ void *eme,
+ DBT key,
+ DBT * new_value
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ rdf_store_counter_t l = 0;
+ int e;
+
+ memset(new_value, 0, sizeof(*new_value));
+
+if (0) fprintf(stderr,"%s: dec\n",me->name);
+ e = backend_caching_fetch(eme,key,new_value);
+ if (e)
+ return e;
+
+ unpackInt(new_value->data, &l);
+ l--;
+ packInt(l, new_value->data);
+
+ if ((e = backend_caching_store(eme,key,*new_value))) {
+ memset(new_value, 0, sizeof(*new_value));
+ } else {
+ (*new_value) = backend_caching_kvdup(me, *new_value);
+ }
+
+ return e;
+}
+
+rdfstore_flat_store_error_t
+backend_caching_sync(
+ void *eme
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+if (0) fprintf(stderr,"%s: sync\n",me->name);
+ purgecache(me, me->cache);
+ return (me->store->sync)(me->instance);
+}
+
+int
+backend_caching_isremote(
+ void *eme
+)
+{
+ backend_caching_t *me = (backend_caching_t *) eme;
+ return (me->store->isremote)(me->instance);
+}
+
+
+#define CACHING_VERSION (100)
+DECLARE_MODULE_BACKEND(backend_caching, "Caching", CACHING_VERSION)
+
Added: incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_dbms_store.c
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_dbms_store.c?view=auto&rev=528394
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_dbms_store.c (added)
+++ incubator/triplesoup/donations/TRIPLES-3-RDFStore/backend_dbms_store.c Fri Apr 13 01:56:01 2007
@@ -0,0 +1,695 @@
+/*
+##############################################################################
+# Copyright (c) 2000-2006 All rights reserved
+# Alberto Reggiori <ar...@webweaving.org>
+# Dirk-Willem van Gulik <di...@webweaving.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# 3. The end-user documentation included with the redistribution,
+# if any, must include the following acknowledgment:
+# "This product includes software developed by
+# Alberto Reggiori <ar...@webweaving.org> and
+# Dirk-Willem van Gulik <di...@webweaving.org>."
+# Alternately, this acknowledgment may appear in the software itself,
+# if and wherever such third-party acknowledgments normally appear.
+#
+# 4. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+#
+# 5. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# 6. Products derived from this software may not be called "RDFStore"
+# nor may "RDFStore" appear in their names without prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ====================================================================
+#
+# This software consists of work developed by Alberto Reggiori and
+# Dirk-Willem van Gulik. The RDF specific part is based based on public
+# domain software written at the Stanford University Database Group by
+# Sergey Melnik. For more information on the RDF API Draft work,
+# please see <http://www-db.stanford.edu/~melnik/rdf/api.html>
+# The DBMS TCP/IP server part is based on software originally written
+# by Dirk-Willem van Gulik for Web Weaving Internet Engineering m/v Enschede,
+# The Netherlands.
+#
+##############################################################################
+#
+# $Id: backend_dbms_store.c,v 1.10 2006/06/19 10:10:21 areggiori Exp $
+*/
+#include "dbms.h"
+#include "dbms_compat.h"
+#include "dbms_comms.h"
+
+#include "db.h"
+
+#include "rdfstore_flat_store.h"
+#include "rdfstore_log.h"
+#include "rdfstore.h"
+
+#include "backend_store.h"
+#include "backend_dbms_store.h"
+#include "backend_dbms_store_private.h"
+
+/* dbms_store error management */
+static char _dbms_store_erm[256] = "\0";
+
+/* human-readable error codes */
+static char *dbms_store_error[] = {
+ /* FLAT_STORE_E_UNDEF 2000 */
+ "Not defined",
+ /* FLAT_STORE_E_NONNUL 2001 */
+ "Undefined Error",
+ /* FLAT_STORE_E_NOMEM 2002 */
+ "Out of memory",
+ /* FLAT_STORE_E_NOPE 2003 */
+ "No such database",
+ /* FLAT_STORE_E_KEYEMPTY 2004 */
+ "Key/data deleted or never created",
+ /* FLAT_STORE_E_KEYEXIST 2005 */
+ "The key/data pair already exists",
+ /* FLAT_STORE_E_NOTFOUND 2006 */
+ "Key/data pair not found",
+ /* FLAT_STORE_E_OLD_VERSION 2007 */
+ "Out-of-date version",
+ /* FLAT_STORE_E_DBMS 2008 */
+ "DBMS error",
+ /* FLAT_STORE_E_CANNOTOPEN 2009 */
+ "Cannot open database",
+ /* FLAT_STORE_E_BUG 2010 */
+ "Conceptual error"
+};
+
+/*
+ * Some default call back functions.
+ */
+static void
+default_myfree(void *adr)
+{
+ RDFSTORE_FREE(adr);
+}
+static void *
+default_mymalloc(size_t x)
+{
+ return RDFSTORE_MALLOC(x);
+}
+static void
+default_myerror(char *err, int erx)
+{
+ fprintf(stderr, "backend_dbms_ Error[%d]: %s\n", erx, err);
+}
+
+void
+backend_dbms_set_error(
+ void *eme,
+ char *msg,
+ rdfstore_flat_store_error_t erx)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ bzero(me->err, sizeof(me->err));
+ if (erx == FLAT_STORE_E_DBMS) {
+ snprintf(me->err, sizeof(me->err), "DBMS Error %s: %s\n", msg,
+ errno == 0 ? "" : (strlen(strerror(errno)) <= sizeof(me->err)) ? strerror(errno) : ""); /* not enough... */
+ } else {
+ if ((erx > FLAT_STORE_E_UNDEF) && (erx <= FLAT_STORE_E_BUG)) {
+ strcpy(me->err, dbms_store_error[erx - FLAT_STORE_E_UNDEF]);
+ } else {
+ if (strlen(strerror(erx)) <= sizeof(me->err))
+ strcpy(me->err, strerror(erx));
+ };
+ };
+ if (strlen(me->err) <= sizeof(_dbms_store_erm))
+ strcpy(_dbms_store_erm, me->err);
+
+#ifdef VERBOSE
+ if (me->error)
+ (*(me->error)) (me->err, erx);
+#endif
+}
+
+
+char *
+backend_dbms_get_error(void *eme)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ if (me == NULL)
+ return _dbms_store_erm;
+ else
+ return me->err;
+}
+
+/* clone a key or value for older BDB */
+DBT
+backend_dbms_kvdup(
+ void *eme,
+ DBT data)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ DBT dup;
+ memset(&dup, 0, sizeof(dup));
+
+ if (data.size == 0) {
+ dup.data = NULL;
+ return dup;
+ };
+
+ dup.size = data.size;
+
+ if ((dup.data = (char *) me->malloc(data.size + 1)) != NULL) {
+ memcpy(dup.data, data.data, data.size);
+ memcpy(dup.data + data.size, "\0", 1);
+ };
+
+ return dup;
+};
+
+void
+backend_dbms_reset_debuginfo(
+ void *eme
+)
+{
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ dbms_store_t *me = (dbms_store_t *) eme;
+ me->num_store = 0;
+ me->num_fetch = 0;
+ me->num_inc = 0;
+ me->num_dec = 0;
+ me->num_sync = 0;
+ me->num_next = 0;
+ me->num_from = 0;
+ me->num_first = 0;
+ me->num_delete = 0;
+ me->num_clear = 0;
+ me->num_exists = 0;
+#endif
+}
+
+/*
+ * NOTE: all the functions return 0 on success and non zero value if error
+ * (see above and include/backend_dbms_.h for known error codes)
+ */
+rdfstore_flat_store_error_t
+backend_dbms_open(
+ int remote,
+ int ro,
+ void **emme,
+ char *dir,
+ char *name,
+ unsigned int local_hash_flags,
+ char *host,
+ int port,
+ void *(*_my_malloc) (size_t size),
+ void (*_my_free) (void *),
+ void (*_my_report) (dbms_cause_t cause, int count),
+ void (*_my_error) (char *err, int erx),
+ int bt_compare_fcn_type
+)
+{
+ dbms_store_t **mme = (dbms_store_t **) emme;
+ dbms_store_t *me;
+ char *buff;
+
+ *mme = NULL;
+
+ if (_my_error == NULL)
+ _my_error = default_myerror;
+
+ if (_my_malloc == NULL)
+ _my_malloc = default_mymalloc;
+
+ if (_my_free == NULL)
+ _my_free = default_myfree;
+
+ me = (dbms_store_t *) _my_malloc(sizeof(dbms_store_t));
+ if (me == NULL) {
+ perror("backend_dbms_open");
+ return FLAT_STORE_E_NOMEM;
+ };
+
+ me->error = _my_error;
+ bzero(me->err, sizeof(me->err));
+ me->malloc = _my_malloc;
+ me->free = _my_free;
+
+ if (_my_report != NULL)
+ me->callback = _my_report;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ backend_dbms_reset_debuginfo(me);
+#endif
+
+ if (!remote) {
+ backend_dbms_set_error(me, "DBMS can only be remote", FLAT_STORE_E_CANNOTOPEN);
+ perror("backend_dbms_open");
+ _my_free(me);
+ return FLAT_STORE_E_CANNOTOPEN;
+ };
+
+ if ((dir) &&
+ (name)) {
+ strcpy(me->filename, dir);
+ strcat(me->filename, "/");
+ strcat(me->filename, name);
+ } else {
+ strcpy(me->filename, "\0");
+ buff = NULL;
+ };
+
+ if (((me->dbms = dbms_connect(
+ me->filename,
+ host, port,
+ ((ro == 0) ? (DBMS_XSMODE_CREAT) : (DBMS_XSMODE_RDONLY)),
+ _my_malloc, _my_free, /* malloc/free to use */
+ _my_report, /* Callback for warnings */
+ _my_error, /* Calllback to set error(variables) */
+ bt_compare_fcn_type
+ ))) == NULL) {
+ backend_dbms_set_error(me, "Could not open/create database", FLAT_STORE_E_CANNOTOPEN);
+ perror("backend_dbms_open");
+ fprintf(stderr, "Could not open/create '%s': %s\n", me->filename, backend_dbms_get_error(me));
+ _my_free(me);
+ return FLAT_STORE_E_CANNOTOPEN;
+ };
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_open '%s'\n", me->filename);
+#endif
+
+ *mme = me;
+ return 0;
+}
+
+rdfstore_flat_store_error_t
+backend_dbms_close(
+ void *eme
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ void (*_my_free) (void *) = me->free;
+ int retval = 0;
+
+ dbms_disconnect(me->dbms);
+ _my_free(me);
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_close '%s'\n", me->filename);
+#endif
+
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_dbms_fetch(
+ void *eme,
+ DBT key,
+ DBT * val
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval = 0;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_fetch num=%d from '%s'\n", ++(me->num_fetch), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_FETCH, &retval, &key, NULL, NULL, val)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_fetch");
+ fprintf(stderr, "Could not fetch '%s': %s\n", me->filename, (char *) key.data);
+ return FLAT_STORE_E_DBMS;
+ };
+
+ if (retval == 1) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_NOTFOUND);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+
+ /* to duplicate rertun value */
+
+ return retval;
+}
+
+rdfstore_flat_store_error_t
+backend_dbms_fetch_compressed(
+ void * eme,
+ void (*func_decode)(unsigned int,unsigned char*, unsigned int *, unsigned char *),
+ DBT key,
+ unsigned int * outsize_p, unsigned char * outchar
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval = 0;
+ DBT val;
+ memset(&val, 0, sizeof(val));
+
+ if ((retval = backend_dbms_fetch(eme,key,&val)))
+ return retval;
+
+ (*func_decode)(val.size,val.data,outsize_p,outchar);
+ (me->free)(val.data);
+
+ return retval;
+}
+
+rdfstore_flat_store_error_t
+backend_dbms_store(
+ void *eme,
+ DBT key,
+ DBT val
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval = 0;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_store num=%d in '%s'\n", ++(me->num_store), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_STORE, &retval, &key, &val, NULL, NULL)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_store");
+ fprintf(stderr, "Could not store '%s': %s = %s\n", me->filename, (char *) key.data, (char *) val.data);
+ return FLAT_STORE_E_DBMS;
+ };
+ if (retval != 0) {
+ if (retval == 1) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_KEYEXIST);
+ return FLAT_STORE_E_KEYEXIST;
+ } else {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_NOTFOUND);
+ perror("backend_dbms_store");
+ fprintf(stderr, "Could not store '%s': %s = %s\n", me->filename, (char *) key.data, (char *) val.data);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+ };
+
+ return retval;
+}
+
+rdfstore_flat_store_error_t
+backend_dbms_store_compressed(
+ void * eme,
+ void (*func_decode)(unsigned int,unsigned char*, unsigned int *, unsigned char *),
+ DBT key,
+ unsigned int insize , unsigned char * inchar,
+ unsigned char * outbuff
+)
+{
+ int outsize;
+ DBT val;
+
+ (*func_decode)(insize,inchar, &outsize, outbuff);
+
+ memset(&val, 0, sizeof(val));
+ val.data = outbuff;
+ val.size = outsize;
+
+ return backend_dbms_store(eme,key,val);
+}
+
+rdfstore_flat_store_error_t
+backend_dbms_exists(
+ void *eme,
+ DBT key
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_exists num=%d from '%s'\n", ++(me->num_exists), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_EXISTS, &retval, &key, NULL, NULL, NULL)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_exists");
+ fprintf(stderr, "Could not exists '%s': %s\n", me->filename, (char *) key.data);
+ return FLAT_STORE_E_DBMS;
+ };
+ if (retval == 1) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_NOTFOUND);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_dbms_delete(
+ void *eme,
+ DBT key
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_delete num=%d from '%s'\n", ++(me->num_delete), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_DELETE, &retval, &key, NULL, NULL, NULL)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_delete");
+ fprintf(stderr, "Could not delete '%s': %s\n", me->filename, (char *) key.data);
+ return FLAT_STORE_E_DBMS;
+ };
+
+ if (retval != 0) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_NOTFOUND);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_dbms_clear(
+ void *eme
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ me->num_store = 0;
+ me->num_fetch = 0;
+ me->num_inc = 0;
+ me->num_dec = 0;
+ me->num_sync = 0;
+ me->num_next = 0;
+ me->num_from = 0;
+ me->num_first = 0;
+ me->num_delete = 0;
+ me->num_exists = 0;
+ fprintf(stderr, "backend_dbms_clear num=%d in '%s'\n", ++(me->num_clear), me->filename);
+#endif
+
+ int retval;
+
+ if (dbms_comms(me->dbms, TOKEN_CLEAR, &retval, NULL, NULL, NULL, NULL)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_clear");
+ fprintf(stderr, "Could not clear '%s'\n", me->filename);
+ return FLAT_STORE_E_DBMS;
+ };
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_dbms_from(
+ void *eme,
+ DBT closest_key,
+ DBT * key
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_from num=%d from '%s'\n", ++(me->num_from), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_FROM, &retval, &closest_key, NULL, key, NULL)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_from");
+ fprintf(stderr, "Could not from '%s'\n", me->filename);
+ return FLAT_STORE_E_DBMS;
+ };
+
+ if (retval == 1) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_NOTFOUND);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_dbms_first(
+ void *eme,
+ DBT * first_key
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_first num=%d from '%s'\n", ++(me->num_first), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_FIRSTKEY, &retval, NULL, NULL, first_key, NULL)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_first");
+ fprintf(stderr, "Could not first '%s'\n", me->filename);
+ return FLAT_STORE_E_DBMS;
+ };
+
+ if (retval == 1) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_NOTFOUND);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+ return retval;
+};
+
+rdfstore_flat_store_error_t
+backend_dbms_next(
+ void *eme,
+ DBT previous_key,
+ DBT * next_key
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_next num=%d from '%s'\n", ++(me->num_next), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_NEXTKEY, &retval, &previous_key, NULL, next_key, NULL)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_next");
+ fprintf(stderr, "Could not next '%s': %s\n", me->filename, (char *) previous_key.data);
+ return FLAT_STORE_E_DBMS;
+ };
+
+ if (retval == 1) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_NOTFOUND);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+ return retval;
+};
+
+/* packed rdf_store_counter_t increment */
+rdfstore_flat_store_error_t
+backend_dbms_inc(
+ void *eme,
+ DBT key,
+ DBT * new_value
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_inc num=%d in '%s'\n", ++(me->num_inc), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_PACKINC, &retval, &key, NULL, NULL, new_value)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_inc");
+ fprintf(stderr, "Could not inc '%s': %s\n", me->filename, (char *) key.data);
+ return FLAT_STORE_E_DBMS;
+ };
+
+ if (retval == 1) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_NOTFOUND);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+ return retval;
+}
+
+/* packed rdf_store_counter_t decrement */
+rdfstore_flat_store_error_t
+backend_dbms_dec(
+ void *eme,
+ DBT key,
+ DBT * new_value
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_dec num=%d from '%s'\n", ++(me->num_dec), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_PACKDEC, &retval, &key, NULL, NULL, new_value)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_dec");
+ fprintf(stderr, "Could not dec '%s': %s\n", me->filename, (char *) key.data);
+ return FLAT_STORE_E_DBMS;
+ };
+
+ if (retval == 1) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_NOTFOUND);
+ return FLAT_STORE_E_NOTFOUND;
+ };
+ return retval;
+}
+
+rdfstore_flat_store_error_t
+backend_dbms_sync(
+ void *eme
+)
+{
+ dbms_store_t *me = (dbms_store_t *) eme;
+ int retval;
+
+#ifdef RDFSTORE_FLAT_STORE_DEBUG
+ fprintf(stderr, "backend_dbms_sync num=%d in '%s'\n", ++(me->num_sync), me->filename);
+#endif
+
+ if (dbms_comms(me->dbms, TOKEN_SYNC, &retval, NULL, NULL, NULL, NULL)) {
+ backend_dbms_set_error(me, dbms_get_error(me->dbms), FLAT_STORE_E_DBMS);
+ perror("backend_dbms_sync");
+ fprintf(stderr, "Could not sync '%s'\n", me->filename);
+ return FLAT_STORE_E_DBMS;
+ }
+ return retval;
+}
+
+int
+backend_dbms_isremote(
+ void *eme
+)
+{
+ /* dbms_store_t * me = (dbms_store_t *)eme; */
+ return 1;
+}
+
+#define DBMS_VERSION (100)
+DECLARE_MODULE_BACKEND(backend_dbms, "DBMS", DBMS_VERSION);
Added: incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/.cvsignore
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/.cvsignore?view=auto&rev=528394
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/.cvsignore (added)
+++ incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/.cvsignore Fri Apr 13 01:56:01 2007
@@ -0,0 +1 @@
+arch.conf
Added: incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/AUTHORS
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/AUTHORS?view=auto&rev=528394
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/AUTHORS (added)
+++ incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/AUTHORS Fri Apr 13 01:56:01 2007
@@ -0,0 +1,2 @@
+Dirk-Willem van Gulik <di...@webweaving.org>
+Alberto Reggiori <ar...@webweaving.org>
Added: incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/CHANGES
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/CHANGES?view=auto&rev=528394
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/CHANGES (added)
+++ incubator/triplesoup/donations/TRIPLES-3-RDFStore/dbms/CHANGES Fri Apr 13 01:56:01 2007
@@ -0,0 +1,127 @@
+Revision history for RDFStore tcp/ip backend storage
+
+version 1.7 (version taken from dbms/veersion.c)
+-------------------------------------------------------------------------------------------
+
+ utils/
+ - added dbms_mirror.pl to copy/mirror DBMS tables either locally or remotely
+
+ dbmsproxy/
+ - added dbmsproxy to use cheap local unix socket for reads if possible.
+
+ client/t/*
+ - updated to receive bt_compare_fcn_type paramter after mode
+
+ include/dbms.h
+ - added bt_compare_fcn_type to dbms struct
+
+ include/dbms_comms.h
+ - added TOKEN_FROM
+
+ deamon/hanlder.c
+ - added TOKEN_FROM handler for from() operation
+ - added bt_compare_fcn_type paramter management to receive from client
+ - fixed bug in frist(), next() methods to use the right macros depending on BDB version
+
+ libdbms/libdbms.c
+ - updated to use debug malloc/free
+ - added TOKEN_FROM
+ - added bt_compare_fcn_type paramter management to send to server
+
+version 1.2.
+-------------------------------------------------------------------------------------------
+
+ Abstracted out a libdbms(.a) which contains all
+ the communciation code and does better error handling.
+ the perl side is now just a wrapper.
+
+ Abstracted/moved all specific things into a compat header
+ file (see include/*compat*).
+
+ Renamed directory DBMS to client and added client/stub.[ch]
+
+ include/dbms.h
+ - added TOKEN_DEC for atomic decrement
+ - added TOKEN_PACKINC for atomic packed increment
+ - added TOKEN_PACKDEC for atomic packed decrement
+
+ deamon/deamon.h
+ - added definitions for BDB > 1.8x support
+
+ deamon/hanlder.c
+ - added basic BDB > 1.8x support
+ - added atomic decrement support via do_dec()
+ - added atomic packed increment support via do_packinc()
+ - added atomic packed decrement support via do_packdec()
+
+ client/DBMS.xs
+ - updated perl/XS glue code
+ - added atomic decrement - see DEC()
+ - moved client related definitions in client/stub.h
+ - moved code to main RDFStore.xs to avoid dynamic linking problems of libdbms.so
+
+ client/DBMS.pm
+ - added atomic decrement - see dec()
+ - moved one level up to main rdfstore dist dir (see ../lib)
+
+version 1.1.1.1 - 2001/01/18 09:53:20
+-------------------------------------------------------------------------------------------
+
+ A a new version of dbmsd has been made. Most of this code come from one of the
+ leatest version authored by Dirk Willem-van Gulik early 1999. Since version 0.1
+ I simpy posted his code almost untouched, but due the fact dirk left since a year
+ ago I will take over the dbmsd project. I am not a C guru and volunteers are
+ welcome. What is new:
+
+ - dirk started with multi-thread supported but it was never finished that
+ I know of
+ - some bug fixing to get it compiled on Irix and Solaris has been made
+ - dbmsd still use BerkeleyDB 1.x style interface
+
+ Now DBMS runs fine on Linux platforms (tested on SuSE Linux Linux 2.2.16) by using the
+ Sleepycat BDB 1.85 compatibility API (namely libdb1 and db_185.h). The user needs to edit
+ the deamon/Makefile to link with the right library.
+
+ DBMS/typemap
+ - Fixed bug to make it compile on old and recent Perl5 versions
+
+ Makefile
+ - general update. Added make depend for deamon
+
+ deamon/children.c
+ - added platform check to include compatibility code db_185.h
+
+ deamon/deamon.c
+ - added platform check to include compatibility code db_185.h
+
+ deamon/deamon.h
+ - added platform check to include compatibility code db_185.h
+
+ deamon/handler.c
+ - added platform check to include compatibility code db_185.h
+
+ deamon/loop.c
+ - added platform check to include compatibility code db_185.h
+
+ deamon/main.c
+ - added platform check to include compatibility code db_185.h
+
+ deamon/Makefile
+ - commented out a few options and cleaned up a few things
+ - added (optional) libdb1 to get DBMS compile on Linux
+
+ deamon/README
+ - included README file originally written by dirk
+
+ utils
+ - moved original utils/dbcat_raw utils to dbsm dirs
+
+ doc
+ - added documentation section
+ - added dbms.html contribution by dirkx@webweaving.org
+
+ INSTALL
+ - added installation instructions
+
+ deamon/handler.c
+ - commented out sys/syslimits.h (already included by sys/param.h)