Files
Mozilla/mozilla/db/tripledb/src/intern.c
terry%mozilla.org 981fe96b56 TripleDB has been completely rewritten. Now requires Sleepycat Berkeley DB.
git-svn-id: svn://10.0.0.236/trunk@72984 18797224-902f-48f8-a5cc-f745e15eee43
2000-06-22 23:11:37 +00:00

238 lines
6.7 KiB
C

/* -*- Mode: C; indent-tabs-mode: nil; -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the TripleDB database library.
*
* The Initial Developer of the Original Code is Geocast Network Systems.
* Portions created by Geocast are
* Copyright (C) 2000 Geocast Network Systems. All
* Rights Reserved.
*
* Contributor(s): Terry Weissman <terry@mozilla.org>
*/
#include "tdbtypes.h"
#include "intern.h"
#include "node.h"
#include "tdb.h"
#include "util.h"
struct _TDBIntern {
DB* nodetoatomdb;
DB* atomtonodedb;
char* tmpbuf;
TDBInt32 tmpbufsize;
};
TDBIntern*
tdbInternInit(TDBBase* base)
{
TDBIntern* intern;
if (base == NULL) {
tdb_ASSERT(0);
return NULL;
}
intern = tdb_NEWZAP(TDBIntern);
if (!intern) return NULL;
if (db_create(&(intern->nodetoatomdb), tdbGetDBEnv(base), 0) != DB_OK) {
goto FAIL;
}
if (intern->nodetoatomdb->open(intern->nodetoatomdb, "nodetoatomdb",
NULL, DB_HASH,
DB_CREATE, 0666) != DB_OK) goto FAIL;
if (db_create(&(intern->atomtonodedb), tdbGetDBEnv(base), 0) != DB_OK) {
goto FAIL;
}
if (intern->atomtonodedb->open(intern->atomtonodedb, "atomtonodedb",
NULL, DB_RECNO,
DB_CREATE, 0666) != DB_OK) goto FAIL;
intern->tmpbufsize = 512;
intern->tmpbuf = tdb_Malloc(intern->tmpbufsize);
if (!intern->tmpbuf) goto FAIL;
return intern;
FAIL:
tdbInternFree(intern);
return NULL;
}
void
tdbInternFree(TDBIntern* intern)
{
if (intern == NULL) {
tdb_ASSERT(0);
return;
}
if (intern->nodetoatomdb) {
intern->nodetoatomdb->close(intern->nodetoatomdb, 0);
}
if (intern->atomtonodedb) {
intern->atomtonodedb->close(intern->atomtonodedb, 0);
}
if (intern->tmpbuf) tdb_Free(intern->tmpbuf);
tdb_Free(intern);
}
TDBNodePtr
tdbIntern(TDBBase* base, TDBNodePtr node)
{
TDBIntern* intern;
char* ptr;
char* endptr;
DBT key;
DBT data;
int dbstatus;
TDBUint32 atom;
TDBUint32 atom2;
if (base == NULL || node == NULL) {
tdb_ASSERT(0);
return NULL;
}
intern = tdbGetIntern(base);
if (intern == NULL || intern->tmpbuf == NULL) {
tdb_ASSERT(0);
return NULL;
}
if (node->type == TDBTYPE_MINNODE) {
return TDBCreateIntNode(0, TDBTYPE_INTERNED);
}
if (node->type == TDBTYPE_MAXNODE) {
return TDBCreateIntNode(0xffffffff, TDBTYPE_INTERNED);
}
if (node->type == TDBTYPE_INTERNED) {
tdb_ASSERT(0);
return NULL;
}
if (intern->tmpbuf) {
ptr = intern->tmpbuf;
endptr = ptr + intern->tmpbufsize;
tdbPutNode(&ptr, node, endptr);
} else {
ptr = NULL;
}
if (ptr == NULL || ptr >= endptr) {
intern->tmpbufsize = tdbNodeSize(node) + 10;
intern->tmpbuf = tdb_Realloc(intern->tmpbuf, intern->tmpbufsize);
if (!intern->tmpbuf) return NULL;
ptr = intern->tmpbuf;
endptr = ptr + intern->tmpbufsize;
tdbPutNode(&ptr, node, endptr);
if (ptr >= endptr) {
tdb_ASSERT(0);
return NULL;
}
}
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = intern->tmpbuf;
key.size = ptr - intern->tmpbuf;
dbstatus = intern->nodetoatomdb->get(intern->nodetoatomdb,
tdbGetTransaction(base),
&key, &data, 0);
if (dbstatus == DB_NOTFOUND) {
do {
data.data = &atom;
data.ulen = sizeof(atom);
data.flags = DB_DBT_USERMEM;
dbstatus = intern->atomtonodedb->put(intern->atomtonodedb,
tdbGetTransaction(base),
&data, &key, DB_APPEND);
if (dbstatus != DB_OK) return NULL;
tdb_ASSERT(data.size == sizeof(TDBUint32));
} while (atom == 0); /* First time, we may get an atom of zero,
which I don't want, since I reserve atom
of zero to mean something special. */
data.data = &atom2;
ptr = data.data;
endptr = ptr + data.size;
tdbPutUInt32(&ptr, atom, endptr);
dbstatus = intern->nodetoatomdb->put(intern->nodetoatomdb,
tdbGetTransaction(base),
&key, &data, 0);
if (dbstatus != DB_OK) return NULL;
} else {
if (dbstatus != DB_OK) return NULL;
if (data.size != sizeof(TDBUint32)) {
tdb_ASSERT(0);
return NULL;
}
ptr = data.data;
endptr = ptr + data.size;
atom = tdbGetUInt32(&ptr, endptr);
}
return TDBCreateIntNode(atom, TDBTYPE_INTERNED);
}
TDBNodePtr
tdbUnintern(TDBBase* base, TDBNodePtr node)
{
char* ptr;
char* endptr;
DBT key;
DBT data;
TDBIntern* intern;
TDBUint32 atom;
int dbstatus;
if (base == NULL || node == NULL || node->type != TDBTYPE_INTERNED ||
node->d.i == 0 || node->d.i == 0xffffffff) {
tdb_ASSERT(0);
return NULL;
}
intern = tdbGetIntern(base);
if (intern == NULL) {
tdb_ASSERT(0);
return NULL;
}
atom = node->d.i;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = &atom;
key.size = sizeof(atom);
dbstatus = intern->atomtonodedb->get(intern->atomtonodedb,
tdbGetTransaction(base),
&key, &data, 0);
if (dbstatus != DB_OK) return NULL;
ptr = (char*) data.data;
endptr = ptr + data.size;
return tdbGetNode(&ptr, endptr);
}
TDBStatus
tdbInternSync(TDBBase* base)
{
TDBIntern* intern;
if (base == NULL) {
tdb_ASSERT(0);
return TDB_FAILURE;
}
intern = tdbGetIntern(base);
if (intern->atomtonodedb->sync(intern->atomtonodedb, 0) != DB_OK) {
return TDB_FAILURE;
}
if (intern->nodetoatomdb->sync(intern->nodetoatomdb, 0) != DB_OK) {
return TDB_FAILURE;
}
return TDB_SUCCESS;
}