bt_open.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
#pragma ident "%Z%%M% %I% %E% SMI"
/*-
* Copyright (c) 1990, 1993, 1994
* 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
* 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.
*/
#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 <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "db-int.h"
#include "btree.h"
#ifdef DEBUG_DB
#define MINPSIZE 128
#endif
/*
* __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 *
const char *fname;
{
BTMETA m;
BTREE *t;
BTREEINFO b;
int machine_lorder;
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. */
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 &&
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. */
b.compare = __bt_defcmp;
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. */
goto einval;
/* Allocate and initialize DB and BTREE structures. */
goto err;
t->bt_rfd = -1;
goto err;
if (t->bt_lorder != machine_lorder)
F_SET(t, B_NEEDSWAP);
/*
* 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) {
case O_RDONLY:
break;
case O_RDWR:
break;
case O_WRONLY:
default:
goto einval;
}
goto err;
} else {
goto einval;
goto err;
}
goto err;
goto err;
goto err;
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.magic == BTREEMAGIC)
F_CLR(t, B_NEEDSWAP);
else {
F_SET(t, B_NEEDSWAP);
}
goto eftype;
goto eftype;
goto eftype;
} 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) {
}
/* Set flag if duplicates permitted. */
t->bt_nrecs = 0;
F_SET(t, B_METADIRTY);
}
/* Set the cache size; must be a multiple of the page size. */
/* Calculate number of pages to cache. */
/*
* 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
* 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
* pages.
*/
t->bt_ovflsize =
/* Initialize the buffer pool. */
if ((t->bt_mp =
goto err;
/* Create a root page if new tree. */
goto err;
/* Global flags. */
F_SET(t, B_DB_SHMEM);
return (dbp);
goto err;
goto err;
err: if (t) {
if (t->bt_dbp)
if (t->bt_fd != -1)
free(t);
}
return (NULL);
}
/*
* NROOT -- Create the root of a new tree.
*
* Parameters:
* t: tree
*
* Returns:
* RET_ERROR, RET_SUCCESS
*/
static int
nroot(t)
BTREE *t;
{
} else {
return (RET_SUCCESS);
}
}
return (RET_ERROR);
errno = 0;
return (RET_ERROR);
return (RET_ERROR);
return (RET_ERROR);
return (RET_SUCCESS);
}
static int
tmp()
{
#ifdef SIG_BLOCK
#else
int oset;
#endif
int fd;
char *envtmp;
char path[MAXPATHLEN];
static char fn[] = "/bt.XXXXXX";
/* this used to be done with snprintf(), but since snprintf
isn't in most operating systems, and overflow checking in
this case is easy, this is what is done */
return(-1);
#ifdef SIG_BLOCK
(void)sigfillset(&set);
#else
#endif
#ifdef SIG_BLOCK
#else
#endif
#ifdef __CYGWIN32__
/* Ensure the fd is in binary mode. */
#endif /* __CYGWIN32__ */
return(fd);
}
static int
{
u_int32_t x;
u_char *p;
x = 0x01020304;
p = (u_char *)&x;
switch (*p) {
case 1:
return (DB_BIG_ENDIAN);
case 4:
return (DB_LITTLE_ENDIAN);
default:
return (0);
}
}
int
{
BTREE *t;
/* Toss any page pinned across calls. */
}
/* In-memory database can't have a file descriptor. */
return (-1);
}
return (t->bt_fd);
}