mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-12 19:22:41 +00:00
DtMmdb: replace Berkeley DB with LMDB.
This commit is contained in:
parent
3fa42c44a8
commit
c7ade43d86
36 changed files with 106 additions and 6835 deletions
|
@ -492,6 +492,12 @@ AC_CHECK_LIB(jpeg, jpeg_read_header, [JPEGLIB="-ljpeg"],
|
||||||
[${EXTRA_INCS} ${EXTRA_LIBS}])
|
[${EXTRA_INCS} ${EXTRA_LIBS}])
|
||||||
AC_SUBST(JPEGLIB)
|
AC_SUBST(JPEGLIB)
|
||||||
|
|
||||||
|
dnl lmdb
|
||||||
|
AC_CHECK_LIB(lmdb, mdb_version, [LMDBLIB="-llmdb"],
|
||||||
|
[AC_MSG_ERROR([liblmdb not found, please install it])],
|
||||||
|
[${EXTRA_INCS} ${EXTRA_LIBS}])
|
||||||
|
AC_SUBST(LMDBLIB)
|
||||||
|
|
||||||
dnl Setup XTOOLLIB - we do it in this specific order to avoid ordering
|
dnl Setup XTOOLLIB - we do it in this specific order to avoid ordering
|
||||||
dnl issues
|
dnl issues
|
||||||
XTOOLLIB=""
|
XTOOLLIB=""
|
||||||
|
@ -633,7 +639,6 @@ lib/DtMmdb/HardCopy/Makefile
|
||||||
lib/DtMmdb/StyleSheet/Makefile
|
lib/DtMmdb/StyleSheet/Makefile
|
||||||
lib/DtMmdb/api/Makefile
|
lib/DtMmdb/api/Makefile
|
||||||
lib/DtMmdb/btree/Makefile
|
lib/DtMmdb/btree/Makefile
|
||||||
lib/DtMmdb/btree_berkeley/Makefile
|
|
||||||
lib/DtMmdb/compression/Makefile
|
lib/DtMmdb/compression/Makefile
|
||||||
lib/DtMmdb/diskhash/Makefile
|
lib/DtMmdb/diskhash/Makefile
|
||||||
lib/DtMmdb/dstr/Makefile
|
lib/DtMmdb/dstr/Makefile
|
||||||
|
|
|
@ -4,7 +4,6 @@ SUBDIRS = HardCopy \
|
||||||
StyleSheet \
|
StyleSheet \
|
||||||
api \
|
api \
|
||||||
btree \
|
btree \
|
||||||
btree_berkeley \
|
|
||||||
compression \
|
compression \
|
||||||
diskhash \
|
diskhash \
|
||||||
dstr \
|
dstr \
|
||||||
|
@ -29,7 +28,6 @@ libDtMmdb_la_LIBADD = HardCopy/libHardCopy.la \
|
||||||
StyleSheet/libStyleSheet.la \
|
StyleSheet/libStyleSheet.la \
|
||||||
api/libapi.la \
|
api/libapi.la \
|
||||||
btree/libbtree.la \
|
btree/libbtree.la \
|
||||||
btree_berkeley/libbtree_berkeley.la \
|
|
||||||
compression/libcompression.la \
|
compression/libcompression.la \
|
||||||
diskhash/libdiskhash.la \
|
diskhash/libdiskhash.la \
|
||||||
dstr/libdstr.la \
|
dstr/libdstr.la \
|
||||||
|
|
|
@ -4,4 +4,4 @@ noinst_LTLIBRARIES = libbtree.la
|
||||||
|
|
||||||
libbtree_la_CXXFLAGS = -I..
|
libbtree_la_CXXFLAGS = -I..
|
||||||
|
|
||||||
libbtree_la_SOURCES = mmdb_btree.C
|
libbtree_la_SOURCES = btree.C
|
||||||
|
|
|
@ -48,44 +48,45 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "btree/mmdb_btree.h"
|
#include "btree/btree.h"
|
||||||
|
|
||||||
|
|
||||||
btree::btree(const char* store_name)
|
btree::btree(const char* store_name)
|
||||||
{
|
{
|
||||||
// let the package figure out all these parameters
|
int err;
|
||||||
btree_info.flags = 0;
|
MDB_txn *txn;
|
||||||
btree_info.cachesize = 0;
|
|
||||||
btree_info.maxkeypage = 0;
|
|
||||||
btree_info.minkeypage = 0;
|
|
||||||
btree_info.psize = 0;
|
|
||||||
btree_info.compare = NULL;
|
|
||||||
btree_info.prefix = NULL;
|
|
||||||
btree_info.lorder = 0;
|
|
||||||
|
|
||||||
key_DBT.data = 0;
|
key_DBT.mv_data = 0;
|
||||||
key_DBT.size = 0;
|
key_DBT.mv_size = 0;
|
||||||
|
|
||||||
int mode = O_CREAT|O_RDWR;
|
if ((err = mdb_env_create(&btree_env)))
|
||||||
|
throw(stringException(mdb_strerror(err)));
|
||||||
|
|
||||||
//btree_DB = dbopen(store_name, mode, 0640, DB_BTREE, &btree_info);
|
if ((err = mdb_env_open(btree_env, store_name, MDB_NOSUBDIR | MDB_NOSYNC,
|
||||||
btree_DB = dbopen(store_name, mode, 0640, DB_BTREE, NULL);
|
0640)))
|
||||||
|
throw(stringException(mdb_strerror(err)));
|
||||||
|
|
||||||
if ( btree_DB == 0 )
|
txn = txn_begin();
|
||||||
throw(stringException("btree dbopen failed"));
|
|
||||||
|
if ((err = mdb_dbi_open(txn, NULL, 0, &btree_DB))) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw(stringException(mdb_strerror(err)));
|
||||||
|
}
|
||||||
|
|
||||||
|
txn_commit(txn);
|
||||||
}
|
}
|
||||||
|
|
||||||
btree::~btree()
|
btree::~btree()
|
||||||
{
|
{
|
||||||
if ( btree_DB->sync(btree_DB, 0) == RET_ERROR ) {
|
int err;
|
||||||
cerr << "btree sync failed";
|
|
||||||
|
if ((err = mdb_env_sync(btree_env, 0))) {
|
||||||
|
cerr << mdb_strerror(err);
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( btree_DB->close(btree_DB) == RET_ERROR ) {
|
mdb_dbi_close(btree_env, btree_DB);
|
||||||
cerr << "btree close failed";
|
mdb_env_close(btree_env);
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void btree::clean()
|
void btree::clean()
|
||||||
|
@ -97,13 +98,13 @@ void btree::data_t_2_DBT(data_t& w)
|
||||||
{
|
{
|
||||||
switch (w.flag) {
|
switch (w.flag) {
|
||||||
case data_t::INT:
|
case data_t::INT:
|
||||||
key_DBT.data = &w.key.int_key;
|
key_DBT.mv_data = &w.key.int_key;
|
||||||
key_DBT.size = sizeof(w.key.int_key);
|
key_DBT.mv_size = sizeof(w.key.int_key);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case data_t::STRING:
|
case data_t::STRING:
|
||||||
key_DBT.data = w.key.str_key;
|
key_DBT.mv_data = w.key.str_key;
|
||||||
key_DBT.size = strlen(w.key.str_key);
|
key_DBT.mv_size = strlen(w.key.str_key);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case data_t::VOID:
|
case data_t::VOID:
|
||||||
|
@ -113,74 +114,78 @@ void btree::data_t_2_DBT(data_t& w)
|
||||||
|
|
||||||
Boolean btree::insert(data_t& w)
|
Boolean btree::insert(data_t& w)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
MDB_txn *txn;
|
||||||
|
|
||||||
data_t_2_DBT(w);
|
data_t_2_DBT(w);
|
||||||
|
|
||||||
DBT data_DBT;
|
MDB_val data_DBT;
|
||||||
data_DBT.data = &w.dt;
|
data_DBT.mv_data = &w.dt;
|
||||||
data_DBT.size = sizeof(w.dt);
|
data_DBT.mv_size = sizeof(w.dt);
|
||||||
|
|
||||||
//int status = btree_DB->put(btree_DB, &key_DBT, &data_DBT, R_NOOVERWRITE);
|
txn = txn_begin();
|
||||||
int status = btree_DB->put(btree_DB, &key_DBT, &data_DBT, 0);
|
|
||||||
|
|
||||||
switch (status) {
|
err = mdb_put(txn, btree_DB, &key_DBT, &data_DBT, 0);
|
||||||
case RET_ERROR:
|
|
||||||
throw(stringException("btree put failed"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RET_SPECIAL:
|
if (err && err != MDB_MAP_FULL && err != MDB_TXN_FULL) {
|
||||||
throw(stringException("btree put: dup key"));
|
mdb_txn_abort(txn);
|
||||||
break;
|
throw(stringException(mdb_strerror(err)));
|
||||||
|
|
||||||
case RET_SUCCESS:
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
txn_commit(txn);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
cerr << mdb_strerror(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Boolean btree::remove(data_t& w)
|
Boolean btree::remove(data_t& w)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
MDB_txn *txn;
|
||||||
|
|
||||||
data_t_2_DBT(w);
|
data_t_2_DBT(w);
|
||||||
|
|
||||||
int status = btree_DB->del(btree_DB, &key_DBT, 0);
|
txn = txn_begin();
|
||||||
|
|
||||||
switch (status) {
|
if ((err = mdb_del(txn, btree_DB, &key_DBT, NULL))) {
|
||||||
case RET_ERROR:
|
mdb_txn_abort(txn);
|
||||||
throw(stringException("btree delete failed"));
|
throw(stringException(mdb_strerror(err)));
|
||||||
break;
|
|
||||||
|
|
||||||
case RET_SPECIAL:
|
|
||||||
case RET_SUCCESS:
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
txn_commit(txn);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Boolean btree::member(data_t& w)
|
Boolean btree::member(data_t& w)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
MDB_txn *txn;
|
||||||
|
|
||||||
data_t_2_DBT(w);
|
data_t_2_DBT(w);
|
||||||
DBT data_DBT;
|
MDB_val data_DBT;
|
||||||
|
|
||||||
int status = btree_DB->get(btree_DB, &key_DBT, &data_DBT, 0);
|
txn = txn_begin(MDB_RDONLY);
|
||||||
|
|
||||||
switch (status) {
|
err = mdb_get(txn, btree_DB, &key_DBT, &data_DBT);
|
||||||
case RET_ERROR:
|
|
||||||
throw(stringException("btree get failed"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RET_SPECIAL:
|
mdb_txn_abort(txn);
|
||||||
return false;
|
|
||||||
|
|
||||||
case RET_SUCCESS:
|
if (err) {
|
||||||
if ( data_DBT.size != sizeof(w.dt) )
|
if (err != MDB_NOTFOUND) throw(stringException(mdb_strerror(err)));
|
||||||
throw(stringException("btree get: tree corrupted"));
|
return false;
|
||||||
|
|
||||||
memcpy((char*)&w.dt, data_DBT.data, data_DBT.size);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (data_DBT.mv_size != sizeof(w.dt))
|
||||||
|
throw(stringException("btree get: tree corrupted"));
|
||||||
|
|
||||||
|
memcpy((char*)&w.dt, data_DBT.mv_data, data_DBT.mv_size);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream& btree::asciiOut(ostream& out)
|
ostream& btree::asciiOut(ostream& out)
|
||||||
|
@ -193,3 +198,19 @@ istream& btree::asciiIn(istream& in)
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MDB_txn *btree::txn_begin(unsigned int flags) {
|
||||||
|
int err;
|
||||||
|
MDB_txn *txn;
|
||||||
|
|
||||||
|
if ((err = mdb_txn_begin(btree_env, NULL, flags, &txn)))
|
||||||
|
throw(stringException(mdb_strerror(err)));
|
||||||
|
|
||||||
|
return txn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btree::txn_commit(MDB_txn *txn) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if ((err = mdb_txn_commit(txn)))
|
||||||
|
throw(stringException(mdb_strerror(err)));
|
||||||
|
}
|
|
@ -69,9 +69,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <lmdb.h>
|
||||||
|
|
||||||
#include "dstr/index_agent.h"
|
#include "dstr/index_agent.h"
|
||||||
#include "btree_berkeley/db.h"
|
|
||||||
|
|
||||||
|
|
||||||
class btree : public index_agent
|
class btree : public index_agent
|
||||||
|
@ -91,12 +91,14 @@ public:
|
||||||
istream& asciiIn(istream& in);
|
istream& asciiIn(istream& in);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DBT key_DBT;
|
MDB_val key_DBT;
|
||||||
DB* btree_DB;
|
MDB_dbi btree_DB;
|
||||||
BTREEINFO btree_info;
|
MDB_env *btree_env;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void data_t_2_DBT(data_t& w);
|
void data_t_2_DBT(data_t& w);
|
||||||
|
MDB_txn *txn_begin(unsigned int flags = 0);
|
||||||
|
void txn_commit(MDB_txn *txn);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,16 +0,0 @@
|
||||||
MAINTAINERCLEANFILES = Makefile.in
|
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libbtree_berkeley.la
|
|
||||||
|
|
||||||
libbtree_berkeley_la_CFLAGS = -DMEMMOVE -I..
|
|
||||||
|
|
||||||
libbtree_berkeley_la_SOURCES = bt_close.c bt_conv.c bt_debug.c bt_delete.c \
|
|
||||||
bt_get.c bt_open.c bt_overflow.c bt_page.c \
|
|
||||||
bt_put.c bt_search.c bt_seq.c bt_split.c \
|
|
||||||
bt_stack.c bt_utils.c mktemp.c \
|
|
||||||
realloc.c snprintf.c mpool.c db.c
|
|
||||||
|
|
||||||
if AIX
|
|
||||||
else
|
|
||||||
libbtree_berkeley_la_SOURCES += memmove.c
|
|
||||||
endif
|
|
|
@ -1,227 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_close.c /main/4 1996/06/11 17:12:14 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_close.c 8.2 (Berkeley) 9/7/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
static int bt_meta __P((BTREE *));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_CLOSE -- Close a btree.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* dbp: pointer to access method
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_close(DB *dbp)
|
|
||||||
{
|
|
||||||
BTREE *t;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
|
|
||||||
/* Toss any page pinned across calls. */
|
|
||||||
if (t->bt_pinned != NULL) {
|
|
||||||
mpool_put(t->bt_mp, t->bt_pinned, 0);
|
|
||||||
t->bt_pinned = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete any already deleted record that we've been saving
|
|
||||||
* because the cursor pointed to it.
|
|
||||||
*/
|
|
||||||
if (ISSET(t, B_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor))
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
if (__bt_sync(dbp, 0) == RET_ERROR)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
if (mpool_close(t->bt_mp) == RET_ERROR)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
if (t->bt_stack)
|
|
||||||
free(t->bt_stack);
|
|
||||||
if (t->bt_kbuf)
|
|
||||||
free(t->bt_kbuf);
|
|
||||||
if (t->bt_dbuf)
|
|
||||||
free(t->bt_dbuf);
|
|
||||||
|
|
||||||
fd = t->bt_fd;
|
|
||||||
free(t);
|
|
||||||
free(dbp);
|
|
||||||
return (close(fd) ? RET_ERROR : RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_SYNC -- sync the btree to disk.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* dbp: pointer to access method
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_SUCCESS, RET_ERROR.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_sync(const DB *dbp, u_int flags)
|
|
||||||
{
|
|
||||||
BTREE *t;
|
|
||||||
int status;
|
|
||||||
PAGE *h;
|
|
||||||
void *p = NULL;
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
|
|
||||||
/* Toss any page pinned across calls. */
|
|
||||||
if (t->bt_pinned != NULL) {
|
|
||||||
mpool_put(t->bt_mp, t->bt_pinned, 0);
|
|
||||||
t->bt_pinned = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sync doesn't currently take any flags. */
|
|
||||||
if (flags != 0) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ISSET(t, B_INMEM | B_RDONLY) || !ISSET(t, B_MODIFIED))
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
|
|
||||||
if (ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Nastiness. If the cursor has been marked for deletion, but not
|
|
||||||
* actually deleted, we have to make a copy of the page, delete the
|
|
||||||
* key/data item, sync the file, and then restore the original page
|
|
||||||
* contents.
|
|
||||||
*/
|
|
||||||
if (ISSET(t, B_DELCRSR)) {
|
|
||||||
if ((p = (void*)malloc(t->bt_psize)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL) {
|
|
||||||
free(p);
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
memmove(p, h, t->bt_psize);
|
|
||||||
if ((status =
|
|
||||||
__bt_dleaf(t, h, t->bt_bcursor.index)) == RET_ERROR)
|
|
||||||
goto ecrsr;
|
|
||||||
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
|
|
||||||
CLR(t, B_MODIFIED);
|
|
||||||
|
|
||||||
ecrsr: if (ISSET(t, B_DELCRSR)) {
|
|
||||||
if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL) {
|
|
||||||
free(p);
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
memmove(h, p, t->bt_psize);
|
|
||||||
free(p);
|
|
||||||
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
|
|
||||||
}
|
|
||||||
return (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_META -- write the tree meta data to disk.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
bt_meta(BTREE *t)
|
|
||||||
{
|
|
||||||
BTMETA m;
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
/* Fill in metadata. */
|
|
||||||
m.m_magic = BTREEMAGIC;
|
|
||||||
m.m_version = BTREEVERSION;
|
|
||||||
m.m_psize = t->bt_psize;
|
|
||||||
m.m_free = t->bt_free;
|
|
||||||
m.m_nrecs = t->bt_nrecs;
|
|
||||||
m.m_flags = t->bt_flags & SAVEMETA;
|
|
||||||
|
|
||||||
memmove(p, &m, sizeof(BTMETA));
|
|
||||||
mpool_put(t->bt_mp, p, MPOOL_DIRTY);
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
|
@ -1,237 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_conv.c /main/3 1996/06/11 17:12:19 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_conv.c 8.1 (Berkeley) 6/4/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
static void mswap __P((PAGE *));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_BPGIN, __BT_BPGOUT --
|
|
||||||
* Convert host-specific number layout to/from the host-independent
|
|
||||||
* format stored on disk.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* pg: page number
|
|
||||||
* h: page to convert
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
__bt_pgin(void *t, pgno_t pg, void *pp)
|
|
||||||
{
|
|
||||||
PAGE *h;
|
|
||||||
int i, top;
|
|
||||||
u_char flags;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (!ISSET(((BTREE *)t), B_NEEDSWAP))
|
|
||||||
return;
|
|
||||||
if (pg == P_META) {
|
|
||||||
mswap(pp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
h = pp;
|
|
||||||
BLSWAP(h->pgno);
|
|
||||||
BLSWAP(h->prevpg);
|
|
||||||
BLSWAP(h->nextpg);
|
|
||||||
BLSWAP(h->flags);
|
|
||||||
BSSWAP(h->lower);
|
|
||||||
BSSWAP(h->upper);
|
|
||||||
|
|
||||||
top = NEXTINDEX(h);
|
|
||||||
if ((h->flags & P_TYPE) == P_BINTERNAL)
|
|
||||||
for (i = 0; i < top; i++) {
|
|
||||||
BSSWAP(h->linp[i]);
|
|
||||||
p = (char *)GETBINTERNAL(h, i);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(size_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(pgno_t);
|
|
||||||
if (*(u_char *)p & P_BIGKEY) {
|
|
||||||
p += sizeof(u_char);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(pgno_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((h->flags & P_TYPE) == P_BLEAF)
|
|
||||||
for (i = 0; i < top; i++) {
|
|
||||||
BSSWAP(h->linp[i]);
|
|
||||||
p = (char *)GETBLEAF(h, i);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(size_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(size_t);
|
|
||||||
flags = *(u_char *)p;
|
|
||||||
if (flags & (P_BIGKEY | P_BIGDATA)) {
|
|
||||||
p += sizeof(u_char);
|
|
||||||
if (flags & P_BIGKEY) {
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(pgno_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
}
|
|
||||||
if (flags & P_BIGDATA) {
|
|
||||||
p += sizeof(size_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(pgno_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
__bt_pgout(void *t, pgno_t pg, void *pp)
|
|
||||||
{
|
|
||||||
PAGE *h;
|
|
||||||
int i, top;
|
|
||||||
u_char flags;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (!ISSET(((BTREE *)t), B_NEEDSWAP))
|
|
||||||
return;
|
|
||||||
if (pg == P_META) {
|
|
||||||
mswap(pp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
h = pp;
|
|
||||||
top = NEXTINDEX(h);
|
|
||||||
if ((h->flags & P_TYPE) == P_BINTERNAL)
|
|
||||||
for (i = 0; i < top; i++) {
|
|
||||||
p = (char *)GETBINTERNAL(h, i);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(size_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(pgno_t);
|
|
||||||
if (*(u_char *)p & P_BIGKEY) {
|
|
||||||
p += sizeof(u_char);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(pgno_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
}
|
|
||||||
BSSWAP(h->linp[i]);
|
|
||||||
}
|
|
||||||
else if ((h->flags & P_TYPE) == P_BLEAF)
|
|
||||||
for (i = 0; i < top; i++) {
|
|
||||||
p = (char *)GETBLEAF(h, i);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(size_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(size_t);
|
|
||||||
flags = *(u_char *)p;
|
|
||||||
if (flags & (P_BIGKEY | P_BIGDATA)) {
|
|
||||||
p += sizeof(u_char);
|
|
||||||
if (flags & P_BIGKEY) {
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(pgno_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
}
|
|
||||||
if (flags & P_BIGDATA) {
|
|
||||||
p += sizeof(size_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
p += sizeof(pgno_t);
|
|
||||||
BLPSWAP(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BSSWAP(h->linp[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
BLSWAP(h->pgno);
|
|
||||||
BLSWAP(h->prevpg);
|
|
||||||
BLSWAP(h->nextpg);
|
|
||||||
BLSWAP(h->flags);
|
|
||||||
BSSWAP(h->lower);
|
|
||||||
BSSWAP(h->upper);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MSWAP -- Actually swap the bytes on the meta page.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* p: page to convert
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
mswap(PAGE *pg)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
p = (char *)pg;
|
|
||||||
BLPSWAP(p); /* m_magic */
|
|
||||||
p += sizeof(u_long);
|
|
||||||
BLPSWAP(p); /* m_version */
|
|
||||||
p += sizeof(u_long);
|
|
||||||
BLPSWAP(p); /* m_psize */
|
|
||||||
p += sizeof(u_long);
|
|
||||||
BLPSWAP(p); /* m_free */
|
|
||||||
p += sizeof(u_long);
|
|
||||||
BLPSWAP(p); /* m_nrecs */
|
|
||||||
p += sizeof(u_long);
|
|
||||||
BLPSWAP(p); /* m_flags */
|
|
||||||
p += sizeof(u_long);
|
|
||||||
}
|
|
|
@ -1,355 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_debug.c /main/4 1996/10/04 09:54:32 drk $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_debug.c 8.1 (Berkeley) 6/4/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
/*
|
|
||||||
* BT_DUMP -- Dump the tree
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* dbp: pointer to the DB
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
__bt_dump(dbp)
|
|
||||||
DB *dbp;
|
|
||||||
{
|
|
||||||
BTREE *t;
|
|
||||||
PAGE *h;
|
|
||||||
pgno_t i;
|
|
||||||
char *sep;
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
(void)fprintf(stderr, "%s: pgsz %ld",
|
|
||||||
ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize);
|
|
||||||
if (ISSET(t, R_RECNO))
|
|
||||||
(void)fprintf(stderr, " keys %lu", t->bt_nrecs);
|
|
||||||
#undef X
|
|
||||||
#define X(flag, name) \
|
|
||||||
if (ISSET(t, flag)) { \
|
|
||||||
(void)fprintf(stderr, "%s%s", sep, name); \
|
|
||||||
sep = ", "; \
|
|
||||||
}
|
|
||||||
if (t->bt_flags) {
|
|
||||||
sep = " flags (";
|
|
||||||
X(B_DELCRSR, "DELCRSR");
|
|
||||||
X(R_FIXLEN, "FIXLEN");
|
|
||||||
X(B_INMEM, "INMEM");
|
|
||||||
X(B_NODUPS, "NODUPS");
|
|
||||||
X(B_RDONLY, "RDONLY");
|
|
||||||
X(R_RECNO, "RECNO");
|
|
||||||
X(B_SEQINIT, "SEQINIT");
|
|
||||||
X(B_METADIRTY,"METADIRTY");
|
|
||||||
(void)fprintf(stderr, ")\n");
|
|
||||||
}
|
|
||||||
#undef X
|
|
||||||
|
|
||||||
for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
|
|
||||||
__bt_dpage(h);
|
|
||||||
(void)mpool_put(t->bt_mp, h, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_DMPAGE -- Dump the meta page
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* h: pointer to the PAGE
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
__bt_dmpage(h)
|
|
||||||
PAGE *h;
|
|
||||||
{
|
|
||||||
BTMETA *m;
|
|
||||||
char *sep;
|
|
||||||
|
|
||||||
m = (BTMETA *)h;
|
|
||||||
(void)fprintf(stderr, "magic %lx\n", m->m_magic);
|
|
||||||
(void)fprintf(stderr, "version %lu\n", m->m_version);
|
|
||||||
(void)fprintf(stderr, "psize %lu\n", m->m_psize);
|
|
||||||
(void)fprintf(stderr, "free %lu\n", m->m_free);
|
|
||||||
(void)fprintf(stderr, "nrecs %lu\n", m->m_nrecs);
|
|
||||||
(void)fprintf(stderr, "flags %lu", m->m_flags);
|
|
||||||
#undef X
|
|
||||||
#define X(flag, name) \
|
|
||||||
if (m->m_flags & flag) { \
|
|
||||||
(void)fprintf(stderr, "%s%s", sep, name); \
|
|
||||||
sep = ", "; \
|
|
||||||
}
|
|
||||||
if (m->m_flags) {
|
|
||||||
sep = " (";
|
|
||||||
X(B_NODUPS, "NODUPS");
|
|
||||||
X(R_RECNO, "RECNO");
|
|
||||||
(void)fprintf(stderr, ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_DNPAGE -- Dump the page
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* n: page number to dump.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
__bt_dnpage(dbp, pgno)
|
|
||||||
DB *dbp;
|
|
||||||
pgno_t pgno;
|
|
||||||
{
|
|
||||||
BTREE *t;
|
|
||||||
PAGE *h;
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) {
|
|
||||||
__bt_dpage(h);
|
|
||||||
(void)mpool_put(t->bt_mp, h, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_DPAGE -- Dump the page
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* h: pointer to the PAGE
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
__bt_dpage(h)
|
|
||||||
PAGE *h;
|
|
||||||
{
|
|
||||||
BINTERNAL *bi;
|
|
||||||
BLEAF *bl;
|
|
||||||
RINTERNAL *ri;
|
|
||||||
RLEAF *rl;
|
|
||||||
indx_t cur, top;
|
|
||||||
char *sep;
|
|
||||||
|
|
||||||
(void)fprintf(stderr, " page %ld: (", h->pgno);
|
|
||||||
#undef X
|
|
||||||
#define X(flag, name) \
|
|
||||||
if (h->flags & flag) { \
|
|
||||||
(void)fprintf(stderr, "%s%s", sep, name); \
|
|
||||||
sep = ", "; \
|
|
||||||
}
|
|
||||||
sep = "";
|
|
||||||
X(P_BINTERNAL, "BINTERNAL") /* types */
|
|
||||||
X(P_BLEAF, "BLEAF")
|
|
||||||
X(P_RINTERNAL, "RINTERNAL") /* types */
|
|
||||||
X(P_RLEAF, "RLEAF")
|
|
||||||
X(P_OVERFLOW, "OVERFLOW")
|
|
||||||
X(P_PRESERVE, "PRESERVE");
|
|
||||||
(void)fprintf(stderr, ")\n");
|
|
||||||
#undef X
|
|
||||||
|
|
||||||
(void)fprintf(stderr, "\tprev %2ld next %2ld", h->prevpg, h->nextpg);
|
|
||||||
if (h->flags & P_OVERFLOW)
|
|
||||||
return;
|
|
||||||
|
|
||||||
top = NEXTINDEX(h);
|
|
||||||
(void)fprintf(stderr, " lower %3d upper %3d nextind %d\n",
|
|
||||||
h->lower, h->upper, top);
|
|
||||||
for (cur = 0; cur < top; cur++) {
|
|
||||||
(void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]);
|
|
||||||
switch(h->flags & P_TYPE) {
|
|
||||||
case P_BINTERNAL:
|
|
||||||
bi = GETBINTERNAL(h, cur);
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"size %03ld pgno %03ld", (long)bi->ksize, bi->pgno);
|
|
||||||
if (bi->flags & P_BIGKEY)
|
|
||||||
(void)fprintf(stderr, " (indirect)");
|
|
||||||
else if (bi->ksize)
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
" {%.*s}", (int)bi->ksize, bi->bytes);
|
|
||||||
break;
|
|
||||||
case P_RINTERNAL:
|
|
||||||
ri = GETRINTERNAL(h, cur);
|
|
||||||
(void)fprintf(stderr, "entries %03ld pgno %03ld",
|
|
||||||
ri->nrecs, ri->pgno);
|
|
||||||
break;
|
|
||||||
case P_BLEAF:
|
|
||||||
bl = GETBLEAF(h, cur);
|
|
||||||
if (bl->flags & P_BIGKEY)
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"big key page %lu size %lu/",
|
|
||||||
*(pgno_t *)bl->bytes,
|
|
||||||
(long)*(size_t *)(bl->bytes + sizeof(pgno_t)));
|
|
||||||
else if (bl->ksize)
|
|
||||||
(void)fprintf(stderr, "%s/", bl->bytes);
|
|
||||||
if (bl->flags & P_BIGDATA)
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"big data page %lu size %lu",
|
|
||||||
*(pgno_t *)(bl->bytes + bl->ksize),
|
|
||||||
(long)*(size_t *)(bl->bytes + bl->ksize +
|
|
||||||
sizeof(pgno_t)));
|
|
||||||
else if (bl->dsize)
|
|
||||||
(void)fprintf(stderr, "%.*s",
|
|
||||||
(int)bl->dsize, bl->bytes + bl->ksize);
|
|
||||||
break;
|
|
||||||
case P_RLEAF:
|
|
||||||
rl = GETRLEAF(h, cur);
|
|
||||||
if (rl->flags & P_BIGDATA)
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"big data page %lu size %lu",
|
|
||||||
*(pgno_t *)rl->bytes,
|
|
||||||
(long)*(size_t *)(rl->bytes + sizeof(pgno_t)));
|
|
||||||
else if (rl->dsize)
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"%.*s", (int)rl->dsize, rl->bytes);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
(void)fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
/*
|
|
||||||
* BT_STAT -- Gather/print the tree statistics
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* dbp: pointer to the DB
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
__bt_stat(dbp)
|
|
||||||
DB *dbp;
|
|
||||||
{
|
|
||||||
extern u_long bt_cache_hit, bt_cache_miss;
|
|
||||||
extern u_long bt_rootsplit, bt_split, bt_sortsplit;
|
|
||||||
extern u_long bt_pfxsaved;
|
|
||||||
BTREE *t;
|
|
||||||
PAGE *h;
|
|
||||||
pgno_t i, pcont, pinternal, pleaf;
|
|
||||||
u_long ifree, lfree, nkeys;
|
|
||||||
int levels;
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
pcont = pinternal = pleaf = 0;
|
|
||||||
nkeys = ifree = lfree = 0;
|
|
||||||
for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
|
|
||||||
switch(h->flags & P_TYPE) {
|
|
||||||
case P_BINTERNAL:
|
|
||||||
case P_RINTERNAL:
|
|
||||||
++pinternal;
|
|
||||||
ifree += h->upper - h->lower;
|
|
||||||
break;
|
|
||||||
case P_BLEAF:
|
|
||||||
case P_RLEAF:
|
|
||||||
++pleaf;
|
|
||||||
lfree += h->upper - h->lower;
|
|
||||||
nkeys += NEXTINDEX(h);
|
|
||||||
break;
|
|
||||||
case P_OVERFLOW:
|
|
||||||
++pcont;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
(void)mpool_put(t->bt_mp, h, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Count the levels of the tree. */
|
|
||||||
for (i = P_ROOT, levels = 0 ;; ++levels) {
|
|
||||||
h = mpool_get(t->bt_mp, i, 0);
|
|
||||||
if (h->flags & (P_BLEAF|P_RLEAF)) {
|
|
||||||
if (levels == 0)
|
|
||||||
levels = 1;
|
|
||||||
(void)mpool_put(t->bt_mp, h, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i = ISSET(t, R_RECNO) ?
|
|
||||||
GETRINTERNAL(h, 0)->pgno :
|
|
||||||
GETBINTERNAL(h, 0)->pgno;
|
|
||||||
(void)mpool_put(t->bt_mp, h, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)fprintf(stderr, "%d level%s with %ld keys",
|
|
||||||
levels, levels == 1 ? "" : "s", nkeys);
|
|
||||||
if (ISSET(t, R_RECNO))
|
|
||||||
(void)fprintf(stderr, " (%ld header count)", t->bt_nrecs);
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n",
|
|
||||||
pinternal + pleaf + pcont, pleaf, pinternal, pcont);
|
|
||||||
(void)fprintf(stderr, "%ld cache hits, %ld cache misses\n",
|
|
||||||
bt_cache_hit, bt_cache_miss);
|
|
||||||
(void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n",
|
|
||||||
bt_split, bt_rootsplit, bt_sortsplit);
|
|
||||||
pleaf *= t->bt_psize - BTDATAOFF;
|
|
||||||
if (pleaf)
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n",
|
|
||||||
((double)(pleaf - lfree) / pleaf) * 100,
|
|
||||||
pleaf - lfree, lfree);
|
|
||||||
pinternal *= t->bt_psize - BTDATAOFF;
|
|
||||||
if (pinternal)
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"%.0f%% internal fill (%ld bytes used, %ld bytes free\n",
|
|
||||||
((double)(pinternal - ifree) / pinternal) * 100,
|
|
||||||
pinternal - ifree, ifree);
|
|
||||||
if (bt_pfxsaved)
|
|
||||||
(void)fprintf(stderr, "prefix checking removed %lu bytes.\n",
|
|
||||||
bt_pfxsaved);
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,340 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_delete.c /main/3 1996/06/11 17:12:29 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_delete.c 8.2 (Berkeley) 9/7/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
static int bt_bdelete __P((BTREE *, const DBT *));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_DELETE -- Delete the item(s) referenced by a key.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* dbp: pointer to access method
|
|
||||||
* key: key to delete
|
|
||||||
* flags: R_CURSOR if deleting what the cursor references
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_delete(const DB *dbp, const DBT *key, u_int flags)
|
|
||||||
{
|
|
||||||
BTREE *t;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
|
|
||||||
/* Toss any page pinned across calls. */
|
|
||||||
if (t->bt_pinned != NULL) {
|
|
||||||
mpool_put(t->bt_mp, t->bt_pinned, 0);
|
|
||||||
t->bt_pinned = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ISSET(t, B_RDONLY)) {
|
|
||||||
errno = EPERM;
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(flags) {
|
|
||||||
case 0:
|
|
||||||
status = bt_bdelete(t, key);
|
|
||||||
break;
|
|
||||||
case R_CURSOR:
|
|
||||||
/*
|
|
||||||
* If flags is R_CURSOR, delete the cursor; must already have
|
|
||||||
* started a scan and not have already deleted the record. For
|
|
||||||
* the delete cursor bit to have been set requires that the
|
|
||||||
* scan be initialized, so no reason to check.
|
|
||||||
*/
|
|
||||||
if (!ISSET(t, B_SEQINIT))
|
|
||||||
goto einval;
|
|
||||||
status = ISSET(t, B_DELCRSR) ?
|
|
||||||
RET_SPECIAL : __bt_crsrdel(t, &t->bt_bcursor);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
einval: errno = EINVAL;
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
if (status == RET_SUCCESS)
|
|
||||||
SET(t, B_MODIFIED);
|
|
||||||
return (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_BDELETE -- Delete all key/data pairs matching the specified key.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* tree: tree
|
|
||||||
* key: key to delete
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
bt_bdelete(BTREE *t, const DBT *key)
|
|
||||||
{
|
|
||||||
EPG *e, save;
|
|
||||||
PAGE *h;
|
|
||||||
pgno_t cpgno, pg;
|
|
||||||
indx_t cindex;
|
|
||||||
int deleted, dirty1, dirty2, exact;
|
|
||||||
|
|
||||||
/* Find any matching record; __bt_search pins the page. */
|
|
||||||
if ((e = __bt_search(t, key, &exact)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
if (!exact) {
|
|
||||||
mpool_put(t->bt_mp, e->page, 0);
|
|
||||||
return (RET_SPECIAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete forward, then delete backward, from the found key. The
|
|
||||||
* ordering is so that the deletions don't mess up the page refs.
|
|
||||||
* The first loop deletes the key from the original page, the second
|
|
||||||
* unpins the original page. In the first loop, dirty1 is set if
|
|
||||||
* the original page is modified, and dirty2 is set if any subsequent
|
|
||||||
* pages are modified. In the second loop, dirty1 starts off set if
|
|
||||||
* the original page has been modified, and is set if any subsequent
|
|
||||||
* pages are modified.
|
|
||||||
*
|
|
||||||
* If find the key referenced by the cursor, don't delete it, just
|
|
||||||
* flag it for future deletion. The cursor page number is P_INVALID
|
|
||||||
* unless the sequential scan is initialized, so no reason to check.
|
|
||||||
* A special case is when the already deleted cursor record was the
|
|
||||||
* only record found. If so, then the delete opertion fails as no
|
|
||||||
* records were deleted.
|
|
||||||
*
|
|
||||||
* Cycle in place in the current page until the current record doesn't
|
|
||||||
* match the key or the page is empty. If the latter, walk forward,
|
|
||||||
* skipping empty pages and repeating until a record doesn't match
|
|
||||||
* the key or the end of the tree is reached.
|
|
||||||
*/
|
|
||||||
cpgno = t->bt_bcursor.pgno;
|
|
||||||
cindex = t->bt_bcursor.index;
|
|
||||||
save = *e;
|
|
||||||
dirty1 = 0;
|
|
||||||
for (h = e->page, deleted = 0;;) {
|
|
||||||
dirty2 = 0;
|
|
||||||
do {
|
|
||||||
if (h->pgno == cpgno && e->index == cindex) {
|
|
||||||
if (!ISSET(t, B_DELCRSR)) {
|
|
||||||
SET(t, B_DELCRSR);
|
|
||||||
deleted = 1;
|
|
||||||
}
|
|
||||||
++e->index;
|
|
||||||
} else {
|
|
||||||
if (__bt_dleaf(t, h, e->index)) {
|
|
||||||
if (h->pgno != save.page->pgno)
|
|
||||||
mpool_put(t->bt_mp, h, dirty2);
|
|
||||||
mpool_put(t->bt_mp, save.page, dirty1);
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
if (h->pgno == save.page->pgno)
|
|
||||||
dirty1 = MPOOL_DIRTY;
|
|
||||||
else
|
|
||||||
dirty2 = MPOOL_DIRTY;
|
|
||||||
deleted = 1;
|
|
||||||
}
|
|
||||||
} while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Quit if didn't find a match, no next page, or first key on
|
|
||||||
* the next page doesn't match. Don't unpin the original page
|
|
||||||
* unless an error occurs.
|
|
||||||
*/
|
|
||||||
if (e->index < NEXTINDEX(h))
|
|
||||||
break;
|
|
||||||
for (;;) {
|
|
||||||
if ((pg = h->nextpg) == P_INVALID)
|
|
||||||
goto done1;
|
|
||||||
if (h->pgno != save.page->pgno)
|
|
||||||
mpool_put(t->bt_mp, h, dirty2);
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) {
|
|
||||||
mpool_put(t->bt_mp, save.page, dirty1);
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
if (NEXTINDEX(h) != 0) {
|
|
||||||
e->page = h;
|
|
||||||
e->index = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__bt_cmp(t, key, e) != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reach here with the original page and the last page referenced
|
|
||||||
* pinned (they may be the same). Release it if not the original.
|
|
||||||
*/
|
|
||||||
done1: if (h->pgno != save.page->pgno)
|
|
||||||
mpool_put(t->bt_mp, h, dirty2);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Walk backwards from the record previous to the record returned by
|
|
||||||
* __bt_search, skipping empty pages, until a record doesn't match
|
|
||||||
* the key or reach the beginning of the tree.
|
|
||||||
*/
|
|
||||||
*e = save;
|
|
||||||
for (;;) {
|
|
||||||
if (e->index)
|
|
||||||
--e->index;
|
|
||||||
for (h = e->page; e->index; --e->index) {
|
|
||||||
if (__bt_cmp(t, key, e) != 0)
|
|
||||||
goto done2;
|
|
||||||
if (h->pgno == cpgno && e->index == cindex) {
|
|
||||||
if (!ISSET(t, B_DELCRSR)) {
|
|
||||||
SET(t, B_DELCRSR);
|
|
||||||
deleted = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (__bt_dleaf(t, h, e->index) == RET_ERROR) {
|
|
||||||
mpool_put(t->bt_mp, h, dirty1);
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
if (h->pgno == save.page->pgno)
|
|
||||||
dirty1 = MPOOL_DIRTY;
|
|
||||||
deleted = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pg = h->prevpg) == P_INVALID)
|
|
||||||
goto done2;
|
|
||||||
mpool_put(t->bt_mp, h, dirty1);
|
|
||||||
dirty1 = 0;
|
|
||||||
if ((e->page = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
e->index = NEXTINDEX(e->page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reach here with the last page that was looked at pinned. Release
|
|
||||||
* it.
|
|
||||||
*/
|
|
||||||
done2: mpool_put(t->bt_mp, h, dirty1);
|
|
||||||
return (deleted ? RET_SUCCESS : RET_SPECIAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_DLEAF -- Delete a single record from a leaf page.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* index: index on current page to delete
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_SUCCESS, RET_ERROR.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_dleaf(BTREE *t, PAGE *h, int index)
|
|
||||||
{
|
|
||||||
BLEAF *bl;
|
|
||||||
indx_t *ip, offset;
|
|
||||||
size_t nbytes;
|
|
||||||
int cnt;
|
|
||||||
char *from;
|
|
||||||
void *to;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete a record from a btree leaf page. Internal records are never
|
|
||||||
* deleted from internal pages, regardless of the records that caused
|
|
||||||
* them to be added being deleted. Pages made empty by deletion are
|
|
||||||
* not reclaimed. They are, however, made available for reuse.
|
|
||||||
*
|
|
||||||
* Pack the remaining entries at the end of the page, shift the indices
|
|
||||||
* down, overwriting the deleted record and its index. If the record
|
|
||||||
* uses overflow pages, make them available for reuse.
|
|
||||||
*/
|
|
||||||
to = bl = GETBLEAF(h, index);
|
|
||||||
if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
|
|
||||||
return (RET_ERROR);
|
|
||||||
if (bl->flags & P_BIGDATA &&
|
|
||||||
__ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR)
|
|
||||||
return (RET_ERROR);
|
|
||||||
nbytes = NBLEAF(bl);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compress the key/data pairs. Compress and adjust the [BR]LEAF
|
|
||||||
* offsets. Reset the headers.
|
|
||||||
*/
|
|
||||||
from = (char *)h + h->upper;
|
|
||||||
memmove(from + nbytes, from, (char *)to - from);
|
|
||||||
h->upper += nbytes;
|
|
||||||
|
|
||||||
offset = h->linp[index];
|
|
||||||
for (cnt = index, ip = &h->linp[0]; cnt--; ++ip)
|
|
||||||
if (ip[0] < offset)
|
|
||||||
ip[0] += nbytes;
|
|
||||||
for (cnt = NEXTINDEX(h) - index; --cnt; ++ip)
|
|
||||||
ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
|
|
||||||
h->lower -= sizeof(indx_t);
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
|
@ -1,254 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_get.c /main/3 1996/06/11 17:12:34 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_get.c 8.2 (Berkeley) 9/7/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_GET -- Get a record from the btree.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* dbp: pointer to access method
|
|
||||||
* key: key to find
|
|
||||||
* data: data to return
|
|
||||||
* flag: currently unused
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_get(const DB *dbp, const DBT *key, DBT *data, u_int flags)
|
|
||||||
{
|
|
||||||
BTREE *t;
|
|
||||||
EPG *e;
|
|
||||||
int exact, status;
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
|
|
||||||
/* Toss any page pinned across calls. */
|
|
||||||
if (t->bt_pinned != NULL) {
|
|
||||||
mpool_put(t->bt_mp, t->bt_pinned, 0);
|
|
||||||
t->bt_pinned = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get currently doesn't take any flags. */
|
|
||||||
if (flags) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((e = __bt_search(t, key, &exact)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
if (!exact) {
|
|
||||||
mpool_put(t->bt_mp, e->page, 0);
|
|
||||||
return (RET_SPECIAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A special case is if we found the record but it's flagged for
|
|
||||||
* deletion. In this case, we want to find another record with the
|
|
||||||
* same key, if it exists. Rather than look around the tree we call
|
|
||||||
* __bt_first and have it redo the search, as __bt_first will not
|
|
||||||
* return keys marked for deletion. Slow, but should never happen.
|
|
||||||
*/
|
|
||||||
if (ISSET(t, B_DELCRSR) && e->page->pgno == t->bt_bcursor.pgno &&
|
|
||||||
e->index == t->bt_bcursor.index) {
|
|
||||||
mpool_put(t->bt_mp, e->page, 0);
|
|
||||||
if ((e = __bt_first(t, key, &exact)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
if (!exact)
|
|
||||||
return (RET_SPECIAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = __bt_ret(t, e, NULL, data);
|
|
||||||
/*
|
|
||||||
* If the user is doing concurrent access, we copied the
|
|
||||||
* key/data, toss the page.
|
|
||||||
*/
|
|
||||||
if (ISSET(t, B_DB_LOCK))
|
|
||||||
mpool_put(t->bt_mp, e->page, 0);
|
|
||||||
else
|
|
||||||
t->bt_pinned = e->page;
|
|
||||||
return (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_FIRST -- Find the first entry.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: the tree
|
|
||||||
* key: the key
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* The first entry in the tree greater than or equal to key.
|
|
||||||
*/
|
|
||||||
EPG *
|
|
||||||
__bt_first(BTREE *t, const DBT *key, int *exactp)
|
|
||||||
{
|
|
||||||
PAGE *h;
|
|
||||||
EPG *e;
|
|
||||||
EPG save;
|
|
||||||
pgno_t cpgno, pg;
|
|
||||||
indx_t cindex;
|
|
||||||
int found;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find any matching record; __bt_search pins the page. Only exact
|
|
||||||
* matches are tricky, otherwise just return the location of the key
|
|
||||||
* if it were to be inserted into the tree.
|
|
||||||
*/
|
|
||||||
if ((e = __bt_search(t, key, exactp)) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
if (!*exactp)
|
|
||||||
return (e);
|
|
||||||
|
|
||||||
if (ISSET(t, B_DELCRSR)) {
|
|
||||||
cpgno = t->bt_bcursor.pgno;
|
|
||||||
cindex = t->bt_bcursor.index;
|
|
||||||
} else {
|
|
||||||
cpgno = P_INVALID;
|
|
||||||
cindex = 0; /* GCC thinks it's uninitialized. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Walk backwards, skipping empty pages, as long as the entry matches
|
|
||||||
* and there are keys left in the tree. Save a copy of each match in
|
|
||||||
* case we go too far. A special case is that we don't return a match
|
|
||||||
* on records that the cursor references that have already been flagged
|
|
||||||
* for deletion.
|
|
||||||
*/
|
|
||||||
save = *e;
|
|
||||||
h = e->page;
|
|
||||||
found = 0;
|
|
||||||
do {
|
|
||||||
if (cpgno != h->pgno || cindex != e->index) {
|
|
||||||
if (save.page->pgno != e->page->pgno) {
|
|
||||||
mpool_put(t->bt_mp, save.page, 0);
|
|
||||||
save = *e;
|
|
||||||
} else
|
|
||||||
save.index = e->index;
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Make a special effort not to unpin the page the last (or
|
|
||||||
* original) match was on, but also make sure it's unpinned
|
|
||||||
* if an error occurs.
|
|
||||||
*/
|
|
||||||
while (e->index == 0) {
|
|
||||||
if (h->prevpg == P_INVALID)
|
|
||||||
goto done1;
|
|
||||||
if (h->pgno != save.page->pgno)
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
if ((h = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) {
|
|
||||||
if (h->pgno == save.page->pgno)
|
|
||||||
mpool_put(t->bt_mp, save.page, 0);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
e->page = h;
|
|
||||||
e->index = NEXTINDEX(h);
|
|
||||||
}
|
|
||||||
--e->index;
|
|
||||||
} while (__bt_cmp(t, key, e) == 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reach here with the last page that was looked at pinned, which may
|
|
||||||
* or may not be the same as the last (or original) match page. If
|
|
||||||
* it's not useful, release it.
|
|
||||||
*/
|
|
||||||
done1: if (h->pgno != save.page->pgno)
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If still haven't found a record, the only possibility left is the
|
|
||||||
* next one. Move forward one slot, skipping empty pages and check.
|
|
||||||
*/
|
|
||||||
if (!found) {
|
|
||||||
h = save.page;
|
|
||||||
if (++save.index == NEXTINDEX(h)) {
|
|
||||||
do {
|
|
||||||
pg = h->nextpg;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
if (pg == P_INVALID) {
|
|
||||||
*exactp = 0;
|
|
||||||
return (e);
|
|
||||||
}
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
} while ((save.index = NEXTINDEX(h)) == 0);
|
|
||||||
save.page = h;
|
|
||||||
}
|
|
||||||
if (__bt_cmp(t, key, &save) != 0) {
|
|
||||||
*exactp = 0;
|
|
||||||
return (e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*e = save;
|
|
||||||
*exactp = 1;
|
|
||||||
return (e);
|
|
||||||
}
|
|
|
@ -1,461 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_open.c /main/3 1996/06/11 17:12:40 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_open.c 8.2 (Berkeley) 9/7/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Implementation of btree access method for 4.4BSD.
|
|
||||||
*
|
|
||||||
* The design here was originally based on that of the btree access method
|
|
||||||
* used in the Postgres database system at UC Berkeley. This implementation
|
|
||||||
* is wholly independent of the Postgres code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define __DBINTERFACE_PRIVATE
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
static int byteorder __P((void));
|
|
||||||
static int nroot __P((BTREE *));
|
|
||||||
static int tmp __P((void));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_OPEN -- Open a btree.
|
|
||||||
*
|
|
||||||
* Creates and fills a DB struct, and calls the routine that actually
|
|
||||||
* opens the btree.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* fname: filename (NULL for in-memory trees)
|
|
||||||
* flags: open flag bits
|
|
||||||
* mode: open permission bits
|
|
||||||
* b: BTREEINFO pointer
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* NULL on failure, pointer to DB on success.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
DB *
|
|
||||||
__bt_open(const char *fname, int flags, int mode, const BTREEINFO *openinfo, int dflags)
|
|
||||||
{
|
|
||||||
BTMETA m;
|
|
||||||
BTREE *t;
|
|
||||||
BTREEINFO b;
|
|
||||||
DB *dbp;
|
|
||||||
pgno_t ncache;
|
|
||||||
struct stat sb;
|
|
||||||
int machine_lorder, nr;
|
|
||||||
|
|
||||||
t = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Intention is to make sure all of the user's selections are okay
|
|
||||||
* here and then use them without checking. Can't be complete, since
|
|
||||||
* we don't know the right page size, lorder or flags until the backing
|
|
||||||
* file is opened. Also, the file's page size can cause the cachesize
|
|
||||||
* to change.
|
|
||||||
*/
|
|
||||||
machine_lorder = byteorder();
|
|
||||||
if (openinfo) {
|
|
||||||
b = *openinfo;
|
|
||||||
|
|
||||||
/* Flags: R_DUP. */
|
|
||||||
if (b.flags & ~(R_DUP))
|
|
||||||
goto einval;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Page size must be indx_t aligned and >= MINPSIZE. Default
|
|
||||||
* page size is set farther on, based on the underlying file
|
|
||||||
* transfer size.
|
|
||||||
*/
|
|
||||||
if (b.psize &&
|
|
||||||
(b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 ||
|
|
||||||
b.psize & (sizeof(indx_t) - 1)))
|
|
||||||
goto einval;
|
|
||||||
|
|
||||||
/* Minimum number of keys per page; absolute minimum is 2. */
|
|
||||||
if (b.minkeypage) {
|
|
||||||
if (b.minkeypage < 2)
|
|
||||||
goto einval;
|
|
||||||
} else
|
|
||||||
b.minkeypage = DEFMINKEYPAGE;
|
|
||||||
|
|
||||||
/* If no comparison, use default comparison and prefix. */
|
|
||||||
if (b.compare == NULL) {
|
|
||||||
b.compare = __bt_defcmp;
|
|
||||||
if (b.prefix == NULL)
|
|
||||||
b.prefix = __bt_defpfx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b.lorder == 0)
|
|
||||||
b.lorder = machine_lorder;
|
|
||||||
} else {
|
|
||||||
b.compare = __bt_defcmp;
|
|
||||||
b.cachesize = 0;
|
|
||||||
b.flags = 0;
|
|
||||||
b.lorder = machine_lorder;
|
|
||||||
b.minkeypage = DEFMINKEYPAGE;
|
|
||||||
b.prefix = __bt_defpfx;
|
|
||||||
b.psize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for the ubiquitous PDP-11. */
|
|
||||||
if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN)
|
|
||||||
goto einval;
|
|
||||||
|
|
||||||
/* Allocate and initialize DB and BTREE structures. */
|
|
||||||
if ((t = malloc(sizeof(BTREE))) == NULL)
|
|
||||||
goto err;
|
|
||||||
t->bt_fd = -1; /* Don't close unopened fd on error. */
|
|
||||||
if ((t->bt_dbp = dbp = malloc(sizeof(DB))) == NULL)
|
|
||||||
goto err;
|
|
||||||
t->bt_bcursor.pgno = P_INVALID;
|
|
||||||
t->bt_bcursor.index = 0;
|
|
||||||
t->bt_stack = NULL;
|
|
||||||
t->bt_pinned = NULL;
|
|
||||||
t->bt_sp = t->bt_maxstack = 0;
|
|
||||||
t->bt_kbuf = t->bt_dbuf = NULL;
|
|
||||||
t->bt_kbufsz = t->bt_dbufsz = 0;
|
|
||||||
t->bt_lorder = b.lorder;
|
|
||||||
t->bt_order = NOT;
|
|
||||||
t->bt_cmp = b.compare;
|
|
||||||
t->bt_pfx = b.prefix;
|
|
||||||
t->bt_flags = 0;
|
|
||||||
if (t->bt_lorder != machine_lorder)
|
|
||||||
SET(t, B_NEEDSWAP);
|
|
||||||
|
|
||||||
dbp->type = DB_BTREE;
|
|
||||||
dbp->internal = t;
|
|
||||||
dbp->close = __bt_close;
|
|
||||||
dbp->del = __bt_delete;
|
|
||||||
dbp->fd = __bt_fd;
|
|
||||||
dbp->get = __bt_get;
|
|
||||||
dbp->put = __bt_put;
|
|
||||||
dbp->seq = __bt_seq;
|
|
||||||
dbp->sync = __bt_sync;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If no file name was supplied, this is an in-memory btree and we
|
|
||||||
* open a backing temporary file. Otherwise, it's a disk-based tree.
|
|
||||||
*/
|
|
||||||
if (fname) {
|
|
||||||
switch(flags & O_ACCMODE) {
|
|
||||||
case O_RDONLY:
|
|
||||||
SET(t, B_RDONLY);
|
|
||||||
break;
|
|
||||||
case O_RDWR:
|
|
||||||
break;
|
|
||||||
case O_WRONLY:
|
|
||||||
default:
|
|
||||||
goto einval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((t->bt_fd = open(fname, flags, mode)) < 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if ((flags & O_ACCMODE) != O_RDWR)
|
|
||||||
goto einval;
|
|
||||||
if ((t->bt_fd = tmp()) == -1)
|
|
||||||
goto err;
|
|
||||||
SET(t, B_INMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fcntl(t->bt_fd, F_SETFD, 1) == -1)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (fstat(t->bt_fd, &sb))
|
|
||||||
goto err;
|
|
||||||
if (sb.st_size) {
|
|
||||||
nr = read(t->bt_fd, &m, sizeof(BTMETA));
|
|
||||||
if (nr < 0)
|
|
||||||
goto err;
|
|
||||||
if (nr != sizeof(BTMETA))
|
|
||||||
goto eftype;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read in the meta-data. This can change the notion of what
|
|
||||||
* the lorder, page size and flags are, and, when the page size
|
|
||||||
* changes, the cachesize value can change too. If the user
|
|
||||||
* specified the wrong byte order for an existing database, we
|
|
||||||
* don't bother to return an error, we just clear the NEEDSWAP
|
|
||||||
* bit.
|
|
||||||
*/
|
|
||||||
if (m.m_magic == BTREEMAGIC)
|
|
||||||
CLR(t, B_NEEDSWAP);
|
|
||||||
else {
|
|
||||||
SET(t, B_NEEDSWAP);
|
|
||||||
BLSWAP(m.m_magic);
|
|
||||||
BLSWAP(m.m_version);
|
|
||||||
BLSWAP(m.m_psize);
|
|
||||||
BLSWAP(m.m_free);
|
|
||||||
BLSWAP(m.m_nrecs);
|
|
||||||
BLSWAP(m.m_flags);
|
|
||||||
}
|
|
||||||
if (m.m_magic != BTREEMAGIC || m.m_version != BTREEVERSION)
|
|
||||||
goto eftype;
|
|
||||||
if (m.m_psize < MINPSIZE || m.m_psize > MAX_PAGE_OFFSET + 1 ||
|
|
||||||
m.m_psize & (sizeof(indx_t) - 1))
|
|
||||||
goto eftype;
|
|
||||||
if (m.m_flags & ~SAVEMETA)
|
|
||||||
goto eftype;
|
|
||||||
b.psize = m.m_psize;
|
|
||||||
t->bt_flags |= m.m_flags;
|
|
||||||
t->bt_free = m.m_free;
|
|
||||||
t->bt_nrecs = m.m_nrecs;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Set the page size to the best value for I/O to this file.
|
|
||||||
* Don't overflow the page offset type.
|
|
||||||
*/
|
|
||||||
if (b.psize == 0) {
|
|
||||||
b.psize = sb.st_blksize;
|
|
||||||
if (b.psize < MINPSIZE)
|
|
||||||
b.psize = MINPSIZE;
|
|
||||||
if (b.psize > MAX_PAGE_OFFSET + 1)
|
|
||||||
b.psize = MAX_PAGE_OFFSET + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set flag if duplicates permitted. */
|
|
||||||
if (!(b.flags & R_DUP))
|
|
||||||
SET(t, B_NODUPS);
|
|
||||||
|
|
||||||
t->bt_free = P_INVALID;
|
|
||||||
t->bt_nrecs = 0;
|
|
||||||
SET(t, B_METADIRTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
t->bt_psize = b.psize;
|
|
||||||
|
|
||||||
/* Set the cache size; must be a multiple of the page size. */
|
|
||||||
if (b.cachesize && b.cachesize & (b.psize - 1))
|
|
||||||
b.cachesize += (~b.cachesize & (b.psize - 1)) + 1;
|
|
||||||
if (b.cachesize < b.psize * MINCACHE)
|
|
||||||
b.cachesize = b.psize * MINCACHE;
|
|
||||||
|
|
||||||
/* Calculate number of pages to cache. */
|
|
||||||
ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The btree data structure requires that at least two keys can fit on
|
|
||||||
* a page, but other than that there's no fixed requirement. The user
|
|
||||||
* specified a minimum number per page, and we translated that into the
|
|
||||||
* number of bytes a key/data pair can use before being placed on an
|
|
||||||
* overflow page. This calculation includes the page header, the size
|
|
||||||
* of the index referencing the leaf item and the size of the leaf item
|
|
||||||
* structure. Also, don't let the user specify a minkeypage such that
|
|
||||||
* a key/data pair won't fit even if both key and data are on overflow
|
|
||||||
* pages.
|
|
||||||
*/
|
|
||||||
t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage -
|
|
||||||
(sizeof(indx_t) + NBLEAFDBT(0, 0));
|
|
||||||
if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t))
|
|
||||||
t->bt_ovflsize =
|
|
||||||
NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t);
|
|
||||||
|
|
||||||
/* Initialize the buffer pool. */
|
|
||||||
if ((t->bt_mp =
|
|
||||||
mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL)
|
|
||||||
goto err;
|
|
||||||
if (!ISSET(t, B_INMEM))
|
|
||||||
mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t);
|
|
||||||
|
|
||||||
/* Create a root page if new tree. */
|
|
||||||
if (nroot(t) == RET_ERROR)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
/* Global flags. */
|
|
||||||
if (dflags & DB_LOCK)
|
|
||||||
SET(t, B_DB_LOCK);
|
|
||||||
if (dflags & DB_SHMEM)
|
|
||||||
SET(t, B_DB_SHMEM);
|
|
||||||
if (dflags & DB_TXN)
|
|
||||||
SET(t, B_DB_TXN);
|
|
||||||
|
|
||||||
return (dbp);
|
|
||||||
|
|
||||||
einval: errno = EINVAL;
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
eftype: errno = EFTYPE;
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
err: if (t) {
|
|
||||||
if (t->bt_dbp)
|
|
||||||
free(t->bt_dbp);
|
|
||||||
if (t->bt_fd != -1)
|
|
||||||
(void)close(t->bt_fd);
|
|
||||||
free(t);
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NROOT -- Create the root of a new tree.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
nroot(BTREE *t)
|
|
||||||
{
|
|
||||||
PAGE *meta, *root;
|
|
||||||
pgno_t npg;
|
|
||||||
|
|
||||||
if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) {
|
|
||||||
mpool_put(t->bt_mp, meta, 0);
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
if (errno != EINVAL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
if ((meta = mpool_new(t->bt_mp, &npg)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
if ((root = mpool_new(t->bt_mp, &npg)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
if (npg != P_ROOT)
|
|
||||||
return (RET_ERROR);
|
|
||||||
root->pgno = npg;
|
|
||||||
root->prevpg = root->nextpg = P_INVALID;
|
|
||||||
root->lower = BTDATAOFF;
|
|
||||||
root->upper = t->bt_psize;
|
|
||||||
root->flags = P_BLEAF;
|
|
||||||
memset(meta, 0, t->bt_psize);
|
|
||||||
mpool_put(t->bt_mp, meta, MPOOL_DIRTY);
|
|
||||||
mpool_put(t->bt_mp, root, MPOOL_DIRTY);
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
tmp(void)
|
|
||||||
{
|
|
||||||
sigset_t set, oset;
|
|
||||||
int fd;
|
|
||||||
char *envtmp;
|
|
||||||
char path[MAXPATHLEN];
|
|
||||||
|
|
||||||
envtmp = getenv("TMPDIR");
|
|
||||||
(void)snprintf(path,
|
|
||||||
sizeof(path), "%s/bt.XXXXXX", envtmp ? envtmp : "/tmp");
|
|
||||||
|
|
||||||
(void)sigfillset(&set);
|
|
||||||
(void)sigprocmask(SIG_BLOCK, &set, &oset);
|
|
||||||
if ((fd = mkstemp(path)) != -1)
|
|
||||||
(void)unlink(path);
|
|
||||||
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
|
|
||||||
return(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
byteorder(void)
|
|
||||||
{
|
|
||||||
u_long x; /* XXX: 32-bit assumption. */
|
|
||||||
u_char *p;
|
|
||||||
|
|
||||||
x = 0x01020304;
|
|
||||||
p = (u_char *)&x;
|
|
||||||
switch (*p) {
|
|
||||||
case 1:
|
|
||||||
return (BIG_ENDIAN);
|
|
||||||
case 4:
|
|
||||||
return (LITTLE_ENDIAN);
|
|
||||||
default:
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
__bt_fd(const DB *dbp)
|
|
||||||
{
|
|
||||||
BTREE *t;
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
|
|
||||||
/* Toss any page pinned across calls. */
|
|
||||||
if (t->bt_pinned != NULL) {
|
|
||||||
mpool_put(t->bt_mp, t->bt_pinned, 0);
|
|
||||||
t->bt_pinned = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In-memory database can't have a file descriptor. */
|
|
||||||
if (ISSET(t, B_INMEM)) {
|
|
||||||
errno = ENOENT;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
return (t->bt_fd);
|
|
||||||
}
|
|
|
@ -1,237 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_overflow.c /main/3 1996/06/11 17:12:45 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_overflow.c 8.1 (Berkeley) 6/4/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Big key/data code.
|
|
||||||
*
|
|
||||||
* Big key and data entries are stored on linked lists of pages. The initial
|
|
||||||
* reference is byte string stored with the key or data and is the page number
|
|
||||||
* and size. The actual record is stored in a chain of pages linked by the
|
|
||||||
* nextpg field of the PAGE header.
|
|
||||||
*
|
|
||||||
* The first page of the chain has a special property. If the record is used
|
|
||||||
* by an internal page, it cannot be deleted and the P_PRESERVE bit will be set
|
|
||||||
* in the header.
|
|
||||||
*
|
|
||||||
* XXX
|
|
||||||
* A single DBT is written to each chain, so a lot of space on the last page
|
|
||||||
* is wasted. This is a fairly major bug for some data sets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __OVFL_GET -- Get an overflow key/data item.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* p: pointer to { pgno_t, size_t }
|
|
||||||
* buf: storage address
|
|
||||||
* bufsz: storage size
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__ovfl_get(BTREE *t, void *p, size_t *ssz, char **buf, size_t *bufsz)
|
|
||||||
{
|
|
||||||
PAGE *h;
|
|
||||||
pgno_t pg;
|
|
||||||
size_t nb, plen, sz;
|
|
||||||
|
|
||||||
memmove(&pg, p, sizeof(pgno_t));
|
|
||||||
memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(size_t));
|
|
||||||
*ssz = sz;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (pg == P_INVALID || sz == 0)
|
|
||||||
abort();
|
|
||||||
#endif
|
|
||||||
/* Make the buffer bigger as necessary. */
|
|
||||||
if (*bufsz < sz) {
|
|
||||||
if ((*buf = __fix_realloc(*buf, sz)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
*bufsz = sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Step through the linked list of pages, copying the data on each one
|
|
||||||
* into the buffer. Never copy more than the data's length.
|
|
||||||
*/
|
|
||||||
plen = t->bt_psize - BTDATAOFF;
|
|
||||||
for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
nb = MIN(sz, plen);
|
|
||||||
memmove(p, (char *)h + BTDATAOFF, nb);
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
|
|
||||||
if ((sz -= nb) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __OVFL_PUT -- Store an overflow key/data item.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* data: DBT to store
|
|
||||||
* pgno: storage page number
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__ovfl_put(BTREE *t, const DBT *dbt, pgno_t *pg)
|
|
||||||
{
|
|
||||||
PAGE *h, *last;
|
|
||||||
void *p;
|
|
||||||
pgno_t npg;
|
|
||||||
size_t nb, plen, sz;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate pages and copy the key/data record into them. Store the
|
|
||||||
* number of the first page in the chain.
|
|
||||||
*/
|
|
||||||
plen = t->bt_psize - BTDATAOFF;
|
|
||||||
for (last = NULL, p = dbt->data, sz = dbt->size;;
|
|
||||||
p = (char *)p + plen, last = h) {
|
|
||||||
if ((h = __bt_new(t, &npg)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
h->pgno = npg;
|
|
||||||
h->nextpg = h->prevpg = P_INVALID;
|
|
||||||
h->flags = P_OVERFLOW;
|
|
||||||
h->lower = h->upper = 0;
|
|
||||||
|
|
||||||
nb = MIN(sz, plen);
|
|
||||||
memmove((char *)h + BTDATAOFF, p, nb);
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
last->nextpg = h->pgno;
|
|
||||||
mpool_put(t->bt_mp, last, MPOOL_DIRTY);
|
|
||||||
} else
|
|
||||||
*pg = h->pgno;
|
|
||||||
|
|
||||||
if ((sz -= nb) == 0) {
|
|
||||||
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __OVFL_DELETE -- Delete an overflow chain.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* p: pointer to { pgno_t, size_t }
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__ovfl_delete(BTREE *t, void *p)
|
|
||||||
{
|
|
||||||
PAGE *h;
|
|
||||||
pgno_t pg;
|
|
||||||
size_t plen, sz;
|
|
||||||
|
|
||||||
memmove(&pg, p, sizeof(pgno_t));
|
|
||||||
memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(size_t));
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (pg == P_INVALID || sz == 0)
|
|
||||||
abort();
|
|
||||||
#endif
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
/* Don't delete chains used by internal pages. */
|
|
||||||
if (h->flags & P_PRESERVE) {
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Step through the chain, calling the free routine for each page. */
|
|
||||||
for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) {
|
|
||||||
pg = h->nextpg;
|
|
||||||
__bt_free(t, h);
|
|
||||||
if (sz <= plen)
|
|
||||||
break;
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_page.c /main/3 1996/06/11 17:12:50 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_page.c 8.1 (Berkeley) 6/4/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#define __DBINTERFACE_PRIVATE
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_FREE -- Put a page on the freelist.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* h: page to free
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_free(BTREE *t, PAGE *h)
|
|
||||||
{
|
|
||||||
/* Insert the page at the start of the free list. */
|
|
||||||
h->prevpg = P_INVALID;
|
|
||||||
h->nextpg = t->bt_free;
|
|
||||||
t->bt_free = h->pgno;
|
|
||||||
|
|
||||||
/* Make sure the page gets written back. */
|
|
||||||
return (mpool_put(t->bt_mp, h, MPOOL_DIRTY));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_NEW -- Get a new page, preferably from the freelist.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* npg: storage for page number.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Pointer to a page, NULL on error.
|
|
||||||
*/
|
|
||||||
PAGE *
|
|
||||||
__bt_new(BTREE *t, pgno_t *npg)
|
|
||||||
{
|
|
||||||
PAGE *h;
|
|
||||||
|
|
||||||
if (t->bt_free != P_INVALID &&
|
|
||||||
(h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) {
|
|
||||||
*npg = t->bt_free;
|
|
||||||
t->bt_free = h->nextpg;
|
|
||||||
return (h);
|
|
||||||
}
|
|
||||||
return (mpool_new(t->bt_mp, npg));
|
|
||||||
}
|
|
|
@ -1,336 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_put.c /main/3 1996/06/11 17:12:56 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_put.c 8.2 (Berkeley) 9/7/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
static EPG *bt_fast __P((BTREE *, const DBT *, const DBT *, int *));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_PUT -- Add a btree item to the tree.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* dbp: pointer to access method
|
|
||||||
* key: key
|
|
||||||
* data: data
|
|
||||||
* flag: R_NOOVERWRITE
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the
|
|
||||||
* tree and R_NOOVERWRITE specified.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_put(const DB *dbp, DBT *key, const DBT *data, u_int flags)
|
|
||||||
{
|
|
||||||
BTREE *t;
|
|
||||||
DBT tkey, tdata;
|
|
||||||
EPG *e = NULL;
|
|
||||||
PAGE *h;
|
|
||||||
indx_t index, nxtindex;
|
|
||||||
pgno_t pg;
|
|
||||||
size_t nbytes;
|
|
||||||
int dflags, exact, status;
|
|
||||||
char *dest, db[NOVFLSIZE], kb[NOVFLSIZE];
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
|
|
||||||
/* Toss any page pinned across calls. */
|
|
||||||
if (t->bt_pinned != NULL) {
|
|
||||||
mpool_put(t->bt_mp, t->bt_pinned, 0);
|
|
||||||
t->bt_pinned = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (flags) {
|
|
||||||
case R_CURSOR:
|
|
||||||
if (!ISSET(t, B_SEQINIT))
|
|
||||||
goto einval;
|
|
||||||
if (ISSET(t, B_DELCRSR))
|
|
||||||
goto einval;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
case R_NOOVERWRITE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
einval: errno = EINVAL;
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ISSET(t, B_RDONLY)) {
|
|
||||||
errno = EPERM;
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the key/data won't fit on a page, store it on indirect pages.
|
|
||||||
* Only store the key on the overflow page if it's too big after the
|
|
||||||
* data is on an overflow page.
|
|
||||||
*
|
|
||||||
* XXX
|
|
||||||
* If the insert fails later on, these pages aren't recovered.
|
|
||||||
*/
|
|
||||||
dflags = 0;
|
|
||||||
if (key->size + data->size > t->bt_ovflsize) {
|
|
||||||
if (key->size > t->bt_ovflsize) {
|
|
||||||
storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR)
|
|
||||||
return (RET_ERROR);
|
|
||||||
tkey.data = kb;
|
|
||||||
tkey.size = NOVFLSIZE;
|
|
||||||
memmove(kb, &pg, sizeof(pgno_t));
|
|
||||||
memmove(kb + sizeof(pgno_t),
|
|
||||||
&key->size, sizeof(size_t));
|
|
||||||
dflags |= P_BIGKEY;
|
|
||||||
key = &tkey;
|
|
||||||
}
|
|
||||||
if (key->size + data->size > t->bt_ovflsize) {
|
|
||||||
if (__ovfl_put(t, data, &pg) == RET_ERROR)
|
|
||||||
return (RET_ERROR);
|
|
||||||
tdata.data = db;
|
|
||||||
tdata.size = NOVFLSIZE;
|
|
||||||
memmove(db, &pg, sizeof(pgno_t));
|
|
||||||
memmove(db + sizeof(pgno_t),
|
|
||||||
&data->size, sizeof(size_t));
|
|
||||||
dflags |= P_BIGDATA;
|
|
||||||
data = &tdata;
|
|
||||||
}
|
|
||||||
if (key->size + data->size > t->bt_ovflsize)
|
|
||||||
goto storekey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace the cursor. */
|
|
||||||
if (flags == R_CURSOR) {
|
|
||||||
if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
index = t->bt_bcursor.index;
|
|
||||||
goto delete;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the key to delete, or, the location at which to insert. Bt_fast
|
|
||||||
* and __bt_search pin the returned page.
|
|
||||||
*/
|
|
||||||
if (t->bt_order == NOT || (e = bt_fast(t, key, data, &exact)) == NULL)
|
|
||||||
if ((e = __bt_search(t, key, &exact)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
h = e->page;
|
|
||||||
index = e->index;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add the specified key/data pair to the tree. If an identical key
|
|
||||||
* is already in the tree, and R_NOOVERWRITE is set, an error is
|
|
||||||
* returned. If R_NOOVERWRITE is not set, the key is either added (if
|
|
||||||
* duplicates are permitted) or an error is returned.
|
|
||||||
*
|
|
||||||
* Pages are split as required.
|
|
||||||
*/
|
|
||||||
switch (flags) {
|
|
||||||
case R_NOOVERWRITE:
|
|
||||||
if (!exact)
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
* One special case is if the cursor references the record and
|
|
||||||
* it's been flagged for deletion. Then, we delete the record,
|
|
||||||
* leaving the cursor there -- this means that the inserted
|
|
||||||
* record will not be seen in a cursor scan.
|
|
||||||
*/
|
|
||||||
if (ISSET(t, B_DELCRSR) && t->bt_bcursor.pgno == h->pgno &&
|
|
||||||
t->bt_bcursor.index == index) {
|
|
||||||
CLR(t, B_DELCRSR);
|
|
||||||
goto delete;
|
|
||||||
}
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
return (RET_SPECIAL);
|
|
||||||
default:
|
|
||||||
if (!exact || !ISSET(t, B_NODUPS))
|
|
||||||
break;
|
|
||||||
delete: if (__bt_dleaf(t, h, index) == RET_ERROR) {
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If not enough room, or the user has put a ceiling on the number of
|
|
||||||
* keys permitted in the page, split the page. The split code will
|
|
||||||
* insert the key and data and unpin the current page. If inserting
|
|
||||||
* into the offset array, shift the pointers up.
|
|
||||||
*/
|
|
||||||
nbytes = NBLEAFDBT(key->size, data->size);
|
|
||||||
if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
|
|
||||||
if ((status = __bt_split(t, h, key,
|
|
||||||
data, dflags, nbytes, index)) != RET_SUCCESS)
|
|
||||||
return (status);
|
|
||||||
goto success;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < (nxtindex = NEXTINDEX(h)))
|
|
||||||
memmove(h->linp + index + 1, h->linp + index,
|
|
||||||
(nxtindex - index) * sizeof(indx_t));
|
|
||||||
h->lower += sizeof(indx_t);
|
|
||||||
|
|
||||||
h->linp[index] = h->upper -= nbytes;
|
|
||||||
dest = (char *)h + h->upper;
|
|
||||||
WR_BLEAF(dest, key, data, dflags);
|
|
||||||
|
|
||||||
if (t->bt_order == NOT) {
|
|
||||||
if (h->nextpg == P_INVALID) {
|
|
||||||
if (index == NEXTINDEX(h) - 1) {
|
|
||||||
t->bt_order = FORWARD;
|
|
||||||
t->bt_last.index = index;
|
|
||||||
t->bt_last.pgno = h->pgno;
|
|
||||||
}
|
|
||||||
} else if (h->prevpg == P_INVALID) {
|
|
||||||
if (index == 0) {
|
|
||||||
t->bt_order = BACK;
|
|
||||||
t->bt_last.index = 0;
|
|
||||||
t->bt_last.pgno = h->pgno;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
|
|
||||||
|
|
||||||
success:
|
|
||||||
if (flags == R_SETCURSOR) {
|
|
||||||
t->bt_bcursor.pgno = e->page->pgno;
|
|
||||||
t->bt_bcursor.index = e->index;
|
|
||||||
}
|
|
||||||
SET(t, B_MODIFIED);
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
u_long bt_cache_hit, bt_cache_miss;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_FAST -- Do a quick check for sorted data.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* key: key to insert
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* EPG for new record or NULL if not found.
|
|
||||||
*/
|
|
||||||
static EPG *
|
|
||||||
bt_fast(BTREE *t, const DBT *key, const DBT *data, int *exactp)
|
|
||||||
{
|
|
||||||
static EPG e;
|
|
||||||
PAGE *h;
|
|
||||||
size_t nbytes;
|
|
||||||
int cmp;
|
|
||||||
|
|
||||||
if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) {
|
|
||||||
t->bt_order = NOT;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
e.page = h;
|
|
||||||
e.index = t->bt_last.index;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If won't fit in this page or have too many keys in this page, have
|
|
||||||
* to search to get split stack.
|
|
||||||
*/
|
|
||||||
nbytes = NBLEAFDBT(key->size, data->size);
|
|
||||||
if (h->upper - h->lower < nbytes + sizeof(indx_t))
|
|
||||||
goto miss;
|
|
||||||
|
|
||||||
if (t->bt_order == FORWARD) {
|
|
||||||
if (e.page->nextpg != P_INVALID)
|
|
||||||
goto miss;
|
|
||||||
if (e.index != NEXTINDEX(h) - 1)
|
|
||||||
goto miss;
|
|
||||||
if ((cmp = __bt_cmp(t, key, &e)) < 0)
|
|
||||||
goto miss;
|
|
||||||
t->bt_last.index = cmp ? ++e.index : e.index;
|
|
||||||
} else {
|
|
||||||
if (e.page->prevpg != P_INVALID)
|
|
||||||
goto miss;
|
|
||||||
if (e.index != 0)
|
|
||||||
goto miss;
|
|
||||||
if ((cmp = __bt_cmp(t, key, &e)) > 0)
|
|
||||||
goto miss;
|
|
||||||
t->bt_last.index = 0;
|
|
||||||
}
|
|
||||||
*exactp = cmp == 0;
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++bt_cache_hit;
|
|
||||||
#endif
|
|
||||||
return (&e);
|
|
||||||
|
|
||||||
miss:
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++bt_cache_miss;
|
|
||||||
#endif
|
|
||||||
t->bt_order = NOT;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
|
@ -1,139 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_search.c /main/3 1996/06/11 17:13:01 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_search.c 8.1 (Berkeley) 6/4/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_SEARCH -- Search a btree for a key.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree to search
|
|
||||||
* key: key to find
|
|
||||||
* exactp: pointer to exact match flag
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* EPG for matching record, if any, or the EPG for the location of the
|
|
||||||
* key, if it were inserted into the tree.
|
|
||||||
*
|
|
||||||
* Warnings:
|
|
||||||
* The EPG returned is in static memory, and will be overwritten by the
|
|
||||||
* next search of any kind in any tree.
|
|
||||||
*/
|
|
||||||
EPG *
|
|
||||||
__bt_search(BTREE *t, const DBT *key, int *exactp)
|
|
||||||
{
|
|
||||||
indx_t index;
|
|
||||||
int base, cmp, lim;
|
|
||||||
PAGE *h;
|
|
||||||
pgno_t pg;
|
|
||||||
static EPG e;
|
|
||||||
|
|
||||||
BT_CLR(t);
|
|
||||||
for (pg = P_ROOT;;) {
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
/* Do a binary search on the current page. */
|
|
||||||
e.page = h;
|
|
||||||
for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
|
|
||||||
e.index = index = base + (lim >> 1);
|
|
||||||
if ((cmp = __bt_cmp(t, key, &e)) == 0) {
|
|
||||||
if (h->flags & P_BLEAF) {
|
|
||||||
*exactp = 1;
|
|
||||||
return (&e);
|
|
||||||
}
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
if (cmp > 0) {
|
|
||||||
base = index + 1;
|
|
||||||
--lim;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If it's a leaf page, we're done. */
|
|
||||||
if (h->flags & P_BLEAF) {
|
|
||||||
e.index = base;
|
|
||||||
*exactp = 0;
|
|
||||||
return (&e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* No match found. Base is the smallest index greater than
|
|
||||||
* key and may be zero or a last + 1 index. If it's non-zero,
|
|
||||||
* decrement by one, and record the internal page which should
|
|
||||||
* be a parent page for the key. If a split later occurs, the
|
|
||||||
* inserted page will be to the right of the saved page.
|
|
||||||
*/
|
|
||||||
index = base ? base - 1 : base;
|
|
||||||
|
|
||||||
next: if (__bt_push(t, h->pgno, index) == RET_ERROR)
|
|
||||||
return (NULL);
|
|
||||||
pg = GETBINTERNAL(h, index)->pgno;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,391 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_seq.c /main/3 1996/06/11 17:13:05 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_seq.c 8.2 (Berkeley) 9/7/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
static int bt_seqadv __P((BTREE *, EPG *, int));
|
|
||||||
static int bt_seqset __P((BTREE *, EPG *, DBT *, int));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sequential scan support.
|
|
||||||
*
|
|
||||||
* The tree can be scanned sequentially, starting from either end of the tree
|
|
||||||
* or from any specific key. A scan request before any scanning is done is
|
|
||||||
* initialized as starting from the least node.
|
|
||||||
*
|
|
||||||
* Each tree has an EPGNO which has the current position of the cursor. The
|
|
||||||
* cursor has to survive deletions/insertions in the tree without losing its
|
|
||||||
* position. This is done by noting deletions without doing them, and then
|
|
||||||
* doing them when the cursor moves (or the tree is closed).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_SEQ -- Btree sequential scan interface.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* dbp: pointer to access method
|
|
||||||
* key: key for positioning and return value
|
|
||||||
* data: data return value
|
|
||||||
* flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_seq(const DB *dbp, DBT *key, DBT *data, u_int flags)
|
|
||||||
{
|
|
||||||
BTREE *t;
|
|
||||||
EPG e;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
t = dbp->internal;
|
|
||||||
|
|
||||||
/* Toss any page pinned across calls. */
|
|
||||||
if (t->bt_pinned != NULL) {
|
|
||||||
mpool_put(t->bt_mp, t->bt_pinned, 0);
|
|
||||||
t->bt_pinned = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If scan unitialized as yet, or starting at a specific record, set
|
|
||||||
* the scan to a specific key. Both bt_seqset and bt_seqadv pin the
|
|
||||||
* page the cursor references if they're successful.
|
|
||||||
*/
|
|
||||||
switch(flags) {
|
|
||||||
case R_NEXT:
|
|
||||||
case R_PREV:
|
|
||||||
if (ISSET(t, B_SEQINIT)) {
|
|
||||||
status = bt_seqadv(t, &e, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case R_CURSOR:
|
|
||||||
case R_FIRST:
|
|
||||||
case R_LAST:
|
|
||||||
status = bt_seqset(t, &e, key, flags);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errno = EINVAL;
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == RET_SUCCESS) {
|
|
||||||
status = __bt_ret(t, &e, key, data);
|
|
||||||
|
|
||||||
/* Update the actual cursor. */
|
|
||||||
t->bt_bcursor.pgno = e.page->pgno;
|
|
||||||
t->bt_bcursor.index = e.index;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the user is doing concurrent access, we copied the
|
|
||||||
* key/data, toss the page.
|
|
||||||
*/
|
|
||||||
if (ISSET(t, B_DB_LOCK))
|
|
||||||
mpool_put(t->bt_mp, e.page, 0);
|
|
||||||
else
|
|
||||||
t->bt_pinned = e.page;
|
|
||||||
SET(t, B_SEQINIT);
|
|
||||||
}
|
|
||||||
return (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_SEQSET -- Set the sequential scan to a specific key.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* ep: storage for returned key
|
|
||||||
* key: key for initial scan position
|
|
||||||
* flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* Pins the page the cursor references.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags)
|
|
||||||
{
|
|
||||||
EPG *e;
|
|
||||||
PAGE *h;
|
|
||||||
pgno_t pg;
|
|
||||||
int exact;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete any already deleted record that we've been saving because
|
|
||||||
* the cursor pointed to it. Since going to a specific key, should
|
|
||||||
* delete any logically deleted records so they aren't found.
|
|
||||||
*/
|
|
||||||
if (ISSET(t, B_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor))
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the first, last or specific key in the tree and point the cursor
|
|
||||||
* at it. The cursor may not be moved until a new key has been found.
|
|
||||||
*/
|
|
||||||
switch(flags) {
|
|
||||||
case R_CURSOR: /* Keyed scan. */
|
|
||||||
/*
|
|
||||||
* Find the first instance of the key or the smallest key which
|
|
||||||
* is greater than or equal to the specified key. If run out
|
|
||||||
* of keys, return RET_SPECIAL.
|
|
||||||
*/
|
|
||||||
if (key->data == NULL || key->size == 0) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
e = __bt_first(t, key, &exact); /* Returns pinned page. */
|
|
||||||
if (e == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
/*
|
|
||||||
* If at the end of a page, skip any empty pages and find the
|
|
||||||
* next entry.
|
|
||||||
*/
|
|
||||||
if (e->index == NEXTINDEX(e->page)) {
|
|
||||||
h = e->page;
|
|
||||||
do {
|
|
||||||
pg = h->nextpg;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
if (pg == P_INVALID)
|
|
||||||
return (RET_SPECIAL);
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
} while (NEXTINDEX(h) == 0);
|
|
||||||
e->index = 0;
|
|
||||||
e->page = h;
|
|
||||||
}
|
|
||||||
*ep = *e;
|
|
||||||
break;
|
|
||||||
case R_FIRST: /* First record. */
|
|
||||||
case R_NEXT:
|
|
||||||
/* Walk down the left-hand side of the tree. */
|
|
||||||
for (pg = P_ROOT;;) {
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
if (h->flags & (P_BLEAF | P_RLEAF))
|
|
||||||
break;
|
|
||||||
pg = GETBINTERNAL(h, 0)->pgno;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip any empty pages. */
|
|
||||||
while (NEXTINDEX(h) == 0 && h->nextpg != P_INVALID) {
|
|
||||||
pg = h->nextpg;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NEXTINDEX(h) == 0) {
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
return (RET_SPECIAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ep->page = h;
|
|
||||||
ep->index = 0;
|
|
||||||
break;
|
|
||||||
case R_LAST: /* Last record. */
|
|
||||||
case R_PREV:
|
|
||||||
/* Walk down the right-hand side of the tree. */
|
|
||||||
for (pg = P_ROOT;;) {
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
if (h->flags & (P_BLEAF | P_RLEAF))
|
|
||||||
break;
|
|
||||||
pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip any empty pages. */
|
|
||||||
while (NEXTINDEX(h) == 0 && h->prevpg != P_INVALID) {
|
|
||||||
pg = h->prevpg;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NEXTINDEX(h) == 0) {
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
return (RET_SPECIAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ep->page = h;
|
|
||||||
ep->index = NEXTINDEX(h) - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_SEQADVANCE -- Advance the sequential scan.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* flags: R_NEXT, R_PREV
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* Pins the page the new key/data record is on.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
bt_seqadv(BTREE *t, EPG *e, int flags)
|
|
||||||
{
|
|
||||||
EPGNO *c, delc;
|
|
||||||
PAGE *h;
|
|
||||||
indx_t index;
|
|
||||||
pgno_t pg;
|
|
||||||
|
|
||||||
/* Save the current cursor if going to delete it. */
|
|
||||||
c = &t->bt_bcursor;
|
|
||||||
if (ISSET(t, B_DELCRSR))
|
|
||||||
delc = *c;
|
|
||||||
|
|
||||||
if ((h = mpool_get(t->bt_mp, c->pgno, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the next/previous record in the tree and point the cursor at it.
|
|
||||||
* The cursor may not be moved until a new key has been found.
|
|
||||||
*/
|
|
||||||
index = c->index;
|
|
||||||
switch(flags) {
|
|
||||||
case R_NEXT: /* Next record. */
|
|
||||||
if (++index == NEXTINDEX(h)) {
|
|
||||||
do {
|
|
||||||
pg = h->nextpg;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
if (pg == P_INVALID)
|
|
||||||
return (RET_SPECIAL);
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
} while (NEXTINDEX(h) == 0);
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case R_PREV: /* Previous record. */
|
|
||||||
if (index-- == 0) {
|
|
||||||
do {
|
|
||||||
pg = h->prevpg;
|
|
||||||
mpool_put(t->bt_mp, h, 0);
|
|
||||||
if (pg == P_INVALID)
|
|
||||||
return (RET_SPECIAL);
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
} while (NEXTINDEX(h) == 0);
|
|
||||||
index = NEXTINDEX(h) - 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
e->page = h;
|
|
||||||
e->index = index;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete any already deleted record that we've been saving because the
|
|
||||||
* cursor pointed to it. This could cause the new index to be shifted
|
|
||||||
* down by one if the record we're deleting is on the same page and has
|
|
||||||
* a larger index.
|
|
||||||
*/
|
|
||||||
if (ISSET(t, B_DELCRSR)) {
|
|
||||||
CLR(t, B_DELCRSR); /* Don't try twice. */
|
|
||||||
if (c->pgno == delc.pgno && c->index > delc.index)
|
|
||||||
--c->index;
|
|
||||||
if (__bt_crsrdel(t, &delc))
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_CRSRDEL -- Delete the record referenced by the cursor.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_crsrdel(BTREE *t, EPGNO *c)
|
|
||||||
{
|
|
||||||
PAGE *h;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
CLR(t, B_DELCRSR); /* Don't try twice. */
|
|
||||||
if ((h = mpool_get(t->bt_mp, c->pgno, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
status = __bt_dleaf(t, h, c->index);
|
|
||||||
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
|
|
||||||
return (status);
|
|
||||||
}
|
|
|
@ -1,826 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_split.c /main/3 1996/06/11 17:13:10 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_split.c 8.1 (Berkeley) 6/4/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#define __DBINTERFACE_PRIVATE
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
static int bt_broot __P((BTREE *, PAGE *, PAGE *, PAGE *));
|
|
||||||
static PAGE *bt_page
|
|
||||||
__P((BTREE *, PAGE *, PAGE **, PAGE **, u_int *, size_t));
|
|
||||||
static int bt_preserve __P((BTREE *, pgno_t));
|
|
||||||
static PAGE *bt_psplit
|
|
||||||
__P((BTREE *, PAGE *, PAGE *, PAGE *, u_int *, size_t));
|
|
||||||
static PAGE *bt_root
|
|
||||||
__P((BTREE *, PAGE *, PAGE **, PAGE **, u_int *, size_t));
|
|
||||||
static int bt_rroot __P((BTREE *, PAGE *, PAGE *, PAGE *));
|
|
||||||
static recno_t rec_total __P((PAGE *));
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
u_long bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_SPLIT -- Split the tree.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* sp: page to split
|
|
||||||
* key: key to insert
|
|
||||||
* data: data to insert
|
|
||||||
* flags: BIGKEY/BIGDATA flags
|
|
||||||
* ilen: insert length
|
|
||||||
* skip: index to leave open
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_split(BTREE *t, PAGE *sp, const DBT *key, const DBT *data, u_long flags, size_t ilen, u_int skip)
|
|
||||||
{
|
|
||||||
BINTERNAL *bi = NULL;
|
|
||||||
BLEAF *bl = NULL;
|
|
||||||
BLEAF *tbl;
|
|
||||||
DBT a, b;
|
|
||||||
EPGNO *parent;
|
|
||||||
PAGE *h, *l, *r, *lchild, *rchild;
|
|
||||||
indx_t nxtindex;
|
|
||||||
size_t n, nbytes;
|
|
||||||
size_t nksize = 0;
|
|
||||||
int parentsplit;
|
|
||||||
char *dest;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Split the page into two pages, l and r. The split routines return
|
|
||||||
* a pointer to the page into which the key should be inserted and with
|
|
||||||
* skip set to the offset which should be used. Additionally, l and r
|
|
||||||
* are pinned.
|
|
||||||
*/
|
|
||||||
h = sp->pgno == P_ROOT ?
|
|
||||||
bt_root(t, sp, &l, &r, &skip, ilen) :
|
|
||||||
bt_page(t, sp, &l, &r, &skip, ilen);
|
|
||||||
if (h == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Insert the new key/data pair into the leaf page. (Key inserts
|
|
||||||
* always cause a leaf page to split first.)
|
|
||||||
*/
|
|
||||||
h->linp[skip] = h->upper -= ilen;
|
|
||||||
dest = (char *)h + h->upper;
|
|
||||||
if (ISSET(t, R_RECNO))
|
|
||||||
WR_RLEAF(dest, data, flags)
|
|
||||||
else
|
|
||||||
WR_BLEAF(dest, key, data, flags)
|
|
||||||
|
|
||||||
/* If the root page was split, make it look right. */
|
|
||||||
if (sp->pgno == P_ROOT &&
|
|
||||||
(ISSET(t, R_RECNO) ?
|
|
||||||
bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
|
|
||||||
goto err2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now we walk the parent page stack -- a LIFO stack of the pages that
|
|
||||||
* were traversed when we searched for the page that split. Each stack
|
|
||||||
* entry is a page number and a page index offset. The offset is for
|
|
||||||
* the page traversed on the search. We've just split a page, so we
|
|
||||||
* have to insert a new key into the parent page.
|
|
||||||
*
|
|
||||||
* If the insert into the parent page causes it to split, may have to
|
|
||||||
* continue splitting all the way up the tree. We stop if the root
|
|
||||||
* splits or the page inserted into didn't have to split to hold the
|
|
||||||
* new key. Some algorithms replace the key for the old page as well
|
|
||||||
* as the new page. We don't, as there's no reason to believe that the
|
|
||||||
* first key on the old page is any better than the key we have, and,
|
|
||||||
* in the case of a key being placed at index 0 causing the split, the
|
|
||||||
* key is unavailable.
|
|
||||||
*
|
|
||||||
* There are a maximum of 5 pages pinned at any time. We keep the left
|
|
||||||
* and right pages pinned while working on the parent. The 5 are the
|
|
||||||
* two children, left parent and right parent (when the parent splits)
|
|
||||||
* and the root page or the overflow key page when calling bt_preserve.
|
|
||||||
* This code must make sure that all pins are released other than the
|
|
||||||
* root page or overflow page which is unlocked elsewhere.
|
|
||||||
*/
|
|
||||||
while ((parent = BT_POP(t)) != NULL) {
|
|
||||||
lchild = l;
|
|
||||||
rchild = r;
|
|
||||||
|
|
||||||
/* Get the parent page. */
|
|
||||||
if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
|
|
||||||
goto err2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The new key goes ONE AFTER the index, because the split
|
|
||||||
* was to the right.
|
|
||||||
*/
|
|
||||||
skip = parent->index + 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the space needed on the parent page.
|
|
||||||
*
|
|
||||||
* Prefix trees: space hack when inserting into BINTERNAL
|
|
||||||
* pages. Retain only what's needed to distinguish between
|
|
||||||
* the new entry and the LAST entry on the page to its left.
|
|
||||||
* If the keys compare equal, retain the entire key. Note,
|
|
||||||
* we don't touch overflow keys, and the entire key must be
|
|
||||||
* retained for the next-to-left most key on the leftmost
|
|
||||||
* page of each level, or the search will fail. Applicable
|
|
||||||
* ONLY to internal pages that have leaf pages as children.
|
|
||||||
* Further reduction of the key between pairs of internal
|
|
||||||
* pages loses too much information.
|
|
||||||
*/
|
|
||||||
switch (rchild->flags & P_TYPE) {
|
|
||||||
case P_BINTERNAL:
|
|
||||||
bi = GETBINTERNAL(rchild, 0);
|
|
||||||
nbytes = NBINTERNAL(bi->ksize);
|
|
||||||
break;
|
|
||||||
case P_BLEAF:
|
|
||||||
bl = GETBLEAF(rchild, 0);
|
|
||||||
nbytes = NBINTERNAL(bl->ksize);
|
|
||||||
if (t->bt_pfx && !(bl->flags & P_BIGKEY) &&
|
|
||||||
(h->prevpg != P_INVALID || skip > 1)) {
|
|
||||||
tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1);
|
|
||||||
a.size = tbl->ksize;
|
|
||||||
a.data = tbl->bytes;
|
|
||||||
b.size = bl->ksize;
|
|
||||||
b.data = bl->bytes;
|
|
||||||
nksize = t->bt_pfx(&a, &b);
|
|
||||||
n = NBINTERNAL(nksize);
|
|
||||||
if (n < nbytes) {
|
|
||||||
#ifdef STATISTICS
|
|
||||||
bt_pfxsaved += nbytes - n;
|
|
||||||
#endif
|
|
||||||
nbytes = n;
|
|
||||||
} else
|
|
||||||
nksize = 0;
|
|
||||||
} else
|
|
||||||
nksize = 0;
|
|
||||||
break;
|
|
||||||
case P_RINTERNAL:
|
|
||||||
case P_RLEAF:
|
|
||||||
nbytes = NRINTERNAL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Split the parent page if necessary or shift the indices. */
|
|
||||||
if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
|
|
||||||
sp = h;
|
|
||||||
h = h->pgno == P_ROOT ?
|
|
||||||
bt_root(t, h, &l, &r, &skip, nbytes) :
|
|
||||||
bt_page(t, h, &l, &r, &skip, nbytes);
|
|
||||||
if (h == NULL)
|
|
||||||
goto err1;
|
|
||||||
parentsplit = 1;
|
|
||||||
} else {
|
|
||||||
if (skip < (nxtindex = NEXTINDEX(h)))
|
|
||||||
memmove(h->linp + skip + 1, h->linp + skip,
|
|
||||||
(nxtindex - skip) * sizeof(indx_t));
|
|
||||||
h->lower += sizeof(indx_t);
|
|
||||||
parentsplit = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert the key into the parent page. */
|
|
||||||
switch(rchild->flags & P_TYPE) {
|
|
||||||
case P_BINTERNAL:
|
|
||||||
h->linp[skip] = h->upper -= nbytes;
|
|
||||||
dest = (char *)h + h->linp[skip];
|
|
||||||
memmove(dest, bi, nbytes);
|
|
||||||
((BINTERNAL *)dest)->pgno = rchild->pgno;
|
|
||||||
break;
|
|
||||||
case P_BLEAF:
|
|
||||||
h->linp[skip] = h->upper -= nbytes;
|
|
||||||
dest = (char *)h + h->linp[skip];
|
|
||||||
WR_BINTERNAL(dest, nksize ? nksize : bl->ksize,
|
|
||||||
rchild->pgno, bl->flags & P_BIGKEY);
|
|
||||||
memmove(dest, bl->bytes, nksize ? nksize : bl->ksize);
|
|
||||||
if (bl->flags & P_BIGKEY &&
|
|
||||||
bt_preserve(t, *(char *)bl->bytes) == RET_ERROR)
|
|
||||||
goto err1;
|
|
||||||
break;
|
|
||||||
case P_RINTERNAL:
|
|
||||||
/*
|
|
||||||
* Update the left page count. If split
|
|
||||||
* added at index 0, fix the correct page.
|
|
||||||
*/
|
|
||||||
if (skip > 0)
|
|
||||||
dest = (char *)h + h->linp[skip - 1];
|
|
||||||
else
|
|
||||||
dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
|
|
||||||
((RINTERNAL *)dest)->nrecs = rec_total(lchild);
|
|
||||||
((RINTERNAL *)dest)->pgno = lchild->pgno;
|
|
||||||
|
|
||||||
/* Update the right page count. */
|
|
||||||
h->linp[skip] = h->upper -= nbytes;
|
|
||||||
dest = (char *)h + h->linp[skip];
|
|
||||||
((RINTERNAL *)dest)->nrecs = rec_total(rchild);
|
|
||||||
((RINTERNAL *)dest)->pgno = rchild->pgno;
|
|
||||||
break;
|
|
||||||
case P_RLEAF:
|
|
||||||
/*
|
|
||||||
* Update the left page count. If split
|
|
||||||
* added at index 0, fix the correct page.
|
|
||||||
*/
|
|
||||||
if (skip > 0)
|
|
||||||
dest = (char *)h + h->linp[skip - 1];
|
|
||||||
else
|
|
||||||
dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
|
|
||||||
((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild);
|
|
||||||
((RINTERNAL *)dest)->pgno = lchild->pgno;
|
|
||||||
|
|
||||||
/* Update the right page count. */
|
|
||||||
h->linp[skip] = h->upper -= nbytes;
|
|
||||||
dest = (char *)h + h->linp[skip];
|
|
||||||
((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild);
|
|
||||||
((RINTERNAL *)dest)->pgno = rchild->pgno;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unpin the held pages. */
|
|
||||||
if (!parentsplit) {
|
|
||||||
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the root page was split, make it look right. */
|
|
||||||
if (sp->pgno == P_ROOT &&
|
|
||||||
(ISSET(t, R_RECNO) ?
|
|
||||||
bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
|
|
||||||
goto err1;
|
|
||||||
|
|
||||||
mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
|
|
||||||
mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unpin the held pages. */
|
|
||||||
mpool_put(t->bt_mp, l, MPOOL_DIRTY);
|
|
||||||
mpool_put(t->bt_mp, r, MPOOL_DIRTY);
|
|
||||||
|
|
||||||
/* Clear any pages left on the stack. */
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If something fails in the above loop we were already walking back
|
|
||||||
* up the tree and the tree is now inconsistent. Nothing much we can
|
|
||||||
* do about it but release any memory we're holding.
|
|
||||||
*/
|
|
||||||
err1: mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
|
|
||||||
mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
|
|
||||||
|
|
||||||
err2: mpool_put(t->bt_mp, l, 0);
|
|
||||||
mpool_put(t->bt_mp, r, 0);
|
|
||||||
__dbpanic(t->bt_dbp);
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_PAGE -- Split a non-root page of a btree.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* h: root page
|
|
||||||
* lp: pointer to left page pointer
|
|
||||||
* rp: pointer to right page pointer
|
|
||||||
* skip: pointer to index to leave open
|
|
||||||
* ilen: insert length
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Pointer to page in which to insert or NULL on error.
|
|
||||||
*/
|
|
||||||
static PAGE *
|
|
||||||
bt_page(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, u_int *skip, size_t ilen)
|
|
||||||
{
|
|
||||||
PAGE *l, *r, *tp;
|
|
||||||
pgno_t npg;
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++bt_split;
|
|
||||||
#endif
|
|
||||||
/* Put the new right page for the split into place. */
|
|
||||||
if ((r = __bt_new(t, &npg)) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
r->pgno = npg;
|
|
||||||
r->lower = BTDATAOFF;
|
|
||||||
r->upper = t->bt_psize;
|
|
||||||
r->nextpg = h->nextpg;
|
|
||||||
r->prevpg = h->pgno;
|
|
||||||
r->flags = h->flags & P_TYPE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're splitting the last page on a level because we're appending
|
|
||||||
* a key to it (skip is NEXTINDEX()), it's likely that the data is
|
|
||||||
* sorted. Adding an empty page on the side of the level is less work
|
|
||||||
* and can push the fill factor much higher than normal. If we're
|
|
||||||
* wrong it's no big deal, we'll just do the split the right way next
|
|
||||||
* time. It may look like it's equally easy to do a similar hack for
|
|
||||||
* reverse sorted data, that is, split the tree left, but it's not.
|
|
||||||
* Don't even try.
|
|
||||||
*/
|
|
||||||
if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) {
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++bt_sortsplit;
|
|
||||||
#endif
|
|
||||||
h->nextpg = r->pgno;
|
|
||||||
r->lower = BTDATAOFF + sizeof(indx_t);
|
|
||||||
*skip = 0;
|
|
||||||
*lp = h;
|
|
||||||
*rp = r;
|
|
||||||
return (r);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Put the new left page for the split into place. */
|
|
||||||
if ((l = malloc(t->bt_psize)) == NULL) {
|
|
||||||
mpool_put(t->bt_mp, r, 0);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
l->pgno = h->pgno;
|
|
||||||
l->nextpg = r->pgno;
|
|
||||||
l->prevpg = h->prevpg;
|
|
||||||
l->lower = BTDATAOFF;
|
|
||||||
l->upper = t->bt_psize;
|
|
||||||
l->flags = h->flags & P_TYPE;
|
|
||||||
|
|
||||||
/* Fix up the previous pointer of the page after the split page. */
|
|
||||||
if (h->nextpg != P_INVALID) {
|
|
||||||
if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) {
|
|
||||||
free(l);
|
|
||||||
/* XXX mpool_free(t->bt_mp, r->pgno); */
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
tp->prevpg = r->pgno;
|
|
||||||
mpool_put(t->bt_mp, tp, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Split right. The key/data pairs aren't sorted in the btree page so
|
|
||||||
* it's simpler to copy the data from the split page onto two new pages
|
|
||||||
* instead of copying half the data to the right page and compacting
|
|
||||||
* the left page in place. Since the left page can't change, we have
|
|
||||||
* to swap the original and the allocated left page after the split.
|
|
||||||
*/
|
|
||||||
tp = bt_psplit(t, h, l, r, skip, ilen);
|
|
||||||
|
|
||||||
/* Move the new left page onto the old left page. */
|
|
||||||
memmove(h, l, t->bt_psize);
|
|
||||||
if (tp == l)
|
|
||||||
tp = h;
|
|
||||||
free(l);
|
|
||||||
|
|
||||||
*lp = h;
|
|
||||||
*rp = r;
|
|
||||||
return (tp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_ROOT -- Split the root page of a btree.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* h: root page
|
|
||||||
* lp: pointer to left page pointer
|
|
||||||
* rp: pointer to right page pointer
|
|
||||||
* skip: pointer to index to leave open
|
|
||||||
* ilen: insert length
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Pointer to page in which to insert or NULL on error.
|
|
||||||
*/
|
|
||||||
static PAGE *
|
|
||||||
bt_root(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, u_int *skip, size_t ilen)
|
|
||||||
{
|
|
||||||
PAGE *l, *r, *tp;
|
|
||||||
pgno_t lnpg, rnpg;
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++bt_split;
|
|
||||||
++bt_rootsplit;
|
|
||||||
#endif
|
|
||||||
/* Put the new left and right pages for the split into place. */
|
|
||||||
if ((l = __bt_new(t, &lnpg)) == NULL ||
|
|
||||||
(r = __bt_new(t, &rnpg)) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
l->pgno = lnpg;
|
|
||||||
r->pgno = rnpg;
|
|
||||||
l->nextpg = r->pgno;
|
|
||||||
r->prevpg = l->pgno;
|
|
||||||
l->prevpg = r->nextpg = P_INVALID;
|
|
||||||
l->lower = r->lower = BTDATAOFF;
|
|
||||||
l->upper = r->upper = t->bt_psize;
|
|
||||||
l->flags = r->flags = h->flags & P_TYPE;
|
|
||||||
|
|
||||||
/* Split the root page. */
|
|
||||||
tp = bt_psplit(t, h, l, r, skip, ilen);
|
|
||||||
|
|
||||||
*lp = l;
|
|
||||||
*rp = r;
|
|
||||||
return (tp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_RROOT -- Fix up the recno root page after it has been split.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* h: root page
|
|
||||||
* l: left page
|
|
||||||
* r: right page
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
bt_rroot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
|
|
||||||
{
|
|
||||||
char *dest;
|
|
||||||
|
|
||||||
/* Insert the left and right keys, set the header information. */
|
|
||||||
h->linp[0] = h->upper = t->bt_psize - NRINTERNAL;
|
|
||||||
dest = (char *)h + h->upper;
|
|
||||||
WR_RINTERNAL(dest,
|
|
||||||
l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno);
|
|
||||||
|
|
||||||
h->linp[1] = h->upper -= NRINTERNAL;
|
|
||||||
dest = (char *)h + h->upper;
|
|
||||||
WR_RINTERNAL(dest,
|
|
||||||
r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno);
|
|
||||||
|
|
||||||
h->lower = BTDATAOFF + 2 * sizeof(indx_t);
|
|
||||||
|
|
||||||
/* Unpin the root page, set to recno internal page. */
|
|
||||||
h->flags &= ~P_TYPE;
|
|
||||||
h->flags |= P_RINTERNAL;
|
|
||||||
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
|
|
||||||
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_BROOT -- Fix up the btree root page after it has been split.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* h: root page
|
|
||||||
* l: left page
|
|
||||||
* r: right page
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
bt_broot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
|
|
||||||
{
|
|
||||||
BINTERNAL *bi;
|
|
||||||
BLEAF *bl;
|
|
||||||
size_t nbytes;
|
|
||||||
char *dest;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the root page was a leaf page, change it into an internal page.
|
|
||||||
* We copy the key we split on (but not the key's data, in the case of
|
|
||||||
* a leaf page) to the new root page.
|
|
||||||
*
|
|
||||||
* The btree comparison code guarantees that the left-most key on any
|
|
||||||
* level of the tree is never used, so it doesn't need to be filled in.
|
|
||||||
*/
|
|
||||||
nbytes = NBINTERNAL(0);
|
|
||||||
h->linp[0] = h->upper = t->bt_psize - nbytes;
|
|
||||||
dest = (char *)h + h->upper;
|
|
||||||
WR_BINTERNAL(dest, 0, l->pgno, 0);
|
|
||||||
|
|
||||||
switch(h->flags & P_TYPE) {
|
|
||||||
case P_BLEAF:
|
|
||||||
bl = GETBLEAF(r, 0);
|
|
||||||
nbytes = NBINTERNAL(bl->ksize);
|
|
||||||
h->linp[1] = h->upper -= nbytes;
|
|
||||||
dest = (char *)h + h->upper;
|
|
||||||
WR_BINTERNAL(dest, bl->ksize, r->pgno, 0);
|
|
||||||
memmove(dest, bl->bytes, bl->ksize);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the key is on an overflow page, mark the overflow chain
|
|
||||||
* so it isn't deleted when the leaf copy of the key is deleted.
|
|
||||||
*/
|
|
||||||
if (bl->flags & P_BIGKEY &&
|
|
||||||
bt_preserve(t, *(char *)bl->bytes) == RET_ERROR)
|
|
||||||
return (RET_ERROR);
|
|
||||||
break;
|
|
||||||
case P_BINTERNAL:
|
|
||||||
bi = GETBINTERNAL(r, 0);
|
|
||||||
nbytes = NBINTERNAL(bi->ksize);
|
|
||||||
h->linp[1] = h->upper -= nbytes;
|
|
||||||
dest = (char *)h + h->upper;
|
|
||||||
memmove(dest, bi, nbytes);
|
|
||||||
((BINTERNAL *)dest)->pgno = r->pgno;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* There are two keys on the page. */
|
|
||||||
h->lower = BTDATAOFF + 2 * sizeof(indx_t);
|
|
||||||
|
|
||||||
/* Unpin the root page, set to btree internal page. */
|
|
||||||
h->flags &= ~P_TYPE;
|
|
||||||
h->flags |= P_BINTERNAL;
|
|
||||||
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
|
|
||||||
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_PSPLIT -- Do the real work of splitting the page.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* h: page to be split
|
|
||||||
* l: page to put lower half of data
|
|
||||||
* r: page to put upper half of data
|
|
||||||
* pskip: pointer to index to leave open
|
|
||||||
* ilen: insert length
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Pointer to page in which to insert.
|
|
||||||
*/
|
|
||||||
static PAGE *
|
|
||||||
bt_psplit(BTREE *t, PAGE *h, PAGE *l, PAGE *r, u_int *pskip, size_t ilen)
|
|
||||||
{
|
|
||||||
BINTERNAL *bi;
|
|
||||||
BLEAF *bl;
|
|
||||||
RLEAF *rl;
|
|
||||||
EPGNO *c;
|
|
||||||
PAGE *rval;
|
|
||||||
void *src = NULL;
|
|
||||||
indx_t full, half, nxt, off, skip, top, used;
|
|
||||||
size_t nbytes;
|
|
||||||
int bigkeycnt, isbigkey;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Split the data to the left and right pages. Leave the skip index
|
|
||||||
* open. Additionally, make some effort not to split on an overflow
|
|
||||||
* key. This makes internal page processing faster and can save
|
|
||||||
* space as overflow keys used by internal pages are never deleted.
|
|
||||||
*/
|
|
||||||
bigkeycnt = 0;
|
|
||||||
skip = *pskip;
|
|
||||||
full = t->bt_psize - BTDATAOFF;
|
|
||||||
half = full / 2;
|
|
||||||
used = 0;
|
|
||||||
for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) {
|
|
||||||
if (skip == off) {
|
|
||||||
nbytes = ilen;
|
|
||||||
isbigkey = 0; /* XXX: not really known. */
|
|
||||||
} else
|
|
||||||
switch (h->flags & P_TYPE) {
|
|
||||||
case P_BINTERNAL:
|
|
||||||
src = bi = GETBINTERNAL(h, nxt);
|
|
||||||
nbytes = NBINTERNAL(bi->ksize);
|
|
||||||
isbigkey = bi->flags & P_BIGKEY;
|
|
||||||
break;
|
|
||||||
case P_BLEAF:
|
|
||||||
src = bl = GETBLEAF(h, nxt);
|
|
||||||
nbytes = NBLEAF(bl);
|
|
||||||
isbigkey = bl->flags & P_BIGKEY;
|
|
||||||
break;
|
|
||||||
case P_RINTERNAL:
|
|
||||||
src = GETRINTERNAL(h, nxt);
|
|
||||||
nbytes = NRINTERNAL;
|
|
||||||
isbigkey = 0;
|
|
||||||
break;
|
|
||||||
case P_RLEAF:
|
|
||||||
src = rl = GETRLEAF(h, nxt);
|
|
||||||
nbytes = NRLEAF(rl);
|
|
||||||
isbigkey = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the key/data pairs are substantial fractions of the max
|
|
||||||
* possible size for the page, it's possible to get situations
|
|
||||||
* where we decide to try and copy too much onto the left page.
|
|
||||||
* Make sure that doesn't happen.
|
|
||||||
*/
|
|
||||||
if (skip <= off && used + nbytes >= full) {
|
|
||||||
--off;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the key/data pair, if not the skipped index. */
|
|
||||||
if (skip != off) {
|
|
||||||
++nxt;
|
|
||||||
|
|
||||||
l->linp[off] = l->upper -= nbytes;
|
|
||||||
memmove((char *)l + l->upper, src, nbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
used += nbytes;
|
|
||||||
if (used >= half) {
|
|
||||||
if (!isbigkey || bigkeycnt == 3)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
++bigkeycnt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Off is the last offset that's valid for the left page.
|
|
||||||
* Nxt is the first offset to be placed on the right page.
|
|
||||||
*/
|
|
||||||
l->lower += (off + 1) * sizeof(indx_t);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If splitting the page that the cursor was on, the cursor has to be
|
|
||||||
* adjusted to point to the same record as before the split. If the
|
|
||||||
* cursor is at or past the skipped slot, the cursor is incremented by
|
|
||||||
* one. If the cursor is on the right page, it is decremented by the
|
|
||||||
* number of records split to the left page.
|
|
||||||
*
|
|
||||||
* Don't bother checking for the B_SEQINIT flag, the page number will
|
|
||||||
* be P_INVALID.
|
|
||||||
*/
|
|
||||||
c = &t->bt_bcursor;
|
|
||||||
if (c->pgno == h->pgno) {
|
|
||||||
if (c->index >= skip)
|
|
||||||
++c->index;
|
|
||||||
if (c->index < nxt) /* Left page. */
|
|
||||||
c->pgno = l->pgno;
|
|
||||||
else { /* Right page. */
|
|
||||||
c->pgno = r->pgno;
|
|
||||||
c->index -= nxt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the skipped index was on the left page, just return that page.
|
|
||||||
* Otherwise, adjust the skip index to reflect the new position on
|
|
||||||
* the right page.
|
|
||||||
*/
|
|
||||||
if (skip <= off) {
|
|
||||||
skip = 0;
|
|
||||||
rval = l;
|
|
||||||
} else {
|
|
||||||
rval = r;
|
|
||||||
*pskip -= nxt;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (off = 0; nxt < top; ++off) {
|
|
||||||
if (skip == nxt) {
|
|
||||||
++off;
|
|
||||||
skip = 0;
|
|
||||||
}
|
|
||||||
switch (h->flags & P_TYPE) {
|
|
||||||
case P_BINTERNAL:
|
|
||||||
src = bi = GETBINTERNAL(h, nxt);
|
|
||||||
nbytes = NBINTERNAL(bi->ksize);
|
|
||||||
break;
|
|
||||||
case P_BLEAF:
|
|
||||||
src = bl = GETBLEAF(h, nxt);
|
|
||||||
nbytes = NBLEAF(bl);
|
|
||||||
break;
|
|
||||||
case P_RINTERNAL:
|
|
||||||
src = GETRINTERNAL(h, nxt);
|
|
||||||
nbytes = NRINTERNAL;
|
|
||||||
break;
|
|
||||||
case P_RLEAF:
|
|
||||||
src = rl = GETRLEAF(h, nxt);
|
|
||||||
nbytes = NRLEAF(rl);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
++nxt;
|
|
||||||
r->linp[off] = r->upper -= nbytes;
|
|
||||||
memmove((char *)r + r->upper, src, nbytes);
|
|
||||||
}
|
|
||||||
r->lower += off * sizeof(indx_t);
|
|
||||||
|
|
||||||
/* If the key is being appended to the page, adjust the index. */
|
|
||||||
if (skip == top)
|
|
||||||
r->lower += sizeof(indx_t);
|
|
||||||
|
|
||||||
return (rval);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BT_PRESERVE -- Mark a chain of pages as used by an internal node.
|
|
||||||
*
|
|
||||||
* Chains of indirect blocks pointed to by leaf nodes get reclaimed when the
|
|
||||||
* record that references them gets deleted. Chains pointed to by internal
|
|
||||||
* pages never get deleted. This routine marks a chain as pointed to by an
|
|
||||||
* internal page.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* pg: page number of first page in the chain.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_SUCCESS, RET_ERROR.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
bt_preserve(BTREE *t, pgno_t pg)
|
|
||||||
{
|
|
||||||
PAGE *h;
|
|
||||||
|
|
||||||
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
h->flags |= P_PRESERVE;
|
|
||||||
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* REC_TOTAL -- Return the number of recno entries below a page.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* h: page
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* The number of recno entries below a page.
|
|
||||||
*
|
|
||||||
* XXX
|
|
||||||
* These values could be set by the bt_psplit routine. The problem is that the
|
|
||||||
* entry has to be popped off of the stack etc. or the values have to be passed
|
|
||||||
* all the way back to bt_split/bt_rroot and it's not very clean.
|
|
||||||
*/
|
|
||||||
static recno_t
|
|
||||||
rec_total(PAGE *h)
|
|
||||||
{
|
|
||||||
recno_t recs;
|
|
||||||
indx_t nxt, top;
|
|
||||||
|
|
||||||
for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt)
|
|
||||||
recs += GETRINTERNAL(h, nxt)->nrecs;
|
|
||||||
return (recs);
|
|
||||||
}
|
|
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_stack.c /main/3 1996/06/11 17:13:15 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_stack.c 8.1 (Berkeley) 6/4/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When a page splits, a new record has to be inserted into its parent page.
|
|
||||||
* This page may have to split as well, all the way up to the root. Since
|
|
||||||
* parent pointers in each page would be expensive, we maintain a stack of
|
|
||||||
* parent pages as we descend the tree.
|
|
||||||
*
|
|
||||||
* XXX
|
|
||||||
* This is a concurrency problem -- if user a builds a stack, then user b
|
|
||||||
* splits the tree, then user a tries to split the tree, there's a new level
|
|
||||||
* in the tree that user a doesn't know about.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_PUSH -- Push parent page info onto the stack (LIFO).
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* pgno: page
|
|
||||||
* index: page index
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_push(BTREE *t, pgno_t pgno, int index)
|
|
||||||
{
|
|
||||||
if (t->bt_sp == t->bt_maxstack) {
|
|
||||||
t->bt_maxstack += 50;
|
|
||||||
if ((t->bt_stack = __fix_realloc(t->bt_stack,
|
|
||||||
t->bt_maxstack * sizeof(EPGNO))) == NULL) {
|
|
||||||
t->bt_maxstack -= 50;
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t->bt_stack[t->bt_sp].pgno = pgno;
|
|
||||||
t->bt_stack[t->bt_sp].index = index;
|
|
||||||
++t->bt_sp;
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
|
@ -1,255 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: bt_utils.c /main/3 1996/06/11 17:13:20 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bt_utils.c 8.2 (Berkeley) 9/7/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#include "btree.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_RET -- Build return key/data pair as a result of search or scan.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* d: LEAF to be returned to the user.
|
|
||||||
* key: user's key structure (NULL if not to be filled in)
|
|
||||||
* data: user's data structure
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_SUCCESS, RET_ERROR.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_ret(BTREE *t, EPG *e, DBT *key, DBT *data)
|
|
||||||
{
|
|
||||||
BLEAF *bl;
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
bl = GETBLEAF(e->page, e->index);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We always copy big keys/data to make them contigous. Otherwise,
|
|
||||||
* we leave the page pinned and don't copy unless the user specified
|
|
||||||
* concurrent access.
|
|
||||||
*/
|
|
||||||
if (bl->flags & P_BIGDATA) {
|
|
||||||
if (__ovfl_get(t, bl->bytes + bl->ksize,
|
|
||||||
&data->size, &t->bt_dbuf, &t->bt_dbufsz))
|
|
||||||
return (RET_ERROR);
|
|
||||||
data->data = t->bt_dbuf;
|
|
||||||
} else if (ISSET(t, B_DB_LOCK)) {
|
|
||||||
/* Use +1 in case the first record retrieved is 0 length. */
|
|
||||||
if (bl->dsize + 1 > t->bt_dbufsz) {
|
|
||||||
if ((p = __fix_realloc(t->bt_dbuf, bl->dsize + 1)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
t->bt_dbuf = p;
|
|
||||||
t->bt_dbufsz = bl->dsize + 1;
|
|
||||||
}
|
|
||||||
memmove(t->bt_dbuf, bl->bytes + bl->ksize, bl->dsize);
|
|
||||||
data->size = bl->dsize;
|
|
||||||
data->data = t->bt_dbuf;
|
|
||||||
} else {
|
|
||||||
data->size = bl->dsize;
|
|
||||||
data->data = bl->bytes + bl->ksize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == NULL)
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
|
|
||||||
if (bl->flags & P_BIGKEY) {
|
|
||||||
if (__ovfl_get(t, bl->bytes,
|
|
||||||
&key->size, &t->bt_kbuf, &t->bt_kbufsz))
|
|
||||||
return (RET_ERROR);
|
|
||||||
key->data = t->bt_kbuf;
|
|
||||||
} else if (ISSET(t, B_DB_LOCK)) {
|
|
||||||
if (bl->ksize > t->bt_kbufsz) {
|
|
||||||
if ((p = __fix_realloc(t->bt_kbuf, bl->ksize)) == NULL)
|
|
||||||
return (RET_ERROR);
|
|
||||||
t->bt_kbuf = p;
|
|
||||||
t->bt_kbufsz = bl->ksize;
|
|
||||||
}
|
|
||||||
memmove(t->bt_kbuf, bl->bytes, bl->ksize);
|
|
||||||
key->size = bl->ksize;
|
|
||||||
key->data = t->bt_kbuf;
|
|
||||||
} else {
|
|
||||||
key->size = bl->ksize;
|
|
||||||
key->data = bl->bytes;
|
|
||||||
}
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_CMP -- Compare a key to a given record.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* t: tree
|
|
||||||
* k1: DBT pointer of first arg to comparison
|
|
||||||
* e: pointer to EPG for comparison
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* < 0 if k1 is < record
|
|
||||||
* = 0 if k1 is = record
|
|
||||||
* > 0 if k1 is > record
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_cmp(BTREE *t, const DBT *k1, EPG *e)
|
|
||||||
{
|
|
||||||
BINTERNAL *bi;
|
|
||||||
BLEAF *bl;
|
|
||||||
DBT k2;
|
|
||||||
PAGE *h;
|
|
||||||
void *bigkey;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The left-most key on internal pages, at any level of the tree, is
|
|
||||||
* guaranteed by the following code to be less than any user key.
|
|
||||||
* This saves us from having to update the leftmost key on an internal
|
|
||||||
* page when the user inserts a new key in the tree smaller than
|
|
||||||
* anything we've yet seen.
|
|
||||||
*/
|
|
||||||
h = e->page;
|
|
||||||
if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
bigkey = NULL;
|
|
||||||
if (h->flags & P_BLEAF) {
|
|
||||||
bl = GETBLEAF(h, e->index);
|
|
||||||
if (bl->flags & P_BIGKEY)
|
|
||||||
bigkey = bl->bytes;
|
|
||||||
else {
|
|
||||||
k2.data = bl->bytes;
|
|
||||||
k2.size = bl->ksize;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bi = GETBINTERNAL(h, e->index);
|
|
||||||
if (bi->flags & P_BIGKEY)
|
|
||||||
bigkey = bi->bytes;
|
|
||||||
else {
|
|
||||||
k2.data = bi->bytes;
|
|
||||||
k2.size = bi->ksize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bigkey) {
|
|
||||||
if (__ovfl_get(t, bigkey,
|
|
||||||
&k2.size, &t->bt_dbuf, &t->bt_dbufsz))
|
|
||||||
return (RET_ERROR);
|
|
||||||
k2.data = t->bt_dbuf;
|
|
||||||
}
|
|
||||||
return ((*t->bt_cmp)(k1, &k2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_DEFCMP -- Default comparison routine.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* a: DBT #1
|
|
||||||
* b: DBT #2
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* < 0 if a is < b
|
|
||||||
* = 0 if a is = b
|
|
||||||
* > 0 if a is > b
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_defcmp(const DBT *a, const DBT *b)
|
|
||||||
{
|
|
||||||
u_char *p1, *p2;
|
|
||||||
int diff, len;
|
|
||||||
|
|
||||||
len = MIN(a->size, b->size);
|
|
||||||
for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
|
|
||||||
if ((diff = *p1 - *p2))
|
|
||||||
return (diff);
|
|
||||||
return (a->size - b->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __BT_DEFPFX -- Default prefix routine.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* a: DBT #1
|
|
||||||
* b: DBT #2
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Number of bytes needed to distinguish b from a.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
__bt_defpfx(const DBT *a, const DBT *b)
|
|
||||||
{
|
|
||||||
u_char *p1, *p2;
|
|
||||||
int len;
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
cnt = 1;
|
|
||||||
len = MIN(a->size, b->size);
|
|
||||||
for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
|
|
||||||
if (*p1 != *p2)
|
|
||||||
return (cnt);
|
|
||||||
|
|
||||||
/* a->size must be <= b->size, or they wouldn't be in this order. */
|
|
||||||
return (a->size < b->size ? a->size + 1 : a->size);
|
|
||||||
}
|
|
|
@ -1,374 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: btree.h /main/5 1996/07/18 16:31:58 drk $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Mike Olson.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*
|
|
||||||
* @(#)btree.h 8.2 (Berkeley) 9/7/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <mpool.h>
|
|
||||||
|
|
||||||
#define DEFMINKEYPAGE (2) /* Minimum keys per page */
|
|
||||||
#define MINCACHE (5) /* Minimum cached pages */
|
|
||||||
#define MINPSIZE (512) /* Minimum page size */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Page 0 of a btree file contains a copy of the meta-data. This page is also
|
|
||||||
* used as an out-of-band page, i.e. page pointers that point to nowhere point
|
|
||||||
* to page 0. Page 1 is the root of the btree.
|
|
||||||
*/
|
|
||||||
#define P_INVALID 0 /* Invalid tree page number. */
|
|
||||||
#define P_META 0 /* Tree metadata page number. */
|
|
||||||
#define P_ROOT 1 /* Tree root page number. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* There are five page layouts in the btree: btree internal pages (BINTERNAL),
|
|
||||||
* btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages
|
|
||||||
* (RLEAF) and overflow pages. All five page types have a page header (PAGE).
|
|
||||||
* This implementation requires that longs within structures are NOT padded.
|
|
||||||
* (ANSI C permits random padding.) If your compiler pads randomly you'll have
|
|
||||||
* to do some work to get this package to run.
|
|
||||||
*/
|
|
||||||
typedef struct _page {
|
|
||||||
pgno_t pgno; /* this page's page number */
|
|
||||||
pgno_t prevpg; /* left sibling */
|
|
||||||
pgno_t nextpg; /* right sibling */
|
|
||||||
|
|
||||||
#define P_BINTERNAL 0x01 /* btree internal page */
|
|
||||||
#define P_BLEAF 0x02 /* leaf page */
|
|
||||||
#define P_OVERFLOW 0x04 /* overflow page */
|
|
||||||
#define P_RINTERNAL 0x08 /* recno internal page */
|
|
||||||
#define P_RLEAF 0x10 /* leaf page */
|
|
||||||
#define P_TYPE 0x1f /* type mask */
|
|
||||||
|
|
||||||
#define P_PRESERVE 0x20 /* never delete this chain of pages */
|
|
||||||
u_long flags;
|
|
||||||
|
|
||||||
indx_t lower; /* lower bound of free space on page */
|
|
||||||
indx_t upper; /* upper bound of free space on page */
|
|
||||||
indx_t linp[1]; /* long-aligned VARIABLE LENGTH DATA */
|
|
||||||
} PAGE;
|
|
||||||
|
|
||||||
/* First and next index. */
|
|
||||||
#define BTDATAOFF (sizeof(pgno_t) + sizeof(pgno_t) + sizeof(pgno_t) + \
|
|
||||||
sizeof(u_long) + sizeof(indx_t) + sizeof(indx_t))
|
|
||||||
#define NEXTINDEX(p) (((p)->lower - BTDATAOFF) / sizeof(indx_t))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For pages other than overflow pages, there is an array of offsets into the
|
|
||||||
* rest of the page immediately following the page header. Each offset is to
|
|
||||||
* an item which is unique to the type of page. The h_lower offset is just
|
|
||||||
* past the last filled-in index. The h_upper offset is the first item on the
|
|
||||||
* page. Offsets are from the beginning of the page.
|
|
||||||
*
|
|
||||||
* If an item is too big to store on a single page, a flag is set and the item
|
|
||||||
* is a { page, size } pair such that the page is the first page of an overflow
|
|
||||||
* chain with size bytes of item. Overflow pages are simply bytes without any
|
|
||||||
* external structure.
|
|
||||||
*
|
|
||||||
* The size and page number fields in the items are long aligned so they can be
|
|
||||||
* manipulated without copying.
|
|
||||||
*/
|
|
||||||
#define LALIGN(n) (((n) + sizeof(u_long) - 1) & ~(sizeof(u_long) - 1))
|
|
||||||
#define NOVFLSIZE (sizeof(pgno_t) + sizeof(size_t))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For the btree internal pages, the item is a key. BINTERNALs are {key, pgno}
|
|
||||||
* pairs, such that the key compares less than or equal to all of the records
|
|
||||||
* on that page. For a tree without duplicate keys, an internal page with two
|
|
||||||
* consecutive keys, a and b, will have all records greater than or equal to a
|
|
||||||
* and less than b stored on the page associated with a. Duplicate keys are
|
|
||||||
* somewhat special and can cause duplicate internal and leaf page records and
|
|
||||||
* some minor modifications of the above rule.
|
|
||||||
*/
|
|
||||||
typedef struct _binternal {
|
|
||||||
size_t ksize; /* key size */
|
|
||||||
pgno_t pgno; /* page number stored on */
|
|
||||||
#define P_BIGDATA 0x01 /* overflow data */
|
|
||||||
#define P_BIGKEY 0x02 /* overflow key */
|
|
||||||
u_char flags;
|
|
||||||
char bytes[1]; /* data */
|
|
||||||
} BINTERNAL;
|
|
||||||
|
|
||||||
/* Get the page's BINTERNAL structure at index indx. */
|
|
||||||
#define GETBINTERNAL(pg, indx) \
|
|
||||||
((BINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
|
|
||||||
|
|
||||||
/* Get the number of bytes in the entry. */
|
|
||||||
#define NBINTERNAL(len) \
|
|
||||||
LALIGN(sizeof(size_t) + sizeof(pgno_t) + sizeof(u_char) + (len))
|
|
||||||
|
|
||||||
/* Copy a BINTERNAL entry to the page. */
|
|
||||||
#define WR_BINTERNAL(p, size, pgno, flags) { \
|
|
||||||
*(size_t *)p = size; \
|
|
||||||
p += sizeof(size_t); \
|
|
||||||
*(pgno_t *)p = pgno; \
|
|
||||||
p += sizeof(pgno_t); \
|
|
||||||
*(u_char *)p = flags; \
|
|
||||||
p += sizeof(u_char); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For the recno internal pages, the item is a page number with the number of
|
|
||||||
* keys found on that page and below.
|
|
||||||
*/
|
|
||||||
typedef struct _rinternal {
|
|
||||||
recno_t nrecs; /* number of records */
|
|
||||||
pgno_t pgno; /* page number stored below */
|
|
||||||
} RINTERNAL;
|
|
||||||
|
|
||||||
/* Get the page's RINTERNAL structure at index indx. */
|
|
||||||
#define GETRINTERNAL(pg, indx) \
|
|
||||||
((RINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
|
|
||||||
|
|
||||||
/* Get the number of bytes in the entry. */
|
|
||||||
#define NRINTERNAL \
|
|
||||||
LALIGN(sizeof(recno_t) + sizeof(pgno_t))
|
|
||||||
|
|
||||||
/* Copy a RINTERAL entry to the page. */
|
|
||||||
#define WR_RINTERNAL(p, nrecs, pgno) { \
|
|
||||||
*(recno_t *)p = nrecs; \
|
|
||||||
p += sizeof(recno_t); \
|
|
||||||
*(pgno_t *)p = pgno; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For the btree leaf pages, the item is a key and data pair. */
|
|
||||||
typedef struct _bleaf {
|
|
||||||
size_t ksize; /* size of key */
|
|
||||||
size_t dsize; /* size of data */
|
|
||||||
u_char flags; /* P_BIGDATA, P_BIGKEY */
|
|
||||||
char bytes[1]; /* data */
|
|
||||||
} BLEAF;
|
|
||||||
|
|
||||||
/* Get the page's BLEAF structure at index indx. */
|
|
||||||
#define GETBLEAF(pg, indx) \
|
|
||||||
((BLEAF *)((char *)(pg) + (pg)->linp[indx]))
|
|
||||||
|
|
||||||
/* Get the number of bytes in the entry. */
|
|
||||||
#define NBLEAF(p) NBLEAFDBT((p)->ksize, (p)->dsize)
|
|
||||||
|
|
||||||
/* Get the number of bytes in the user's key/data pair. */
|
|
||||||
#define NBLEAFDBT(ksize, dsize) \
|
|
||||||
LALIGN(sizeof(size_t) + sizeof(size_t) + sizeof(u_char) + \
|
|
||||||
(ksize) + (dsize))
|
|
||||||
|
|
||||||
/* Copy a BLEAF entry to the page. */
|
|
||||||
#define WR_BLEAF(p, key, data, flags) { \
|
|
||||||
*(size_t *)p = key->size; \
|
|
||||||
p += sizeof(size_t); \
|
|
||||||
*(size_t *)p = data->size; \
|
|
||||||
p += sizeof(size_t); \
|
|
||||||
*(u_char *)p = flags; \
|
|
||||||
p += sizeof(u_char); \
|
|
||||||
memmove(p, key->data, key->size); \
|
|
||||||
p += key->size; \
|
|
||||||
memmove(p, data->data, data->size); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For the recno leaf pages, the item is a data entry. */
|
|
||||||
typedef struct _rleaf {
|
|
||||||
size_t dsize; /* size of data */
|
|
||||||
u_char flags; /* P_BIGDATA */
|
|
||||||
char bytes[1];
|
|
||||||
} RLEAF;
|
|
||||||
|
|
||||||
/* Get the page's RLEAF structure at index indx. */
|
|
||||||
#define GETRLEAF(pg, indx) \
|
|
||||||
((RLEAF *)((char *)(pg) + (pg)->linp[indx]))
|
|
||||||
|
|
||||||
/* Get the number of bytes in the entry. */
|
|
||||||
#define NRLEAF(p) NRLEAFDBT((p)->dsize)
|
|
||||||
|
|
||||||
/* Get the number of bytes from the user's data. */
|
|
||||||
#define NRLEAFDBT(dsize) \
|
|
||||||
LALIGN(sizeof(size_t) + sizeof(u_char) + (dsize))
|
|
||||||
|
|
||||||
/* Copy a RLEAF entry to the page. */
|
|
||||||
#define WR_RLEAF(p, data, flags) { \
|
|
||||||
*(size_t *)p = data->size; \
|
|
||||||
p += sizeof(size_t); \
|
|
||||||
*(u_char *)p = flags; \
|
|
||||||
p += sizeof(u_char); \
|
|
||||||
memmove(p, data->data, data->size); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A record in the tree is either a pointer to a page and an index in the page
|
|
||||||
* or a page number and an index. These structures are used as a cursor, stack
|
|
||||||
* entry and search returns as well as to pass records to other routines.
|
|
||||||
*
|
|
||||||
* One comment about searches. Internal page searches must find the largest
|
|
||||||
* record less than key in the tree so that descents work. Leaf page searches
|
|
||||||
* must find the smallest record greater than key so that the returned index
|
|
||||||
* is the record's correct position for insertion.
|
|
||||||
*
|
|
||||||
* One comment about cursors. The cursor key is never removed from the tree,
|
|
||||||
* even if deleted. This is because it is quite difficult to decide where the
|
|
||||||
* cursor should be when other keys have been inserted/deleted in the tree;
|
|
||||||
* duplicate keys make it impossible. This scheme does require extra work
|
|
||||||
* though, to make sure that we don't perform an operation on a deleted key.
|
|
||||||
*/
|
|
||||||
typedef struct _epgno {
|
|
||||||
pgno_t pgno; /* the page number */
|
|
||||||
indx_t index; /* the index on the page */
|
|
||||||
} EPGNO;
|
|
||||||
|
|
||||||
typedef struct _epg {
|
|
||||||
PAGE *page; /* the (pinned) page */
|
|
||||||
indx_t index; /* the index on the page */
|
|
||||||
} EPG;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The metadata of the tree. The m_nrecs field is used only by the RECNO code.
|
|
||||||
* This is because the btree doesn't really need it and it requires that every
|
|
||||||
* put or delete call modify the metadata.
|
|
||||||
*/
|
|
||||||
typedef struct _btmeta {
|
|
||||||
u_long m_magic; /* magic number */
|
|
||||||
u_long m_version; /* version */
|
|
||||||
u_long m_psize; /* page size */
|
|
||||||
u_long m_free; /* page number of first free page */
|
|
||||||
u_long m_nrecs; /* R: number of records */
|
|
||||||
#define SAVEMETA (B_NODUPS | R_RECNO)
|
|
||||||
u_long m_flags; /* bt_flags & SAVEMETA */
|
|
||||||
u_long m_unused; /* unused */
|
|
||||||
} BTMETA;
|
|
||||||
|
|
||||||
/* The in-memory btree/recno data structure. */
|
|
||||||
typedef struct _btree {
|
|
||||||
MPOOL *bt_mp; /* memory pool cookie */
|
|
||||||
|
|
||||||
DB *bt_dbp; /* pointer to enclosing DB */
|
|
||||||
|
|
||||||
PAGE *bt_pinned; /* page pinned across calls */
|
|
||||||
|
|
||||||
EPGNO bt_bcursor; /* B: btree cursor */
|
|
||||||
recno_t bt_rcursor; /* R: recno cursor (1-based) */
|
|
||||||
|
|
||||||
#define BT_POP(t) (t->bt_sp ? t->bt_stack + --t->bt_sp : NULL)
|
|
||||||
#define BT_CLR(t) (t->bt_sp = 0)
|
|
||||||
EPGNO *bt_stack; /* stack of parent pages */
|
|
||||||
u_int bt_sp; /* current stack pointer */
|
|
||||||
u_int bt_maxstack; /* largest stack */
|
|
||||||
|
|
||||||
char *bt_kbuf; /* key buffer */
|
|
||||||
size_t bt_kbufsz; /* key buffer size */
|
|
||||||
char *bt_dbuf; /* data buffer */
|
|
||||||
size_t bt_dbufsz; /* data buffer size */
|
|
||||||
|
|
||||||
int bt_fd; /* tree file descriptor */
|
|
||||||
|
|
||||||
pgno_t bt_free; /* next free page */
|
|
||||||
u_long bt_psize; /* page size */
|
|
||||||
indx_t bt_ovflsize; /* cut-off for key/data overflow */
|
|
||||||
int bt_lorder; /* byte order */
|
|
||||||
/* sorted order */
|
|
||||||
enum { NOT, BACK, FORWARD } bt_order;
|
|
||||||
EPGNO bt_last; /* last insert */
|
|
||||||
|
|
||||||
/* B: key comparison function */
|
|
||||||
int (*bt_cmp) __P((const DBT *, const DBT *));
|
|
||||||
/* B: prefix comparison function */
|
|
||||||
int (*bt_pfx) __P((const DBT *, const DBT *));
|
|
||||||
/* R: recno input function */
|
|
||||||
int (*bt_irec) __P((struct _btree *, recno_t));
|
|
||||||
|
|
||||||
FILE *bt_rfp; /* R: record FILE pointer */
|
|
||||||
int bt_rfd; /* R: record file descriptor */
|
|
||||||
|
|
||||||
caddr_t bt_cmap; /* R: current point in mapped space */
|
|
||||||
caddr_t bt_smap; /* R: start of mapped space */
|
|
||||||
caddr_t bt_emap; /* R: end of mapped space */
|
|
||||||
size_t bt_msize; /* R: size of mapped region. */
|
|
||||||
|
|
||||||
recno_t bt_nrecs; /* R: number of records */
|
|
||||||
size_t bt_reclen; /* R: fixed record length */
|
|
||||||
u_char bt_bval; /* R: delimiting byte/pad character */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NB:
|
|
||||||
* B_NODUPS and R_RECNO are stored on disk, and may not be changed.
|
|
||||||
*/
|
|
||||||
#define B_DELCRSR 0x00001 /* cursor has been deleted */
|
|
||||||
#define B_INMEM 0x00002 /* in-memory tree */
|
|
||||||
#define B_METADIRTY 0x00004 /* need to write metadata */
|
|
||||||
#define B_MODIFIED 0x00008 /* tree modified */
|
|
||||||
#define B_NEEDSWAP 0x00010 /* if byte order requires swapping */
|
|
||||||
#define B_NODUPS 0x00020 /* no duplicate keys permitted */
|
|
||||||
#define B_RDONLY 0x00040 /* read-only tree */
|
|
||||||
#define R_RECNO 0x00080 /* record oriented tree */
|
|
||||||
#define B_SEQINIT 0x00100 /* sequential scan initialized */
|
|
||||||
|
|
||||||
#define R_CLOSEFP 0x00200 /* opened a file pointer */
|
|
||||||
#define R_EOF 0x00400 /* end of input file reached. */
|
|
||||||
#define R_FIXLEN 0x00800 /* fixed length records */
|
|
||||||
#define R_MEMMAPPED 0x01000 /* memory mapped file. */
|
|
||||||
#define R_INMEM 0x02000 /* in-memory file */
|
|
||||||
#define R_MODIFIED 0x04000 /* modified file */
|
|
||||||
#define R_RDONLY 0x08000 /* read-only file */
|
|
||||||
|
|
||||||
#define B_DB_LOCK 0x10000 /* DB_LOCK specified. */
|
|
||||||
#define B_DB_SHMEM 0x20000 /* DB_SHMEM specified. */
|
|
||||||
#define B_DB_TXN 0x40000 /* DB_TXN specified. */
|
|
||||||
|
|
||||||
u_long bt_flags; /* btree state */
|
|
||||||
} BTREE;
|
|
||||||
|
|
||||||
#define SET(t, f) ((t)->bt_flags |= (f))
|
|
||||||
#define CLR(t, f) ((t)->bt_flags &= ~(f))
|
|
||||||
#define ISSET(t, f) ((t)->bt_flags & (f))
|
|
||||||
|
|
||||||
#include "extern.h"
|
|
|
@ -1,134 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: cdefs.h /main/4 1996/06/11 17:13:31 cde-hal $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*
|
|
||||||
* @(#)cdefs.h 8.1 (Berkeley) 6/2/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _CDEFS_H_
|
|
||||||
#define _CDEFS_H_
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
#ifndef __BEGIN_DECLS
|
|
||||||
#define __BEGIN_DECLS extern "C" {
|
|
||||||
#endif
|
|
||||||
#ifndef __END_DECLS
|
|
||||||
#define __END_DECLS };
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#undef __BEGIN_DECLS
|
|
||||||
#define __BEGIN_DECLS
|
|
||||||
#undef __END_DECLS
|
|
||||||
#define __END_DECLS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
|
|
||||||
* with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
|
|
||||||
* The __CONCAT macro is a bit tricky -- make sure you don't put spaces
|
|
||||||
* in between its arguments. __CONCAT can also concatenate double-quoted
|
|
||||||
* strings produced by the __STRING macro, but this only works with ANSI C.
|
|
||||||
*/
|
|
||||||
#if defined(__STDC__) || defined(__cplusplus)
|
|
||||||
#ifdef __P
|
|
||||||
#undef __P
|
|
||||||
#endif
|
|
||||||
#define __P(protos) protos /* full-blown ANSI C */
|
|
||||||
#ifndef __CONCAT
|
|
||||||
#define __CONCAT(x,y) x ## y
|
|
||||||
#endif
|
|
||||||
#define __STRING(x) #x
|
|
||||||
|
|
||||||
#else /* !(__STDC__ || __cplusplus) */
|
|
||||||
#ifdef __P
|
|
||||||
#undef __P
|
|
||||||
#endif
|
|
||||||
#define __P(protos) () /* traditional C preprocessor */
|
|
||||||
#define __CONCAT(x,y) x/**/y
|
|
||||||
#define __STRING(x) "x"
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define const __const /* GCC: ANSI C with -traditional */
|
|
||||||
#define inline __inline
|
|
||||||
#define signed __signed
|
|
||||||
#define volatile __volatile
|
|
||||||
|
|
||||||
#else /* !__GNUC__ */
|
|
||||||
#define const /* delete ANSI C keywords */
|
|
||||||
#define inline
|
|
||||||
#define signed
|
|
||||||
#define volatile
|
|
||||||
#endif /* !__GNUC__ */
|
|
||||||
#endif /* !(__STDC__ || __cplusplus) */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GCC has extensions for declaring functions as `pure' (always returns
|
|
||||||
* the same value given the same inputs, i.e., has no external state and
|
|
||||||
* no side effects) and `dead' (nonreturning). These mainly affect
|
|
||||||
* optimization and warnings. Unfortunately, GCC complains if these are
|
|
||||||
* used under strict ANSI mode (`gcc -ansi -pedantic'), hence we need to
|
|
||||||
* define them only if compiling without this.
|
|
||||||
*/
|
|
||||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
|
||||||
#undef __dead
|
|
||||||
#define __dead __volatile
|
|
||||||
#ifndef __pure
|
|
||||||
#define __pure __const
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define __dead
|
|
||||||
#define __pure
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !_CDEFS_H_ */
|
|
|
@ -1,254 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: compat.h /main/8 1996/07/18 16:32:14 drk $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*
|
|
||||||
* @(#)compat.h 8.3 (Berkeley) 9/6/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _COMPAT_H_
|
|
||||||
#define _COMPAT_H_
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "utility/config.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If your system doesn't typedef u_long, u_short, or u_char, change
|
|
||||||
* the 0 to a 1.
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
typedef unsigned long u_long;
|
|
||||||
typedef unsigned short u_short;
|
|
||||||
typedef unsigned char u_char;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If your system doesn't typedef size_t, change the 0 to a 1. */
|
|
||||||
#if 0
|
|
||||||
typedef unsigned int size_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If your system doesn't have the POSIX type for a signal mask,
|
|
||||||
* change the 0 to a 1.
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
typedef unsigned int sigset_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If you don't have POSIX 1003.1 signals, the signal code surrounding the
|
|
||||||
* temporary file creation is intended to block all of the possible signals
|
|
||||||
* long enough to create the file and unlink it. All of this stuff is
|
|
||||||
* intended to use old-style BSD calls to fake POSIX 1003.1 calls.
|
|
||||||
*/
|
|
||||||
#ifdef NO_POSIX_SIGNALS
|
|
||||||
#define sigemptyset(set) (*(set) = 0)
|
|
||||||
#define sigfillset(set) (*(set) = ~(sigset_t)0, 0)
|
|
||||||
#define sigaddset(set,signo) (*(set) |= sigmask(signo), 0)
|
|
||||||
#define sigdelset(set,signo) (*(set) &= ~sigmask(signo), 0)
|
|
||||||
#define sigismember(set,signo) ((*(set) & sigmask(signo)) != 0)
|
|
||||||
|
|
||||||
#define SIG_BLOCK 1
|
|
||||||
#define SIG_UNBLOCK 2
|
|
||||||
#define SIG_SETMASK 3
|
|
||||||
|
|
||||||
static int __sigtemp; /* For the use of sigprocmask */
|
|
||||||
|
|
||||||
/* Repeated test of oset != NULL is to avoid "*0". */
|
|
||||||
#define sigprocmask(how, set, oset) \
|
|
||||||
((__sigtemp = \
|
|
||||||
(((how) == SIG_BLOCK) ? \
|
|
||||||
sigblock(0) | *(set) : \
|
|
||||||
(((how) == SIG_UNBLOCK) ? \
|
|
||||||
sigblock(0) & ~(*(set)) : \
|
|
||||||
((how) == SIG_SETMASK ? \
|
|
||||||
*(set) : sigblock(0))))), \
|
|
||||||
((oset) ? (*(oset ? oset : set) = sigsetmask(__sigtemp)) : \
|
|
||||||
sigsetmask(__sigtemp)), 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If realloc(3) of a NULL pointer on your system isn't the same as
|
|
||||||
* a malloc(3) call, change the 0 to a 1, and add realloc.o to the
|
|
||||||
* MISC line in your Makefile.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
#if 1
|
|
||||||
#define realloc __fix_realloc
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
void * __fix_realloc __P((void*, size_t));
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If your system doesn't have an include file with the appropriate
|
|
||||||
* byte order set, make sure you specify the correct one.
|
|
||||||
*/
|
|
||||||
#ifndef BYTE_ORDER
|
|
||||||
|
|
||||||
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */
|
|
||||||
#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */
|
|
||||||
|
|
||||||
#ifdef MMDB_LITTLE_ENDIAN
|
|
||||||
#define BYTE_ORDER LITTLE_ENDIAN /* Set for your system. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MMDB_BIG_ENDIAN
|
|
||||||
#define BYTE_ORDER BIG_ENDIAN /* Set for your system. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SYSV) || defined(SYSTEM5) || defined(SVR4)
|
|
||||||
/* #define index(a, b) strchr(a, b) */
|
|
||||||
#ifndef rindex
|
|
||||||
#define rindex(a, b) strrchr(a, b)
|
|
||||||
#endif
|
|
||||||
#define bzero(a, b) memset(a, 0, b)
|
|
||||||
#define bcmp(a, b, n) memcmp(a, b, n)
|
|
||||||
#define bcopy(a, b, n) memmove(b, a, n)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(BSD) || defined(BSD4_3)
|
|
||||||
#define strchr(a, b) index(a, b)
|
|
||||||
#define strrchr(a, b) rindex(a, b)
|
|
||||||
#define memcmp(a, b, n) bcmp(a, b, n)
|
|
||||||
#define memmove(a, b, n) bcopy(b, a, n)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 32-bit machine. The db routines are theoretically independent of
|
|
||||||
* the size of u_shorts and u_longs, but I don't know that anyone has
|
|
||||||
* ever actually tried it. At a minimum, change the following #define's
|
|
||||||
* if you are trying to compile on a different type of system.
|
|
||||||
*/
|
|
||||||
#ifndef USHRT_MAX
|
|
||||||
#define USHRT_MAX 0xFFFF
|
|
||||||
#define ULONG_MAX 0xFFFFFFFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* POSIX 1003.1 access mode mask. */
|
|
||||||
#ifndef O_ACCMODE
|
|
||||||
#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* POSIX 1003.2 RE limit. */
|
|
||||||
#ifndef _POSIX2_RE_DUP_MAX
|
|
||||||
#define _POSIX2_RE_DUP_MAX 255
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If you can't provide lock values in the open(2) call. Note, this
|
|
||||||
* allows races to happen.
|
|
||||||
*/
|
|
||||||
#ifndef O_EXLOCK
|
|
||||||
#define O_EXLOCK 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef O_SHLOCK
|
|
||||||
#define O_SHLOCK 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EFTYPE
|
|
||||||
#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WCOREDUMP /* 4.4BSD extension */
|
|
||||||
#define WCOREDUMP(a) 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef STDERR_FILENO
|
|
||||||
#define STDIN_FILENO 0 /* ANSI C #defines */
|
|
||||||
#define STDOUT_FILENO 1
|
|
||||||
#define STDERR_FILENO 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SEEK_END
|
|
||||||
#define SEEK_SET 0 /* POSIX 1003.1 seek values */
|
|
||||||
#define SEEK_CUR 1
|
|
||||||
#define SEEK_END 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef S_ISLNK /* BSD POSIX 1003.1 extensions */
|
|
||||||
#define S_ISLNK(m) ((m & 0170000) == 0120000)
|
|
||||||
#define S_ISSOCK(m) ((m & 0170000) == 0140000)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TCSASOFT
|
|
||||||
#define TCSASOFT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _POSIX2_RE_DUP_MAX
|
|
||||||
#define _POSIX2_RE_DUP_MAX 255
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NULL /* ANSI C #defines NULL everywhere. */
|
|
||||||
#define NULL 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef MAX
|
|
||||||
#define MAX(a,b) ((a)<(b)?(b):(a))
|
|
||||||
|
|
||||||
#undef MIN
|
|
||||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
|
||||||
|
|
||||||
#ifndef DEFFILEMODE /* Default file permissions. */
|
|
||||||
#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _BSD_VA_LIST_
|
|
||||||
#define _BSD_VA_LIST_ char *
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !_COMPAT_H_ */
|
|
|
@ -1,122 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: db.c /main/3 1996/06/11 17:13:41 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)db.c 8.2 (Berkeley) 9/7/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define __DBINTERFACE_PRIVATE
|
|
||||||
#include <db.h>
|
|
||||||
|
|
||||||
DB *
|
|
||||||
dbopen(const char *fname, int flags, int mode, DBTYPE type, const void *openinfo)
|
|
||||||
{
|
|
||||||
|
|
||||||
#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN)
|
|
||||||
#define USE_OPEN_FLAGS \
|
|
||||||
(O_CREAT | O_EXCL | O_EXLOCK | O_RDONLY | O_RDWR | \
|
|
||||||
O_SHLOCK | O_TRUNC)
|
|
||||||
|
|
||||||
if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
|
|
||||||
switch (type) {
|
|
||||||
case DB_BTREE:
|
|
||||||
return (__bt_open(fname, flags & USE_OPEN_FLAGS,
|
|
||||||
mode, openinfo, flags & DB_FLAGS));
|
|
||||||
/*
|
|
||||||
case DB_HASH:
|
|
||||||
return (__hash_open(fname, flags & USE_OPEN_FLAGS,
|
|
||||||
mode, openinfo, flags & DB_FLAGS));
|
|
||||||
case DB_RECNO:
|
|
||||||
return (__rec_open(fname, flags & USE_OPEN_FLAGS,
|
|
||||||
mode, openinfo, flags & DB_FLAGS));
|
|
||||||
*/
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
errno = EINVAL;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
__dberr(void)
|
|
||||||
{
|
|
||||||
return (RET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __DBPANIC -- Stop.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* dbp: pointer to the DB structure.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
__dbpanic(DB *dbp)
|
|
||||||
{
|
|
||||||
/* The only thing that can succeed is a close. */
|
|
||||||
dbp->del = (int (*)())__dberr;
|
|
||||||
dbp->fd = (int (*)())__dberr;
|
|
||||||
dbp->get = (int (*)())__dberr;
|
|
||||||
dbp->put = (int (*)())__dberr;
|
|
||||||
dbp->seq = (int (*)())__dberr;
|
|
||||||
dbp->sync = (int (*)())__dberr;
|
|
||||||
}
|
|
|
@ -1,249 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: db.h /main/3 1996/06/11 17:13:46 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*
|
|
||||||
* @(#)db.h 8.2 (Berkeley) 9/7/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _DB_H_
|
|
||||||
#define _DB_H_
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "cdefs.h"
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include "compat.h"
|
|
||||||
|
|
||||||
#define RET_ERROR -1 /* Return values. */
|
|
||||||
#define RET_SUCCESS 0
|
|
||||||
#define RET_SPECIAL 1
|
|
||||||
|
|
||||||
#define MAX_PAGE_NUMBER ULONG_MAX /* >= # of pages in a file */
|
|
||||||
typedef u_long pgno_t;
|
|
||||||
#define MAX_PAGE_OFFSET USHRT_MAX /* >= # of bytes in a page */
|
|
||||||
typedef u_short indx_t;
|
|
||||||
#define MAX_REC_NUMBER ULONG_MAX /* >= # of records in a tree */
|
|
||||||
typedef u_long recno_t;
|
|
||||||
|
|
||||||
/* Key/data structure -- a Data-Base Thang. */
|
|
||||||
typedef struct {
|
|
||||||
void *data; /* data */
|
|
||||||
size_t size; /* data length */
|
|
||||||
} DBT;
|
|
||||||
|
|
||||||
/* Routine flags. */
|
|
||||||
#define R_CURSOR 1 /* del, put, seq */
|
|
||||||
#define __R_UNUSED 2 /* UNUSED */
|
|
||||||
#define R_FIRST 3 /* seq */
|
|
||||||
#define R_IAFTER 4 /* put (RECNO) */
|
|
||||||
#define R_IBEFORE 5 /* put (RECNO) */
|
|
||||||
#define R_LAST 6 /* seq (BTREE, RECNO) */
|
|
||||||
#define R_NEXT 7 /* seq */
|
|
||||||
#define R_NOOVERWRITE 8 /* put */
|
|
||||||
#define R_PREV 9 /* seq (BTREE, RECNO) */
|
|
||||||
#define R_SETCURSOR 10 /* put (RECNO) */
|
|
||||||
#define R_RECNOSYNC 11 /* sync (RECNO) */
|
|
||||||
|
|
||||||
typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* !!!
|
|
||||||
* The following flags are included in the dbopen(3) call as part of the
|
|
||||||
* open(2) flags. In order to avoid conflicts with the open flags, start
|
|
||||||
* at the top of the 16 or 32-bit number space and work our way down. If
|
|
||||||
* the open flags were significantly expanded in the future, it could be
|
|
||||||
* a problem. Wish I'd left another flags word in the dbopen call.
|
|
||||||
*
|
|
||||||
* !!!
|
|
||||||
* None of this stuff is implemented yet. The only reason that it's here
|
|
||||||
* is so that the access methods can skip copying the key/data pair when
|
|
||||||
* the DB_LOCK flag isn't set.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
assume 32 bit UINT.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
#if UINT_MAX > 65535
|
|
||||||
*/
|
|
||||||
#define DB_LOCK 0x20000000 /* Do locking. */
|
|
||||||
#define DB_SHMEM 0x40000000 /* Use shared memory. */
|
|
||||||
#define DB_TXN 0x80000000 /* Do transactions. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
#else
|
|
||||||
#define DB_LOCK 0x00002000
|
|
||||||
#define DB_SHMEM 0x00004000
|
|
||||||
#define DB_TXN 0x00008000
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Access method description structure. */
|
|
||||||
typedef struct __db {
|
|
||||||
DBTYPE type; /* Underlying db type. */
|
|
||||||
int (*close) __P((struct __db *));
|
|
||||||
int (*del) __P((const struct __db *, const DBT *, u_int));
|
|
||||||
int (*fd) __P((const struct __db *));
|
|
||||||
int (*get) __P((const struct __db *, const DBT *, DBT *, u_int));
|
|
||||||
int (*put) __P((const struct __db *, DBT *, const DBT *, u_int));
|
|
||||||
int (*seq) __P((const struct __db *, DBT *, DBT *, u_int));
|
|
||||||
int (*sync) __P((const struct __db *, u_int));
|
|
||||||
void *internal; /* access method private */
|
|
||||||
} DB;
|
|
||||||
|
|
||||||
#define BTREEMAGIC 0x053162
|
|
||||||
#define BTREEVERSION 3
|
|
||||||
|
|
||||||
/* Structure used to pass parameters to the btree routines. */
|
|
||||||
typedef struct {
|
|
||||||
#define R_DUP 0x01 /* duplicate keys */
|
|
||||||
u_long flags;
|
|
||||||
int cachesize; /* bytes to cache */
|
|
||||||
int maxkeypage; /* maximum keys per page */
|
|
||||||
int minkeypage; /* minimum keys per page */
|
|
||||||
int psize; /* page size */
|
|
||||||
/* comparison, prefix functions */
|
|
||||||
int (*compare) __P((const DBT *, const DBT *));
|
|
||||||
int (*prefix) __P((const DBT *, const DBT *));
|
|
||||||
int lorder; /* byte order */
|
|
||||||
} BTREEINFO;
|
|
||||||
|
|
||||||
#define HASHMAGIC 0x061561
|
|
||||||
#define HASHVERSION 2
|
|
||||||
|
|
||||||
/* Structure used to pass parameters to the hashing routines. */
|
|
||||||
typedef struct {
|
|
||||||
int bsize; /* bucket size */
|
|
||||||
int ffactor; /* fill factor */
|
|
||||||
int nelem; /* number of elements */
|
|
||||||
int cachesize; /* bytes to cache */
|
|
||||||
/* hash function */
|
|
||||||
int (*hash) __P((const void *, size_t));
|
|
||||||
int lorder; /* byte order */
|
|
||||||
} HASHINFO;
|
|
||||||
|
|
||||||
/* Structure used to pass parameters to the record routines. */
|
|
||||||
typedef struct {
|
|
||||||
#define R_FIXEDLEN 0x01 /* fixed-length records */
|
|
||||||
#define R_NOKEY 0x02 /* key not required */
|
|
||||||
#define R_SNAPSHOT 0x04 /* snapshot the input */
|
|
||||||
u_long flags;
|
|
||||||
int cachesize; /* bytes to cache */
|
|
||||||
int psize; /* page size */
|
|
||||||
int lorder; /* byte order */
|
|
||||||
size_t reclen; /* record length (fixed-length records) */
|
|
||||||
u_char bval; /* delimiting byte (variable-length records */
|
|
||||||
char *bfname; /* btree file name */
|
|
||||||
} RECNOINFO;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Little endian <==> big endian long swap macros.
|
|
||||||
* BLSWAP swap a memory location
|
|
||||||
* BLPSWAP swap a referenced memory location
|
|
||||||
* BLSWAP_COPY swap from one location to another
|
|
||||||
*/
|
|
||||||
#define BLSWAP(a) { \
|
|
||||||
u_long _tmp = a; \
|
|
||||||
((char *)&a)[0] = ((char *)&_tmp)[3]; \
|
|
||||||
((char *)&a)[1] = ((char *)&_tmp)[2]; \
|
|
||||||
((char *)&a)[2] = ((char *)&_tmp)[1]; \
|
|
||||||
((char *)&a)[3] = ((char *)&_tmp)[0]; \
|
|
||||||
}
|
|
||||||
#define BLPSWAP(a) { \
|
|
||||||
u_long _tmp = *(u_long *)a; \
|
|
||||||
((char *)a)[0] = ((char *)&_tmp)[3]; \
|
|
||||||
((char *)a)[1] = ((char *)&_tmp)[2]; \
|
|
||||||
((char *)a)[2] = ((char *)&_tmp)[1]; \
|
|
||||||
((char *)a)[3] = ((char *)&_tmp)[0]; \
|
|
||||||
}
|
|
||||||
#define BLSWAP_COPY(a, b) { \
|
|
||||||
((char *)&(b))[0] = ((char *)&(a))[3]; \
|
|
||||||
((char *)&(b))[1] = ((char *)&(a))[2]; \
|
|
||||||
((char *)&(b))[2] = ((char *)&(a))[1]; \
|
|
||||||
((char *)&(b))[3] = ((char *)&(a))[0]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Little endian <==> big endian short swap macros.
|
|
||||||
* BSSWAP swap a memory location
|
|
||||||
* BSPSWAP swap a referenced memory location
|
|
||||||
* BSSWAP_COPY swap from one location to another
|
|
||||||
*/
|
|
||||||
#define BSSWAP(a) { \
|
|
||||||
u_short _tmp = a; \
|
|
||||||
((char *)&a)[0] = ((char *)&_tmp)[1]; \
|
|
||||||
((char *)&a)[1] = ((char *)&_tmp)[0]; \
|
|
||||||
}
|
|
||||||
#define BSPSWAP(a) { \
|
|
||||||
u_short _tmp = *(u_short *)a; \
|
|
||||||
((char *)a)[0] = ((char *)&_tmp)[1]; \
|
|
||||||
((char *)a)[1] = ((char *)&_tmp)[0]; \
|
|
||||||
}
|
|
||||||
#define BSSWAP_COPY(a, b) { \
|
|
||||||
((char *)&(b))[0] = ((char *)&(a))[1]; \
|
|
||||||
((char *)&(b))[1] = ((char *)&(a))[0]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
__BEGIN_DECLS
|
|
||||||
DB *dbopen __P((const char *, int, int, DBTYPE, const void *));
|
|
||||||
|
|
||||||
#ifdef __DBINTERFACE_PRIVATE
|
|
||||||
DB *__bt_open __P((const char *, int, int, const BTREEINFO *, int));
|
|
||||||
DB *__hash_open __P((const char *, int, int, const HASHINFO *, int));
|
|
||||||
DB *__rec_open __P((const char *, int, int, const RECNOINFO *, int));
|
|
||||||
void __dbpanic __P((DB *dbp));
|
|
||||||
#endif
|
|
||||||
__END_DECLS
|
|
||||||
#endif /* !_DB_H_ */
|
|
|
@ -1,93 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: extern.h /main/3 1996/06/11 17:13:51 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*
|
|
||||||
* @(#)extern.h 8.2 (Berkeley) 9/7/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
int __bt_close __P((DB *));
|
|
||||||
int __bt_cmp __P((BTREE *, const DBT *, EPG *));
|
|
||||||
int __bt_crsrdel __P((BTREE *, EPGNO *));
|
|
||||||
int __bt_defcmp __P((const DBT *, const DBT *));
|
|
||||||
int __bt_defpfx __P((const DBT *, const DBT *));
|
|
||||||
int __bt_delete __P((const DB *, const DBT *, u_int));
|
|
||||||
int __bt_dleaf __P((BTREE *, PAGE *, int));
|
|
||||||
int __bt_fd __P((const DB *));
|
|
||||||
EPG *__bt_first __P((BTREE *, const DBT *, int *));
|
|
||||||
int __bt_free __P((BTREE *, PAGE *));
|
|
||||||
int __bt_get __P((const DB *, const DBT *, DBT *, u_int));
|
|
||||||
PAGE *__bt_new __P((BTREE *, pgno_t *));
|
|
||||||
void __bt_pgin __P((void *, pgno_t, void *));
|
|
||||||
void __bt_pgout __P((void *, pgno_t, void *));
|
|
||||||
int __bt_push __P((BTREE *, pgno_t, int));
|
|
||||||
int __bt_put __P((const DB *dbp, DBT *, const DBT *, u_int));
|
|
||||||
int __bt_ret __P((BTREE *, EPG *, DBT *, DBT *));
|
|
||||||
EPG *__bt_search __P((BTREE *, const DBT *, int *));
|
|
||||||
int __bt_seq __P((const DB *, DBT *, DBT *, u_int));
|
|
||||||
int __bt_split __P((BTREE *, PAGE *,
|
|
||||||
const DBT *, const DBT *, u_long, size_t, u_int));
|
|
||||||
int __bt_sync __P((const DB *, u_int));
|
|
||||||
|
|
||||||
int __ovfl_delete __P((BTREE *, void *));
|
|
||||||
int __ovfl_get __P((BTREE *, void *, size_t *, char **, size_t *));
|
|
||||||
int __ovfl_put __P((BTREE *, const DBT *, pgno_t *));
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void __bt_dnpage __P((DB *, pgno_t));
|
|
||||||
void __bt_dpage __P((PAGE *));
|
|
||||||
void __bt_dump __P((DB *));
|
|
||||||
#endif
|
|
||||||
#ifdef STATISTICS
|
|
||||||
void __bt_stat __P((DB *));
|
|
||||||
#endif
|
|
|
@ -1,162 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: memmove.c /main/3 1996/06/11 17:13:55 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Chris Torek.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include "cdefs.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sizeof(word) MUST BE A POWER OF TWO
|
|
||||||
* SO THAT wmask BELOW IS ALL ONES
|
|
||||||
*/
|
|
||||||
typedef int word; /* "word" used for optimal copy speed */
|
|
||||||
|
|
||||||
#define wsize sizeof(word)
|
|
||||||
#define wmask (wsize - 1)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy a block of memory, handling overlap.
|
|
||||||
* This is the routine that actually implements
|
|
||||||
* (the portable versions of) bcopy, memcpy, and memmove.
|
|
||||||
*/
|
|
||||||
#ifdef MEMCOPY
|
|
||||||
void *
|
|
||||||
memcpy(dst0, src0, length)
|
|
||||||
#else
|
|
||||||
#ifdef MEMMOVE
|
|
||||||
void *
|
|
||||||
memmove(dst0, src0, length)
|
|
||||||
#else
|
|
||||||
void
|
|
||||||
bcopy(src0, dst0, length)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
void *dst0;
|
|
||||||
const void *src0;
|
|
||||||
size_t length;
|
|
||||||
{
|
|
||||||
char *dst = dst0;
|
|
||||||
const char *src = src0;
|
|
||||||
size_t t;
|
|
||||||
|
|
||||||
if (length == 0 || dst == src) /* nothing to do */
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Macros: loop-t-times; and loop-t-times, t>0
|
|
||||||
*/
|
|
||||||
#define TLOOP(s) if (t) TLOOP1(s)
|
|
||||||
#define TLOOP1(s) do { s; } while (--t)
|
|
||||||
|
|
||||||
if ((unsigned long)dst < (unsigned long)src) {
|
|
||||||
/*
|
|
||||||
* Copy forward.
|
|
||||||
*/
|
|
||||||
t = (size_t)src; /* only need low bits */
|
|
||||||
if ((t | (size_t)dst) & wmask) {
|
|
||||||
/*
|
|
||||||
* Try to align operands. This cannot be done
|
|
||||||
* unless the low bits match.
|
|
||||||
*/
|
|
||||||
if ((t ^ (size_t)dst) & wmask || length < wsize)
|
|
||||||
t = length;
|
|
||||||
else
|
|
||||||
t = wsize - (t & wmask);
|
|
||||||
length -= t;
|
|
||||||
TLOOP1(*dst++ = *src++);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Copy whole words, then mop up any trailing bytes.
|
|
||||||
*/
|
|
||||||
t = length / wsize;
|
|
||||||
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
|
|
||||||
t = length & wmask;
|
|
||||||
TLOOP(*dst++ = *src++);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Copy backwards. Otherwise essentially the same.
|
|
||||||
* Alignment works as before, except that it takes
|
|
||||||
* (t&wmask) bytes to align, not wsize-(t&wmask).
|
|
||||||
*/
|
|
||||||
src += length;
|
|
||||||
dst += length;
|
|
||||||
t = (size_t)src;
|
|
||||||
if ((t | (size_t)dst) & wmask) {
|
|
||||||
if ((t ^ (size_t)dst) & wmask || length <= wsize)
|
|
||||||
t = length;
|
|
||||||
else
|
|
||||||
t &= wmask;
|
|
||||||
length -= t;
|
|
||||||
TLOOP1(*--dst = *--src);
|
|
||||||
}
|
|
||||||
t = length / wsize;
|
|
||||||
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
|
|
||||||
t = length & wmask;
|
|
||||||
TLOOP(*--dst = *--src);
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
#if defined(MEMCOPY) || defined(MEMMOVE)
|
|
||||||
return (dst0);
|
|
||||||
#else
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1,150 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: mktemp.c /main/4 1996/11/01 10:18:53 drk $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1987, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include <X11/Xosdefs.h>
|
|
||||||
#ifdef X_NOT_STDC_ENV
|
|
||||||
extern int errno;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int _gettemp(char*, int*);
|
|
||||||
|
|
||||||
int mkstemp(char *path)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
return (_gettemp(path, &fd) ? fd : -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
mktemp(char *path)
|
|
||||||
{
|
|
||||||
return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
_gettemp(char *path, int *doopen)
|
|
||||||
{
|
|
||||||
char *start, *trv;
|
|
||||||
struct stat sbuf;
|
|
||||||
u_int pid;
|
|
||||||
|
|
||||||
pid = getpid();
|
|
||||||
for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
|
|
||||||
while (*--trv == 'X') {
|
|
||||||
*trv = (pid % 10) + '0';
|
|
||||||
pid /= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check the target directory; if you have six X's and it
|
|
||||||
* doesn't exist this runs for a *very* long time.
|
|
||||||
*/
|
|
||||||
for (start = trv + 1;; --trv) {
|
|
||||||
if (trv <= path)
|
|
||||||
break;
|
|
||||||
if (*trv == '/') {
|
|
||||||
*trv = '\0';
|
|
||||||
if (stat(path, &sbuf))
|
|
||||||
return(0);
|
|
||||||
if (!S_ISDIR(sbuf.st_mode)) {
|
|
||||||
errno = ENOTDIR;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
*trv = '/';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (doopen) {
|
|
||||||
if ((*doopen =
|
|
||||||
open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
|
|
||||||
return(1);
|
|
||||||
if (errno != EEXIST)
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
else if (stat(path, &sbuf))
|
|
||||||
return(errno == ENOENT ? 1 : 0);
|
|
||||||
|
|
||||||
/* tricky little algorithm for backward compatibility */
|
|
||||||
for (trv = start;;) {
|
|
||||||
if (!*trv)
|
|
||||||
return(0);
|
|
||||||
if (*trv == 'z')
|
|
||||||
*trv++ = 'a';
|
|
||||||
else {
|
|
||||||
if (isdigit((unsigned char) *trv))
|
|
||||||
*trv = 'a';
|
|
||||||
else
|
|
||||||
++*trv;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
|
@ -1,542 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: mpool.c /main/4 1996/10/04 09:47:13 drk $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char sccsid[] = "@(#)mpool.c 8.1 (Berkeley) 6/6/93";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
#define __MPOOLINTERFACE_PRIVATE
|
|
||||||
#include "mpool.h"
|
|
||||||
|
|
||||||
static BKT *mpool_bkt __P((MPOOL *));
|
|
||||||
static BKT *mpool_look __P((MPOOL *, pgno_t));
|
|
||||||
static int mpool_write __P((MPOOL *, BKT *));
|
|
||||||
#ifdef DEBUG
|
|
||||||
static void __mpoolerr __P((const char *fmt, ...));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_OPEN -- initialize a memory pool.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* key: Shared buffer key.
|
|
||||||
* fd: File descriptor.
|
|
||||||
* pagesize: File page size.
|
|
||||||
* maxcache: Max number of cached pages.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* MPOOL pointer, NULL on error.
|
|
||||||
*/
|
|
||||||
MPOOL *
|
|
||||||
mpool_open(DBT *key, int fd, pgno_t pagesize, pgno_t maxcache)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
MPOOL *mp;
|
|
||||||
int entry;
|
|
||||||
|
|
||||||
if (fstat(fd, &sb))
|
|
||||||
return (NULL);
|
|
||||||
/* XXX
|
|
||||||
* We should only set st_size to 0 for pipes -- 4.4BSD has the fix so
|
|
||||||
* that stat(2) returns true for ISSOCK on pipes. Until then, this is
|
|
||||||
* fairly close.
|
|
||||||
*/
|
|
||||||
if (!S_ISREG(sb.st_mode)) {
|
|
||||||
errno = ESPIPE;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mp = malloc(sizeof(MPOOL))) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
mp->free.cnext = mp->free.cprev = (BKT *)(void *)&mp->free;
|
|
||||||
mp->lru.cnext = mp->lru.cprev = (BKT *)(void *)&mp->lru;
|
|
||||||
for (entry = 0; entry < HASHSIZE; ++entry)
|
|
||||||
mp->hashtable[entry].hnext = mp->hashtable[entry].hprev =
|
|
||||||
mp->hashtable[entry].cnext = mp->hashtable[entry].cprev =
|
|
||||||
(BKT *)&mp->hashtable[entry];
|
|
||||||
mp->curcache = 0;
|
|
||||||
mp->maxcache = maxcache;
|
|
||||||
mp->pagesize = pagesize;
|
|
||||||
mp->npages = sb.st_size / pagesize;
|
|
||||||
mp->fd = fd;
|
|
||||||
mp->pgcookie = NULL;
|
|
||||||
mp->pgin = mp->pgout = NULL;
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
mp->cachehit = mp->cachemiss = mp->pagealloc = mp->pageflush =
|
|
||||||
mp->pageget = mp->pagenew = mp->pageput = mp->pageread =
|
|
||||||
mp->pagewrite = 0;
|
|
||||||
#endif
|
|
||||||
return (mp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_FILTER -- initialize input/output filters.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* pgin: Page in conversion routine.
|
|
||||||
* pgout: Page out conversion routine.
|
|
||||||
* pgcookie: Cookie for page in/out routines.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mpool_filter(MPOOL *mp,
|
|
||||||
void (*pgin) __P((void *, pgno_t, void *)),
|
|
||||||
void (*pgout) __P((void *, pgno_t, void *)),
|
|
||||||
void *pgcookie)
|
|
||||||
{
|
|
||||||
mp->pgin = pgin;
|
|
||||||
mp->pgout = pgout;
|
|
||||||
mp->pgcookie = pgcookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_NEW -- get a new page
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* mp: mpool cookie
|
|
||||||
* pgnoadddr: place to store new page number
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
mpool_new(MPOOL *mp, pgno_t *pgnoaddr)
|
|
||||||
{
|
|
||||||
BKT *b;
|
|
||||||
BKTHDR *hp;
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->pagenew;
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* Get a BKT from the cache. Assign a new page number, attach it to
|
|
||||||
* the hash and lru chains and return.
|
|
||||||
*/
|
|
||||||
if ((b = mpool_bkt(mp)) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
*pgnoaddr = b->pgno = mp->npages++;
|
|
||||||
b->flags = MPOOL_PINNED;
|
|
||||||
inshash(b, b->pgno);
|
|
||||||
inschain(b, &mp->lru);
|
|
||||||
return (b->page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_GET -- get a page from the pool
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* mp: mpool cookie
|
|
||||||
* pgno: page number
|
|
||||||
* flags: not used
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
mpool_get(MPOOL *mp, pgno_t pgno, u_int flags /* XXX not used? */)
|
|
||||||
{
|
|
||||||
BKT *b;
|
|
||||||
BKTHDR *hp;
|
|
||||||
off_t off;
|
|
||||||
int nr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If asking for a specific page that is already in the cache, find
|
|
||||||
* it and return it.
|
|
||||||
*/
|
|
||||||
if ((b = mpool_look(mp, pgno))) {
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->pageget;
|
|
||||||
#endif
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (b->flags & MPOOL_PINNED)
|
|
||||||
__mpoolerr("mpool_get: page %d already pinned",
|
|
||||||
b->pgno);
|
|
||||||
#endif
|
|
||||||
rmchain(b);
|
|
||||||
inschain(b, &mp->lru);
|
|
||||||
b->flags |= MPOOL_PINNED;
|
|
||||||
return (b->page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not allowed to retrieve a non-existent page. */
|
|
||||||
if (pgno >= mp->npages) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a page from the cache. */
|
|
||||||
if ((b = mpool_bkt(mp)) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
b->pgno = pgno;
|
|
||||||
b->flags = MPOOL_PINNED;
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->pageread;
|
|
||||||
#endif
|
|
||||||
/* Read in the contents. */
|
|
||||||
off = mp->pagesize * pgno;
|
|
||||||
if (lseek(mp->fd, off, SEEK_SET) != off)
|
|
||||||
return (NULL);
|
|
||||||
if ((nr = read(mp->fd, b->page, mp->pagesize)) != mp->pagesize) {
|
|
||||||
if (nr >= 0)
|
|
||||||
errno = EFTYPE;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
if (mp->pgin)
|
|
||||||
(mp->pgin)(mp->pgcookie, b->pgno, b->page);
|
|
||||||
|
|
||||||
inshash(b, b->pgno);
|
|
||||||
inschain(b, &mp->lru);
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->pageget;
|
|
||||||
#endif
|
|
||||||
return (b->page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_PUT -- return a page to the pool
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* mp: mpool cookie
|
|
||||||
* page: page pointer
|
|
||||||
* pgno: page number
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
mpool_put(MPOOL *mp, void *page, u_int flags)
|
|
||||||
{
|
|
||||||
BKT *baddr;
|
|
||||||
#ifdef DEBUG
|
|
||||||
BKT *b;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->pageput;
|
|
||||||
#endif
|
|
||||||
baddr = (BKT *)((char *)page - sizeof(BKT));
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (!(baddr->flags & MPOOL_PINNED))
|
|
||||||
__mpoolerr("mpool_put: page %d not pinned", b->pgno);
|
|
||||||
for (b = mp->lru.cnext; b != (BKT *)&mp->lru; b = b->cnext) {
|
|
||||||
if (b == (BKT *)&mp->lru)
|
|
||||||
__mpoolerr("mpool_put: %0x: bad address", baddr);
|
|
||||||
if (b == baddr)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
baddr->flags &= ~MPOOL_PINNED;
|
|
||||||
baddr->flags |= flags & MPOOL_DIRTY;
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_CLOSE -- close the buffer pool
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* mp: mpool cookie
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
mpool_close(MPOOL *mp)
|
|
||||||
{
|
|
||||||
BKT *b, *next;
|
|
||||||
|
|
||||||
/* Free up any space allocated to the lru pages. */
|
|
||||||
for (b = mp->lru.cprev; b != (BKT *)(void *)&mp->lru; b = next) {
|
|
||||||
next = b->cprev;
|
|
||||||
free(b);
|
|
||||||
}
|
|
||||||
free(mp);
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_SYNC -- sync the file to disk.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* mp: mpool cookie
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
mpool_sync(MPOOL *mp)
|
|
||||||
{
|
|
||||||
BKT *b;
|
|
||||||
|
|
||||||
for (b = mp->lru.cprev; b != (BKT *)(void *)&mp->lru; b = b->cprev)
|
|
||||||
if (b->flags & MPOOL_DIRTY && mpool_write(mp, b) == RET_ERROR)
|
|
||||||
return (RET_ERROR);
|
|
||||||
return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_BKT -- get/create a BKT from the cache
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* mp: mpool cookie
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* NULL on failure and a pointer to the BKT on success
|
|
||||||
*/
|
|
||||||
static BKT *
|
|
||||||
mpool_bkt(MPOOL *mp)
|
|
||||||
{
|
|
||||||
BKT *b;
|
|
||||||
|
|
||||||
if (mp->curcache < mp->maxcache)
|
|
||||||
goto new;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the cache is maxxed out, search the lru list for a buffer we
|
|
||||||
* can flush. If we find one, write it if necessary and take it off
|
|
||||||
* any lists. If we don't find anything we grow the cache anyway.
|
|
||||||
* The cache never shrinks.
|
|
||||||
*/
|
|
||||||
for (b = mp->lru.cprev; b != (BKT *)(void *)&mp->lru; b = b->cprev)
|
|
||||||
if (!(b->flags & MPOOL_PINNED)) {
|
|
||||||
if (b->flags & MPOOL_DIRTY &&
|
|
||||||
mpool_write(mp, b) == RET_ERROR)
|
|
||||||
return (NULL);
|
|
||||||
rmhash(b);
|
|
||||||
rmchain(b);
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->pageflush;
|
|
||||||
#endif
|
|
||||||
#ifdef DEBUG
|
|
||||||
{
|
|
||||||
void *spage;
|
|
||||||
spage = b->page;
|
|
||||||
memset(b, 0xff, sizeof(BKT) + mp->pagesize);
|
|
||||||
b->page = spage;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return (b);
|
|
||||||
}
|
|
||||||
|
|
||||||
new: if ((b = malloc(sizeof(BKT) + mp->pagesize)) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->pagealloc;
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
#ifdef DEBUG
|
|
||||||
*/
|
|
||||||
memset(b, 0xff, sizeof(BKT) + mp->pagesize);
|
|
||||||
/*
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
b->page = (char *)b + sizeof(BKT);
|
|
||||||
|
|
||||||
++mp->curcache;
|
|
||||||
return (b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_WRITE -- sync a page to disk
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* mp: mpool cookie
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* RET_ERROR, RET_SUCCESS
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
mpool_write(MPOOL *mp, BKT *b)
|
|
||||||
{
|
|
||||||
off_t off;
|
|
||||||
|
|
||||||
if (mp->pgout)
|
|
||||||
(mp->pgout)(mp->pgcookie, b->pgno, b->page);
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->pagewrite;
|
|
||||||
#endif
|
|
||||||
off = mp->pagesize * b->pgno;
|
|
||||||
if (lseek(mp->fd, off, SEEK_SET) != off)
|
|
||||||
return (RET_ERROR);
|
|
||||||
if (write(mp->fd, b->page, mp->pagesize) != mp->pagesize)
|
|
||||||
return (RET_ERROR);
|
|
||||||
b->flags &= ~MPOOL_DIRTY;
|
|
||||||
return (RET_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPOOL_LOOK -- lookup a page
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* mp: mpool cookie
|
|
||||||
* pgno: page number
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* NULL on failure and a pointer to the BKT on success
|
|
||||||
*/
|
|
||||||
static BKT *
|
|
||||||
mpool_look(MPOOL *mp, pgno_t pgno)
|
|
||||||
{
|
|
||||||
BKT *b;
|
|
||||||
BKTHDR *tb;
|
|
||||||
|
|
||||||
/* XXX
|
|
||||||
* If find the buffer, put it first on the hash chain so can
|
|
||||||
* find it again quickly.
|
|
||||||
*/
|
|
||||||
tb = &mp->hashtable[HASHKEY(pgno)];
|
|
||||||
for (b = tb->hnext; b != (BKT *)tb; b = b->hnext)
|
|
||||||
if (b->pgno == pgno) {
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->cachehit;
|
|
||||||
#endif
|
|
||||||
return (b);
|
|
||||||
}
|
|
||||||
#ifdef STATISTICS
|
|
||||||
++mp->cachemiss;
|
|
||||||
#endif
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef STATISTICS
|
|
||||||
/*
|
|
||||||
* MPOOL_STAT -- cache statistics
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* mp: mpool cookie
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mpool_stat(MPOOL *mp)
|
|
||||||
{
|
|
||||||
BKT *b;
|
|
||||||
int cnt;
|
|
||||||
char *sep;
|
|
||||||
|
|
||||||
(void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"page size %lu, cacheing %lu pages of %lu page max cache\n",
|
|
||||||
mp->pagesize, mp->curcache, mp->maxcache);
|
|
||||||
(void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
|
|
||||||
mp->pageput, mp->pageget, mp->pagenew);
|
|
||||||
(void)fprintf(stderr, "%lu page allocs, %lu page flushes\n",
|
|
||||||
mp->pagealloc, mp->pageflush);
|
|
||||||
if (mp->cachehit + mp->cachemiss)
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"%.0f%% cache hit rate (%lu hits, %lu misses)\n",
|
|
||||||
((double)mp->cachehit / (mp->cachehit + mp->cachemiss))
|
|
||||||
* 100, mp->cachehit, mp->cachemiss);
|
|
||||||
(void)fprintf(stderr, "%lu page reads, %lu page writes\n",
|
|
||||||
mp->pageread, mp->pagewrite);
|
|
||||||
|
|
||||||
sep = "";
|
|
||||||
cnt = 0;
|
|
||||||
for (b = mp->lru.cnext; b != (BKT *)&mp->lru; b = b->cnext) {
|
|
||||||
(void)fprintf(stderr, "%s%ld", sep, b->pgno);
|
|
||||||
if (b->flags & MPOOL_DIRTY)
|
|
||||||
(void)fprintf(stderr, "d");
|
|
||||||
if (b->flags & MPOOL_PINNED)
|
|
||||||
(void)fprintf(stderr, "P");
|
|
||||||
if (++cnt == 10) {
|
|
||||||
sep = "\n";
|
|
||||||
cnt = 0;
|
|
||||||
} else
|
|
||||||
sep = ", ";
|
|
||||||
|
|
||||||
}
|
|
||||||
(void)fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#if __STDC__
|
|
||||||
#include <stdarg.h>
|
|
||||||
#else
|
|
||||||
#include <varargs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
#if __STDC__
|
|
||||||
__mpoolerr(const char *fmt, ...)
|
|
||||||
#else
|
|
||||||
__mpoolerr(fmt, va_alist)
|
|
||||||
char *fmt;
|
|
||||||
va_dcl
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
#if __STDC__
|
|
||||||
va_start(ap, fmt);
|
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
#endif
|
|
||||||
(void)vfprintf(stderr, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
(void)fprintf(stderr, "\n");
|
|
||||||
abort();
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,158 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: mpool.h /main/3 1996/06/11 17:14:12 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*
|
|
||||||
* @(#)mpool.h 8.1 (Berkeley) 6/2/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The memory pool scheme is a simple one. Each in memory page is referenced
|
|
||||||
* by a bucket which is threaded in three ways. All active pages are threaded
|
|
||||||
* on a hash chain (hashed by the page number) and an lru chain. Inactive
|
|
||||||
* pages are threaded on a free chain. Each reference to a memory pool is
|
|
||||||
* handed an MPOOL which is the opaque cookie passed to all of the memory
|
|
||||||
* routines.
|
|
||||||
*/
|
|
||||||
#define HASHSIZE 128
|
|
||||||
#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE)
|
|
||||||
|
|
||||||
/* The BKT structures are the elements of the lists. */
|
|
||||||
typedef struct BKT {
|
|
||||||
struct BKT *hnext; /* next hash bucket */
|
|
||||||
struct BKT *hprev; /* previous hash bucket */
|
|
||||||
struct BKT *cnext; /* next free/lru bucket */
|
|
||||||
struct BKT *cprev; /* previous free/lru bucket */
|
|
||||||
void *page; /* page */
|
|
||||||
pgno_t pgno; /* page number */
|
|
||||||
|
|
||||||
#define MPOOL_DIRTY 0x01 /* page needs to be written */
|
|
||||||
#define MPOOL_PINNED 0x02 /* page is pinned into memory */
|
|
||||||
unsigned long flags; /* flags */
|
|
||||||
} BKT;
|
|
||||||
|
|
||||||
/* The BKTHDR structures are the heads of the lists. */
|
|
||||||
typedef struct BKTHDR {
|
|
||||||
struct BKT *hnext; /* next hash bucket */
|
|
||||||
struct BKT *hprev; /* previous hash bucket */
|
|
||||||
struct BKT *cnext; /* next free/lru bucket */
|
|
||||||
struct BKT *cprev; /* previous free/lru bucket */
|
|
||||||
} BKTHDR;
|
|
||||||
|
|
||||||
typedef struct MPOOL {
|
|
||||||
BKTHDR free; /* The free list. */
|
|
||||||
BKTHDR lru; /* The LRU list. */
|
|
||||||
BKTHDR hashtable[HASHSIZE]; /* Hashed list by page number. */
|
|
||||||
pgno_t curcache; /* Current number of cached pages. */
|
|
||||||
pgno_t maxcache; /* Max number of cached pages. */
|
|
||||||
pgno_t npages; /* Number of pages in the file. */
|
|
||||||
u_long pagesize; /* File page size. */
|
|
||||||
int fd; /* File descriptor. */
|
|
||||||
/* Page in conversion routine. */
|
|
||||||
void (*pgin) __P((void *, pgno_t, void *));
|
|
||||||
/* Page out conversion routine. */
|
|
||||||
void (*pgout) __P((void *, pgno_t, void *));
|
|
||||||
void *pgcookie; /* Cookie for page in/out routines. */
|
|
||||||
#ifdef STATISTICS
|
|
||||||
unsigned long cachehit;
|
|
||||||
unsigned long cachemiss;
|
|
||||||
unsigned long pagealloc;
|
|
||||||
unsigned long pageflush;
|
|
||||||
unsigned long pageget;
|
|
||||||
unsigned long pagenew;
|
|
||||||
unsigned long pageput;
|
|
||||||
unsigned long pageread;
|
|
||||||
unsigned long pagewrite;
|
|
||||||
#endif
|
|
||||||
} MPOOL;
|
|
||||||
|
|
||||||
#ifdef __MPOOLINTERFACE_PRIVATE
|
|
||||||
/* Macros to insert/delete into/from hash chain. */
|
|
||||||
#define rmhash(bp) { \
|
|
||||||
(bp)->hprev->hnext = (bp)->hnext; \
|
|
||||||
(bp)->hnext->hprev = (bp)->hprev; \
|
|
||||||
}
|
|
||||||
#define inshash(bp, pg) { \
|
|
||||||
hp = &mp->hashtable[HASHKEY(pg)]; \
|
|
||||||
(bp)->hnext = hp->hnext; \
|
|
||||||
(bp)->hprev = (struct BKT *)hp; \
|
|
||||||
hp->hnext->hprev = (bp); \
|
|
||||||
hp->hnext = (bp); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Macros to insert/delete into/from lru and free chains. */
|
|
||||||
#define rmchain(bp) { \
|
|
||||||
(bp)->cprev->cnext = (bp)->cnext; \
|
|
||||||
(bp)->cnext->cprev = (bp)->cprev; \
|
|
||||||
}
|
|
||||||
#define inschain(bp, dp) { \
|
|
||||||
(bp)->cnext = (dp)->cnext; \
|
|
||||||
(bp)->cprev = (struct BKT *)(void *)(dp); \
|
|
||||||
(dp)->cnext->cprev = (bp); \
|
|
||||||
(dp)->cnext = (bp); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__BEGIN_DECLS
|
|
||||||
MPOOL *mpool_open __P((DBT *, int, pgno_t, pgno_t));
|
|
||||||
void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *),
|
|
||||||
void (*)(void *, pgno_t, void *), void *));
|
|
||||||
void *mpool_new __P((MPOOL *, pgno_t *));
|
|
||||||
void *mpool_get __P((MPOOL *, pgno_t, u_int));
|
|
||||||
int mpool_put __P((MPOOL *, void *, u_int));
|
|
||||||
int mpool_sync __P((MPOOL *));
|
|
||||||
int mpool_close __P((MPOOL *));
|
|
||||||
#ifdef STATISTICS
|
|
||||||
void mpool_stat __P((MPOOL *));
|
|
||||||
#endif
|
|
||||||
__END_DECLS
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: ndbm.h /main/3 1996/06/11 17:14:17 cde-hal $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1990, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Margo Seltzer.
|
|
||||||
*
|
|
||||||
* 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. 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.
|
|
||||||
* 4. 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS 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.
|
|
||||||
*
|
|
||||||
* @(#)ndbm.h 8.1 (Berkeley) 6/2/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _NDBM_H_
|
|
||||||
#define _NDBM_H_
|
|
||||||
|
|
||||||
#include <db.h>
|
|
||||||
|
|
||||||
/* Map dbm interface onto db(3). */
|
|
||||||
#define DBM_RDONLY O_RDONLY
|
|
||||||
|
|
||||||
/* Flags to dbm_store(). */
|
|
||||||
#define DBM_INSERT 0
|
|
||||||
#define DBM_REPLACE 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The db(3) support for ndbm(3) always appends this suffix to the
|
|
||||||
* file name to avoid overwriting the user's original database.
|
|
||||||
*/
|
|
||||||
#define DBM_SUFFIX ".db"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *dptr;
|
|
||||||
int dsize;
|
|
||||||
} datum;
|
|
||||||
|
|
||||||
typedef DB DBM;
|
|
||||||
#define dbm_pagfno(a) DBM_PAGFNO_NOT_AVAILABLE
|
|
||||||
|
|
||||||
__BEGIN_DECLS
|
|
||||||
void dbm_close __P((DBM *));
|
|
||||||
int dbm_delete __P((DBM *, datum));
|
|
||||||
datum dbm_fetch __P((DBM *, datum));
|
|
||||||
datum dbm_firstkey __P((DBM *));
|
|
||||||
long dbm_forder __P((DBM *, datum));
|
|
||||||
datum dbm_nextkey __P((DBM *));
|
|
||||||
DBM *dbm_open __P((const char *, int, int));
|
|
||||||
int dbm_store __P((DBM *, datum, datum, int));
|
|
||||||
int dbm_dirfno __P((DBM *));
|
|
||||||
__END_DECLS
|
|
||||||
|
|
||||||
#endif /* !_NDBM_H_ */
|
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: realloc.c /main/3 1996/06/11 17:14:22 cde-hal $ */
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void *
|
|
||||||
__fix_realloc(void *p, size_t n)
|
|
||||||
{
|
|
||||||
return (p == 0 ? malloc(n) : realloc(p, n));
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
/*
|
|
||||||
* CDE - Common Desktop Environment
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
||||||
*
|
|
||||||
* These libraries and programs are free software; you can
|
|
||||||
* redistribute them and/or modify them under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation; either version 2 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* These libraries and programs are distributed in the hope that
|
|
||||||
* they 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 these libraries and programs; if not, write
|
|
||||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
* Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
/* $XConsortium: snprintf.c /main/3 1996/06/11 17:14:27 cde-hal $ */
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "cdefs.h"
|
|
||||||
|
|
||||||
#include <compat.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
#include <stdarg.h>
|
|
||||||
#else
|
|
||||||
#include <varargs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
|
||||||
#ifdef __STDC__
|
|
||||||
snprintf(char *str, size_t n, const char *fmt, ...)
|
|
||||||
#else
|
|
||||||
snprintf(str, n, fmt, va_alist)
|
|
||||||
char *str;
|
|
||||||
size_t n;
|
|
||||||
const char *fmt;
|
|
||||||
va_dcl
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
#ifdef VSPRINTF_CHARSTAR
|
|
||||||
char *rp;
|
|
||||||
#else
|
|
||||||
int rval;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(ap, fmt);
|
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VSPRINTF_CHARSTAR
|
|
||||||
rp = (char*)(size_t)vsnprintf(str, n, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return (strlen(rp));
|
|
||||||
#else
|
|
||||||
rval = vsnprintf(str, n, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return (rval);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int
|
|
||||||
vsnprintf(str, n, fmt, ap)
|
|
||||||
char *str;
|
|
||||||
size_t n;
|
|
||||||
const char *fmt;
|
|
||||||
va_list ap;
|
|
||||||
{
|
|
||||||
#ifdef VSPRINTF_CHARSTAR
|
|
||||||
return (strlen((char*)(size_t)vsnprintf(str, fmt, ap)));
|
|
||||||
#else
|
|
||||||
return (vsnprintf(str, fmt, ap));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -53,7 +53,7 @@
|
||||||
#define _btree_index_h 1
|
#define _btree_index_h 1
|
||||||
|
|
||||||
#include "index/dyn_index.h"
|
#include "index/dyn_index.h"
|
||||||
#include "btree/mmdb_btree.h"
|
#include "btree/btree.h"
|
||||||
|
|
||||||
class btree_index : public dyn_index
|
class btree_index : public dyn_index
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,7 +164,7 @@ handler* btree_index_desc::init_handler(object_dict& dict)
|
||||||
(*(btree_index_handler*)v_handler_ptr) ->
|
(*(btree_index_handler*)v_handler_ptr) ->
|
||||||
init_data_member(
|
init_data_member(
|
||||||
(inv_lists_handler*)inv_handler,
|
(inv_lists_handler*)inv_handler,
|
||||||
form("%s/%s", get_agent_nm(), dict.db_path())
|
form("%s/%s", dict.db_path(), get_agent_nm())
|
||||||
);
|
);
|
||||||
|
|
||||||
(*(btree_index_handler*)v_handler_ptr) -> set_selector(position) ;
|
(*(btree_index_handler*)v_handler_ptr) -> set_selector(position) ;
|
||||||
|
|
|
@ -67,6 +67,6 @@ bin_PROGRAMS = dtinfo
|
||||||
dtinfo_CXXFLAGS = $(DTINFO_DEFINES) $(DTINFO_INCLUDES)
|
dtinfo_CXXFLAGS = $(DTINFO_DEFINES) $(DTINFO_INCLUDES)
|
||||||
|
|
||||||
dtinfo_LDADD = $(OLIASNORMALLIBS) $(LIBSEARCH) $(MMDB_LIBS) $(WWL_LIBS) \
|
dtinfo_LDADD = $(OLIASNORMALLIBS) $(LIBSEARCH) $(MMDB_LIBS) $(WWL_LIBS) \
|
||||||
$(DTCLIENTLIBS) $(XTOOLLIB)
|
$(DTCLIENTLIBS) $(XTOOLLIB) $(LMDBLIB)
|
||||||
|
|
||||||
dtinfo_SOURCES = main.C Support/InputNotifier.C
|
dtinfo_SOURCES = main.C Support/InputNotifier.C
|
||||||
|
|
Loading…
Reference in a new issue