Initial import of the CDE 2.1.30 sources from the Open Group.

This commit is contained in:
Peter Howkins
2012-03-10 18:21:40 +00:00
commit 83b6996daa
18978 changed files with 3945623 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
XCOMM $XConsortium: Imakefile /main/4 1996/04/21 19:12:37 drk $
#define DoNormalLib YES
#define DoSharedLib NO
#define DoDebugLib NO
#define DoProfileLib NO
#define LibName isam
#define LibHeaders NO
#define LibInstall NO
#include <Threads.tmpl>
#include "../tooltalk.tmpl"
INCLUDES = -I.
SRCS = isaddindex.c isamaddindex.c isopen.c isamopen.c \
isdelcurr.c isdelrec.c isamdelrec.c isbuild.c \
isvars.c isrewrec.c iserase.c iscntl.c isstart.c \
isaddprimary.c isrewcurr.c isclose.c isread.c \
iswrite.c isamwrite.c issync.c isapplmr.c ismngfcb.c \
issort.c ischange1key.c isfab.c isdiskbufs2.c isfd.c isbtree.c \
isdel1key.c isfcb.c isfixrec.c issignals.c isapplmw.c \
isfcbwatchfd.c isamhooks.c isfcbindex.c isalloc.c isbytearray.c \
isdatconv.c isminmax.c isfname.c isvarrec.c isperm.c iserror.c \
iskeycmp.c iskeycalc.c iskeyvalid.c isamerror.c iskeyaux.c \
isfileio.c ispageio.c isdlink.c isbtree2.c \
isbtree3.c isindfreel.c isindexconv.c isbsearch.c isadd1key.c \
iskeyconv.c isversion.c isrepair.c iswrrec.c isrename.c \
isindexinfo.c isgarbage.c iscurpos.c
OBJS = isaddindex.o isamaddindex.o isopen.o isamopen.o \
isdelcurr.o isdelrec.o isamdelrec.o isbuild.o \
isvars.o isrewrec.o iserase.o iscntl.o isstart.o \
isaddprimary.o isrewcurr.o isclose.o isread.o \
iswrite.o isamwrite.o issync.o isapplmr.o ismngfcb.o \
issort.o ischange1key.o isfab.o isdiskbufs2.o isfd.o isbtree.o \
isdel1key.o isfcb.o isfixrec.o issignals.o isapplmw.o \
isfcbwatchfd.o isamhooks.o isfcbindex.o isalloc.o isbytearray.o \
isdatconv.o isminmax.o isfname.o isvarrec.o isperm.o iserror.o \
iskeycmp.o iskeycalc.o iskeyvalid.o isamerror.o iskeyaux.o \
isfileio.o ispageio.o isdlink.o isbtree2.o \
isbtree3.o isindfreel.o isindexconv.o isbsearch.o isadd1key.o \
iskeyconv.o isversion.o isrepair.o iswrrec.o isrename.o \
isindexinfo.o isgarbage.o iscurpos.o
#include <Library.tmpl>
SpecialLibObjectRule(isversion.o,,$(TT_VERSION_DEFINE))
DependTarget()

View File

@@ -0,0 +1,120 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isadd1key.c /main/3 1995/10/23 11:33:17 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isadd1key.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isadd1key.c
*
* Description:
* Add an entry to B tree.
*
*
*/
#include "isam_impl.h"
extern long *ismaxlong;
int
_add1key(fcb, pkeydesc2, record, recnum, newkey)
Fcb *fcb;
Keydesc2 *pkeydesc2;
char *record;
Recno recnum;
char *newkey;
{
char keybuf[MAXKEYSIZE];
Btree *btree;
char *pkey;
/*
* Special case when there is no primary key.
*/
if (pkeydesc2->k2_nparts == 0)
return (ISOK);
memset((char *)keybuf, 0, pkeydesc2->k2_len);
_iskey_extract(pkeydesc2, record, keybuf);
btree = _isbtree_create(fcb, pkeydesc2);
if (ALLOWS_DUPS2(pkeydesc2)) {
/*
* Duplicates allowed on this key.
* Try to read the last duplicate (with the highest serial number).
* If such duplicate exists, the inserted key entry will be
* assigned next higher value for duplicate serial number.
* If there is no such duplicate, assign duplicate serial number 1.
*/
strecno(recnum, keybuf + KEY_RECNO_OFF);
memcpy(keybuf + KEY_DUPS_OFF, (char *)ismaxlong, LONGSIZE);
_isbtree_search(btree, keybuf);
if ((pkey = _isbtree_current(btree)) != NULL &&
memcmp(pkey + RECNOSIZE + DUPIDSIZE,
keybuf + RECNOSIZE + DUPIDSIZE,
pkeydesc2->k2_len - RECNOSIZE - DUPIDSIZE) == 0) {
/*
* A duplicate exists. Assign +1 value for the new serial
* number.
*/
stlong(ldlong(pkey + KEY_DUPS_OFF) + 1, keybuf + KEY_DUPS_OFF);
/*
* Set isdupl to 1 to indicate allowed duplicates exist.
*/
isdupl = 1;
}
else {
/*
* This is the first duplicate. Assign serial number 1.
*/
stlong(1L, keybuf + KEY_DUPS_OFF);
}
_isbtree_insert(btree, keybuf);
_isbtree_destroy(btree);
}
else {
/* Duplicates not allowed on this key.
* Set TID part to maximum value, causing the search path
* to point just past the possible duplicate in the key file
* If there is no duplicate, this is the correct spot to
* insert the new key entry.
*/
memcpy( keybuf + KEY_RECNO_OFF,(char *)ismaxlong, LONGSIZE);
_isbtree_search (btree, keybuf);
if ((pkey = _isbtree_current(btree)) != NULL &&
memcmp(pkey + RECNOSIZE, keybuf + RECNOSIZE,
pkeydesc2->k2_len - RECNOSIZE) == 0) {
_isbtree_destroy(btree);
return (EDUPL);
}
strecno(recnum, keybuf + KEY_RECNO_OFF);
_isbtree_insert(btree, keybuf);
_isbtree_destroy(btree);
}
/*
* Return new key position.
*/
if (newkey != NULL)
memcpy( newkey,keybuf, pkeydesc2->k2_len);
return (ISOK);
}

View File

@@ -0,0 +1,68 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isaddindex.c /main/3 1995/10/23 11:33:26 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isaddindex.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isaddindex.c
*
* Description:
* Add secondary index to ISAM file
*/
#include "isam_impl.h"
#include <sys/time.h>
/*
* err = isaddindex(isfd, keydesc)
*
* Isaddindex() is used to add an alternate index to ISAM file.
*
* Errors:
* EBADKEY error in keydesc
* EDUPL there are duplicate keys and the keydesc does not allow
* duplicate keys
* EKEXISTS key with the same key descriptor already exists
* ENOTEXCL ISAM file is not open in exclusive mode
* ENOTOPEN the ISAM file is not open in ISINOUT mode.
* EACCES Cannot create index file because of UNIX error.
*/
int
isaddindex(isfd, keydesc)
int isfd;
struct keydesc *keydesc;
{
int _amaddindex();
register Fab *fab;
int ret;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISOUTPUT
*/
if (fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
ret = _amaddindex(&fab->isfhandle, keydesc, &fab->errcode);
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}

View File

@@ -0,0 +1,80 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isaddprimary.c /main/3 1995/10/23 11:33:35 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isaddprimary.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/* @(#)isaddprimary.c 1.7 93/09/07
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isaddprimary.c
*
* Description:
* Add secondary index to ISAM file
*/
#include "isam_impl.h"
#include <sys/time.h>
Static int _am_addprimary();
/*
* err = isaddprimary(isfd, keydesc)
*
* Isaddprimary() is used to add primary index to ISAM file.
*
* This call is not part of the X/OPEN sprec.
*
* Errors:
* EBADKEY error in keydesc
* EDUPL there are duplicate keys and the keydesc does not allow
* duplicate keys
* EKEXISTS key with the same key descriptor already exists
* EKEXISTS the ISAM file already has a primary index.
* ENOTEXCL ISAM file is not open in exclusive mode
* ENOTOPEN the ISAM file is not open in ISINOUT mode.
* EACCES Cannot create index file because of UNIX error.
*/
int
isaddprimary(isfd, keydesc)
int isfd;
struct keydesc *keydesc;
{
register Fab *fab;
int ret;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISOUTPUT
*/
if (fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
ret = _am_addprimary(fab, keydesc);
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}
Static int _am_addprimary(fab, keydesc)
register Fab *fab;
struct keydesc *keydesc;
{
return (_amaddprimary(&fab->isfhandle, keydesc, &fab->errcode));
}

View File

@@ -0,0 +1,91 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isalloc.c /main/3 1995/10/23 11:33:43 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isalloc.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isalloc.c
*
* Description:
* Functions that allocate and deallocate memory.
* All errors are treated as fatal.
*/
#include "isam_impl.h"
#include <malloc.h>
/* strdup is not defined in Ultrix' string.h, so it is implemented in a separate
* file named strdup.ultrix.c
*/
#ifdef __ultrix__
extern char *strdup();
#endif
/*
* _ismalloc(nbytes)
*
* Allocate nbytes.
*/
char *_ismalloc(nbytes)
unsigned int nbytes;
{
register char *p;
if ((p = (char *) malloc (nbytes)) == NULL)
_isfatal_error("malloc() failed");
return (p);
}
char *_isrealloc(oldaddr, nbytes)
char *oldaddr;
unsigned int nbytes;
{
register char *p;
if ((p = (char *) realloc (oldaddr, nbytes)) == NULL)
_isfatal_error("realloc() failed");
return (p);
}
/*
* _isallocstring(str)
*
* Create a duplicate of string in dynamic memory.
*/
char *
_isallocstring(str)
char *str;
{
register char *p;
if ((p = strdup(str)) == NULL)
_isfatal_error("strdup() failed");
return (p);
}
/*
* _isfreestring(str)
*
* Free dynamically allocated string.
*/
void
_isfreestring(str)
char *str;
{
assert(str != NULL);
free(str);
}

290
cde/lib/tt/mini_isam/isam.h Normal file
View File

@@ -0,0 +1,290 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isam.h /main/3 1995/10/23 11:33:51 rswiston $ */
/*
@(#)isam.h
1.17 90/01/20
SMI */
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isam.h
*
* Description:
* isam.h is to be included in NetISAM C application programs.
*
* Make sure all changes in this file are reflected in lib/db/tt_client_isam.h
*/
#ifndef _ISAM_H
#define _ISAM_H
#include <limits.h>
#ifndef LONG_BIT
#define LONG_BIT 32
#endif
extern short ldint();
extern long ldlong();
extern float ldfloat();
extern double lddbl();
extern short ldshort();
extern ldchar(), stchar(), stlong(), stint(), stdbl(), stfloat();
extern stbin(), ldbin();
extern int iserrno; /* isam error number code */
extern long isrecnum; /* record number of last call */
extern int isreclen; /* used for variable length recs */
extern char isstat1; /* cobol status characters */
extern char isstat2;
#define CHARTYPE 0
#define CHARSIZE 1
#define INTTYPE 1
#define INTSIZE 2
#define LONGTYPE 2
#define LONGSIZE LONG_BIT/8
#define DOUBLETYPE 3
#define DOUBLESIZE 8
#define FLOATTYPE 4
#define FLOATSIZE 4
#define BINTYPE 5
#define BINSIZE 1
#define MINTYPE 0
#define MAXTYPE 6
#define ISDESC 0x80 /* add to make descending type */
#define TYPEMASK 0x7f /* type mask */
#define BYTEMASK 0xff /* mask for one byte */
#define BYTESHFT 8 /* shift for one byte */
/* mode parameter in isread() and isstart() */
#define ISFIRST 0 /* first record */
#define ISLAST 1 /* last record */
#define ISNEXT 2 /* next record */
#define ISPREV 3 /* previous record */
#define ISCURR 4 /* current record */
#define ISEQUAL 5 /* equal value */
#define ISGREAT 6 /* greater value */
#define ISGTEQ 7 /* >= value */
#define ISLESS 8 /* < */
#define ISLTEQ 9 /* <= */
/* isopen, isbuild lock modes */
#define ISAUTOLOCK 0x200 /* automatic record lock */
#define ISMANULOCK 0x400 /* manual record lock */
#define ISEXCLLOCK 0x800 /* exclusive isam file lock */
#define ISFASTLOCK 0x4000 /* no locking when EXCLLOCK! */
/* isread lock modes */
#define ISLOCK 0x100 /* lock record before reading */
#define ISSKIPLOCK 0x1000 /* advance record pointer to */
/* locked record */
/* isstart lock mode for automatic record locking */
#define ISKEEPLOCK 0x2000 /* keep record locked */
/* Fix/Variable length records mode */
#define ISFIXLEN 0
#define ISVARLEN 0x10000
/* Access remote file via NFS */
#define ISNFS 0x20000
#define ISINPUT 0 /* open for input only */
#define ISOUTPUT 1 /* open for output only */
#define ISINOUT 2 /* open for input and output */
#define MAXKEYSIZE 150 /* max number of bytes in key */
#define NPARTS 8 /* max number of key parts */
/*#define ISMAXRECLEN 8192 */ /* Maximum number of bytes in record */
#define ISMAXRECLEN 32767 /* 32K - 1 */
#define ISMINRECLEN 4 /* Minimum number of bytes in record */
struct keypart {
unsigned short kp_start; /* starting byte of key part */
short kp_leng; /* length in bytes */
short kp_type; /* type of key part */
};
struct keydesc {
short k_flags; /* flags */
short k_nparts; /* number of parts in key */
struct keypart k_part[NPARTS]; /* each part */
};
/* The next three defines are for compatibility with X/OPEN */
#define k_start k_part[0].kp_start
#define k_leng k_part[0].kp_leng
#define k_type k_part[0].kp_type
#define ISNODUPS 000 /* no duplicates and */
/* no compression */
#define ISDUPS 001 /* duplicates allowed */
#define COMPRESS 020 /* full compression */
struct dictinfo {
short di_nkeys; /* number of keys defined */
unsigned short di_recsize; /* data record size */
short di_idxsize; /* index record size */
long di_nrecords; /* number of records in file */
};
/* msb in di_nkeys indicates that ISAM file supports variable length records */
#define DICTVARLENBIT 0x8000
/* mask to access the true number of keys */
#define DICTNKEYSMASK (DICTVARLENBIT - 1)
#define ENOERROR 0 /* No error */
#define EDUPL 100 /* duplicate record */
#define ENOTOPEN 101 /* file not open */
#define EBADARG 102 /* illegal argument */
#define EBADKEY 103 /* illegal key desc */
#define ETOOMANY 104 /* too many files open */
#define EBADFILE 105 /* bad ISAM file format */
#define ENOTEXCL 106 /* non-exclusive access */
#define ELOCKED 107 /* record locked */
#define EKEXISTS 108 /* key already exists */
#define EPRIMKEY 109 /* is primary key */
#define EENDFILE 110 /* end/begin of file */
#define ENOREC 111 /* no record found */
#define ENOCURR 112 /* no current record */
#define EFLOCKED 113 /* file locked */
#define EFNAME 114 /* file name too long */
#define EBADMEM 116 /* cannot allocate memory */
/* NetISAM specific error codes non XOPEN compliant*/
#define ETIMEOUT 1117 /* RPC timeout */
#define ERPC 1118 /* Broken TCP/IP */
#define ETCP 1119 /* Cannot connect to server */
#define EIMPORT 1120 /* Cannot import */
#define ENODAEMON 1121 /* no local daemon */
#define EFATAL 1122 /* internal fatal error */
#define ELANG 1123 /* Locale/LANG mismatch */
#define ISOK 0 /* no error return code */
#define ISERROR -1 /* error return code */
extern struct keydesc *nokey; /* May be used as parameter
* to isbuild() if no
* primary key is to be built
*/
/* ischeckindex() diagmode values */
#define CHK_NODIAG 0 /* do not print any messages */
#define CHK_DIAG 1 /* Access Level module will print to stderr */
/* values of corrupt parameter of ischeckindex() */
#define CHK_OK 0 /* ISAM file is not corrupted */
#define CHK_DAT 1 /* .dat file is corrupted */
#define CHK_VAR 2 /* .var file is corrupted */
#define CHK_IND 3 /* .ind file is corrupted */
/* iscntl() definitions */
/* For one isfd - use iscntl(isfd, func, ...) */
#define ISCNTL_RPCS_TO_SET 1 /* short oper. timeout (in sec) */
#define ISCNTL_RPCS_TO_GET 2 /* short oper. timeout (in sec) */
#define ISCNTL_RPCL_TO_SET 3 /* long oper. timeout (in sec) */
#define ISCNTL_RPCL_TO_GET 4 /* long oper. timeout (in sec) */
#define ISCNTL_TCP_TO_SET 5 /* timeout to reconnect TCP?IP */
#define ISCNTL_TCP_TO_GET 6 /* timeout to reconnect TCP?IP */
#define ISCNTL_APPLMAGIC_WRITE 7 /* Write Appl. Magic */
#define ISCNTL_APPLMAGIC_READ 8 /* Read Appl. Magic */
#define ISCNTL_FSYNC 9 /* Flush pages to disk */
#define ISCNTL_FDLIMIT_SET 10 /* Set UNIX fd usage limit */
#define ISCNTL_FDLIMIT_GET 11 /* Get UNIX fd usage limit */
#define ISCNTL_FATAL 12 /* Specify NetISAM fatal error hadler */
#define ISCNTL_MASKSIGNALS 13 /* Enable or Disable masking signals during NetISAM operations */
#define ISAPPLMAGICLEN 32
/*
* ALLISFD in iscntl() calls means that the operation should be done
* on all open file descriptors, or the operation is not related to
* any file descriptor (e.g: maskintg signals)
*/
#define ALLISFD (-2)
/* isshowlocks() and isshowhostlocks() return an array of struct showlock */
#define IPADDRLEN 4 /* IP address length */
struct showlock {
short dev; /* Major/Minor device number,
* actually type dev_t */
long inode; /* inode number */
long recnum; /* record number */
char hostid[IPADDRLEN]; /* IP address of host */
short pid; /* UNIX process ID */
long uid; /* User ID */
short type; /* See below */
};
/* NetISAM Programmer Toolkit related definitions */
struct isfldmap {
char *flm_fldname;
short flm_recoff;
short flm_bufoff;
short flm_type;
short flm_length;
};
struct istableinfo {
char *tbi_tablename;
int tbi_reclength;
int tbi_nfields;
struct isfldmap *tbi_fields;
int tbi_nkeys;
struct keydesc *tbi_keys;
char **tbi_keynames;
};
/* record descriptor isreadm/iswritem record descriptor */
struct recorddesc {
char *rec_buffer;
long rec_number;
short rec_length;
short rec_locked;
};
/*
* The following defines and variable definitions are not used by NetISAM 1.0.
* They are defined for compatibility with VSX 2.5.
*/
#define EBADCOLL (-1)
#define IO_OPEN 0x10 /* open() */
#define IO_CREA 0x20 /* creat() */
#define IO_SEEK 0x30 /* lseek() */
#define IO_READ 0x40 /* read() */
#define IO_WRIT 0x50 /* write() */
#define IO_LOCK 0x60 /* lockf() */
#define IO_IOCTL 0x70 /* ioctl() */
#define IO_RENAME 0x80 /* rename() */
#define IO_UNLINK 0x90 /* unlink() */
extern int iserrio;
#endif /* !_ISAM_H */

View File

@@ -0,0 +1,762 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: isam_impl.h /main/4 1998/03/16 14:41:21 mgreess $ */
/* @(#)isam_impl.h 1.11 93/09/07 */
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isam_impl.h
*
* Description:
* NetISAM implementation specific definitions
*
*/
#ifndef _ISAM_IMPL_H
#define _ISAM_IMPL_H
#include <assert.h>
#include <stdio.h>
#include <fcntl.h>
#include <setjmp.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
/* AIX does not define FD_SETSIZE in sys/types.h. */
#if !defined(FD_SETSIZE)
#include <sys/select.h>
#endif
/*
* #include sys/types.h is to get u_long, u_short, dev_t
*
* #include sys/param.h is to get MAXHOSTNAMELEN
*/
#include "isam.h"
/*
* Static is used in definitions of local functions. It is defined to
* "static" normally, but to an empty string when compiled for profiling
* purposes (-p or -pg options to the cc compiler). If a function is
* defined as static, then the profiling tools account the time spent in
* this function to the physically previous global function which is
* incorrect and makes the output of the profiler tools useless.
*/
#if defined(PROF) || defined(GPROF)
#define Static
#else
#define Static static
#endif
extern int isdupl;
typedef long Recno; /* record numbers */
typedef long Blkno; /* block numbers */
typedef long Time; /* standard UNIX time */
typedef int Isfd; /* ISAM file descriptor */
typedef int Bool;
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
#define ISOPENMODE 0xff /* Mask to get ISINPUT/ISOUTPUT */
/* or ISINOUT */
#define ISLOCKMODE 0xff00 /* Mask to get lock mode */
#define ISREADMODE 0xff /* Mask to get ISFIRST, etc. */
#define ISLENMODE 0x10000 /* Mask to get FIX/VAR length */
#define ISPAGESIZE 1024 /* page size */
#define N_CNTL_PAGES 2 /*
* Number of control pages
* at the beg. of .rec file
*/
#define ISCNTLSIZE (ISPAGESIZE * N_CNTL_PAGES)
#define ISMAGIC "NetISAM" /* 'magic number' in ISAM files */
#ifndef ISVERSION
#define ISVERSION "Unknown"
#endif
#define MAXFCB_UNIXFD 30 /* Maximum number of UNIX fd
* used by the FCB module
*/
#define ISLEAFSLACK 10 /* Default slack in leaves */
/* Default RPC timeout values */
#define ISRPCS_TO_DEF 60 /* secs for short oper. */
#define ISRPCL_TO_DEF (120 * 60) /* secs for long oper. */
#define ISTCP_TO_DEF (3 * 60) /* secs to reconnect TCP/IP */
#define ISRPC_POLL_TO_DEF 30 /* interval to hear from polled client */
#define ISTCP_RETRY_SLEEP 5 /* time between tries to
* establish a connection
*/
/*
* The X/OPEN ISAM internal data representations.
* The #define statements are used to declare type lengths and offsets
* in structures in order for the definitions to be compiler independent.
*/
#define TIMETYPE LONGTYPE /* standard UNIX time */
#define TIMESIZE LONGSIZE
#define BLKNOTYPE LONGTYPE /* block (page) numbers */
#define BLKNOSIZE LONGSIZE
#define RECNOTYPE LONGTYPE /* record numbers */
#define RECNOSIZE LONGSIZE
/*
* SHORTTYPE is a safeguard - if the X/OPEN ISAM changes INTTYPE to 4 bytes
* all the internals of NetISAM will work. The only change will be
* re-defining SHORTTYPE.
*/
#define SHORTTYPE INTTYPE
#define SHORTSIZE INTSIZE
/* The following defines are used in isstart() */
#define WHOLEKEY 0
#define USE_PHYS_ORDER(keydesc) (keydesc->k_nparts == 0)
/* Structure for storing and passing variable length byte array data */
typedef struct bytearray {
u_short length;
char *data;
} Bytearray;
extern Bytearray _bytearr_getempty(), _bytearr_dup(), _bytearr_new();
extern void _bytearr_free();
/* Client identification - used to identify owners of locks */
/*
#define IPADDRLEN 4
*/
/* Definitions related to ISAM file descriptor (isfd.c file) */
#define MAXISFD FD_SETSIZE
#define NOISFD (-1) /* Not a valid file descriptor */
extern struct fab *_isfd_find();
extern void _isfd_delete();
extern Isfd _isfd_insert();
/* Definitions related to File access block (isfab.c file */
/* File open mode */
enum openmode { OM_INPUT = 0, OM_OUTPUT = 1, OM_INOUT = 2, OM_BADMODE = 3};
enum lockmode { LM_FAST = 0, LM_EXCL = 1, LM_AUTOMATIC = 2, LM_MANUAL = 3, LM_BADMODE = 4};
/* isread() read modes */
enum readmode { RM_FIRST = 0, RM_LAST = 1, RM_NEXT = 2, RM_PREV = 3,
RM_CURR = 4, RM_EQUAL = 5, RM_GREAT = 6, RM_GTEQ = 7,
RM_LESS = 8, RM_LTEQ = 9, RM_BADMODE = 10 };
/* lock flag is passed to Access Method module for every record oriented op. */
/* Bit position in the lock flag: */
enum openmode _getopenmode();
enum readmode _getreadmode();
/* Error code structure */
struct errcode {
int iserrno;
char isstat [4];
};
typedef struct fab {
Isfd isfd; /* ISAM file descriptor */
enum openmode openmode; /* File access mode */
enum lockmode lockmode; /* File lock mode */
Bool locked; /* TRUE if file is locked */
Bool varlength; /* TRUE if variable length records
* supported by this ISAM file */
int minreclen; /* Minimum record length */
int maxreclen; /* Maximum record length */
char *isamhost; /* IP host name */
char *isfname; /* ISAM file local pathname */
Bytearray isfhandle; /* ISAM file handle */
Bytearray curpos; /* Current record position */
struct errcode errcode; /* Error codes structure */
} Fab;
/* values for filemode */
#define LOCAL_FILE 0
#define REMOTE_FILE 1
#define NFS_FILE 2 /* File is remote, but is
* accessed via NFS
*/
#define FAB_ISFDSET(fab, isfd) (fab->isfd = isfd)
extern Fab *_fab_new();
void _fab_destroy();
/* ISAM file identification for locking purposes. */
typedef struct lckfid {
dev_t diskid; /* Disk device id */
ino_t inode; /* .rec file inode number */
} Lckfid;
/* File Control Block */
typedef struct fcb {
char *isfname; /* ISAM file name */
int blocksize; /* Block size */
Bool rdonly; /* file is read-only */
Lckfid lckfid; /* File id for locking */
int datfd; /* UNIX file descr. of .rec file */
int indfd; /* UNIX file descr. of .ind file */
int varfd; /* UNIX file descr. of .var file */
Blkno datsize; /* dat file size in blocks */
Blkno indsize; /* ind file size in blocks */
Blkno varsize; /* var file size in blocks */
Bool varflag; /* TRUE if variable length*/
long nrecords; /* Number of records */
int minreclen; /* Minimum record length */
int maxreclen; /* Maximum record length */
Recno lastrecno; /* Last recno in use */
Recno freerecno; /* Pointer to first free record */
int lastkeyid; /* Last key identifier used */
int changestamp1; /* Stamp 1 of last change */
int changestamp2; /* Stamp 2 of last change */
Blkno indfreelist; /* Head of freepage list of .ind */
int nkeys; /* Number of keys */
struct keydesc2 *keys; /* Key descriptors */
long varend; /* Offset of the last byte */
/* in .var file */
int lockfd; /* lock file fd for locking .rec for 5.0 */
} Fcb;
#define FCB_NOPRIMARY_KEY(fcb) ((fcb)->keys[0].k2_nparts == 0)
/* Current Record Position (interpreted only by Access Method) */
enum crpflag { CRP_UNDEF = 0, CRP_ON = 1, CRP_AFTER = 2, CRP_BEFORE = 3,
CRP_BEFOREANY = 4, CRP_AFTERANY = 5};
typedef struct crp {
int keyid; /* Key index */
enum crpflag flag; /* ON/BEFORE/AFTER/UNDEF */
Recno recno; /* Record number */
int matchkeylen; /* match so many bytes of key */
char key[1]; /* Index position */
} Crp;
#define PHYS_ORDER (-1) /* value for keyid when physical
order is used*/
/*
* keydesc2 is the 'internal copy'of keydesc.
* keydesc2 contains all information needed by internally by NetISAM,
* whereas keydesc conforms to the X/OPEN ISAM.
*/
#define NPARTS2 (NPARTS+2) /* duplid and recno */
#define DUPSMASK 001 /* Mask to get ISDUPS/ISNODUPS */
#define ISPRIMKEY 040 /* this is primary key */
#define ALLOWS_DUPS2(pkdesc2) (((pkdesc2)->k2_flags & DUPSMASK) == ISDUPS)
#define ALLOWS_DUPS(pkdesc) (((pkdesc)->k_flags & DUPSMASK) == ISDUPS)
/* serial number of duplicate keys */
#define DUPIDTYPE LONGTYPE
#define DUPIDSIZE LONGSIZE
#define KEY_RECNO_OFF 0
#define KEY_DUPS_OFF RECNOSIZE
#define stdupser(n, b) stlong((long)(n), (b))
#define lddupser(b) ((int)ldlong(b))
struct keypart2 {
u_short kp2_start; /* starting byte of key part */
short kp2_leng; /* length in bytes */
short kp2_type; /* type of key part */
u_short kp2_offset; /* offset in key buffer */
};
typedef struct keydesc2 {
short k2_flags; /* flags */
short k2_nparts; /* number of parts in key */
short k2_len; /* length of the whole key */
Blkno k2_rootnode; /* pointer to root node */
int k2_keyid; /* Key identifier */
struct keypart2 k2_part[NPARTS2]; /* each part */
} Keydesc2;
typedef unsigned long rel_addr;
/* Double linked list element */
struct dlink {
rel_addr dln_forward; /* Forward link */
rel_addr dln_backward; /* Backward link */
};
/* Disk buffer management definitions */
/* cache buffer header */
typedef struct bufhdr {
Fcb *isb_fcb; /* Pointer to FCB */
int isb_unixfd; /* UNIX file descriptor */
Blkno isb_blkno; /* block number */
struct dlink isb_hash; /* hashed list*/
struct dlink isb_aclist; /* available or changed list */
struct dlink isb_flist; /* list of fixed blocks */
char *isb_buf_w; /* malloc() buffer with dirty data */
char *isb_buf_r; /* points to mapped segment */
char *isb_buffer; /* set to isb_buf_r or isb_buf_w */
char isb_flags; /* flags - defs. see below */
struct bufhdr *isb_oldcopy; /* pointer to old copy */
} Bufhdr;
/* mapped segment header */
typedef struct maphdr {
Fcb *m_fcb; /* Pointer to FCB */
int m_unixfd; /* UNIX file descriptor */
char *m_addr; /* Pointer to beginning of seg. */
int m_segm_num; /* Segment number in the file */
unsigned long m_stamp; /* Assigned when touched */
} Maphdr;
/* values of isb_flags */
#define ISB_NODATA 00 /* block has no data */
#define ISB_READ 01 /* page has valid data */
#define ISB_CHANGE 02 /* page must be flushed */
#define ISB_RFIXED 04 /* block is fixed for read*/
#define ISB_WFIXED 010 /* block is fixed for write*/
#define ISB_OLDCOPY 020 /* block is old copy */
/* mode values to is__cache_fix() */
#define ISFIXREAD 1 /* fix for read */
#define ISFIXWRITE 2 /* fix for update */
#define ISFIXNOREAD 3 /* fix for update, don't read */
/*
* Macro to get pointer to structure if pointer to some element is known
*/
#define GETBASE(p,s,e) ((struct s *) ((char *)(p) - (int)&((struct s *)0)->e))
/* In memory sorting object */
typedef struct issort {
int ist_reclength; /* record length in bytes */
int ist_allocrecs; /* memory allocated for so */
/* many records */
int ist_nrecs; /* number of records inserted */
int ist_currec; /* current position */
int (*ist_compf) (); /* comparison function */
char *ist_array; /* array of records */
} Issort;
/* btree is object used for processing B-tree operations */
#define ISMAXBTRLEVEL 12 /* Maximum level of B-tree */
typedef struct btree {
Fcb *fcb;
Keydesc2 *keydesc2;
int depth; /* depth of the B-tree */
Bufhdr *bufhdr[ISMAXBTRLEVEL]; /* fixed blocks buf. headers */
int curpos[ISMAXBTRLEVEL]; /* current position on block */
} Btree;
/* Lock manager related definitions. */
/* Entry in lock table */
/* Number of buckets for hashing by clientid. Must be a power of 2*/
#ifndef HASHPROCSIZE
#define HASHPROCSIZE 64
#endif
/*
* Number of buckets for hashing by record number and fileid.
* Must be a power of 2
*/
#ifndef HASHENTSIZE
#define HASHENTSIZE 1024
#endif
/* Pseudo record numbers used by file locking. */
#define AVAIL_RECNO (0L) /* Entry is available */
#define ALLFILE_RECNO (-1L) /* Entire file lock */
#define OPENFILE_RECNO (-2L) /* Used by isopen() */
/* Lock table file header */
struct lockfilehdr {
int size; /* size of LOCKTABLEFILE
* set to 0 forces reinitialization
* at next lock request.
*/
int prochdsn; /* Number of lists hashed by
* clientid */
int enthdsn; /* Number of list hashed by
* record number */
int lockentriesn; /* total number of lock entries */
struct dlink avail; /* Double linked list of
* available lock entries */
};
/* Exported filesystem options structure and constants*/
#define RW_CLIENTS_SIZE 1 /* Not currently needed */
#define UID_SIZE 10 /* Big enough to hold a Unix UID */
#define ROOT_OPT_SIZE 240 /* List of hosts for which root access
is allowed -- can be quite long */
#define SHARE_BUFFER_SIZE 400
struct export_opts {
int read_write; /* 0 => read-only, 1 => read/write */
char rw_clients[1]; /* Not interesting, len=1 to save space */
char export_dir[1]; /* ditto here */
char anon[UID_SIZE];
char root[ROOT_OPT_SIZE];
int secure; /* RPC authentication flag: 0 => AUTH_UNIX, 1 => AUTH_DES */
};
extern Fcb *_isfcb_create();
extern Fcb *_isfcb_open();
extern void _isfcb_remove();
extern void _isfcb_close();
extern void _isfcb_setreclength();
extern void _isfcb_setprimkey();
extern int _isfcb_cntlpg_w();
#define DAT_SUFFIX ".rec"
#define IND_SUFFIX ".ind"
#define VAR_SUFFIX ".var"
#define LOCK_SUFFIX ".lock" /* yh: lock file for .rec to solve mmap in 5.0 */
/* Values of deleted flag for fixed length records */
#define FL_RECDELETED 0
#define FL_RECEXISTS 1
/* Special values of tail pointer for variable length records */
#define VL_RECDELETED ((long ) -1L)
#define VL_RECNOTAIL ((long ) -2L)
extern long lseek();
extern char *_ismalloc(), *_isrealloc(), *_isallocstring();
extern void _isfree(), _isfreestring();
extern void _isfatal_error(), _setiserrno2(), _seterr_errcode();
extern void _makedat_isfname();
extern void _makeind_isfname();
extern void _makevar_isfname();
extern void _amseterrcode();
extern void _isseekpg(), _isreadpg(), _iswritepg();
extern Bufhdr *_isdisk_fix(), *_isdisk_refix();
extern void _isdisk_commit(), _isdisk_sync(), _isdisk_inval(),
_isdisk_commit1(), _isdisk_unfix();
extern void _isdisk_rollback();
extern void _cp_tofile(), _cp_fromfile();
Blkno _extend_file();
extern void _isdln_base_insert(), _isdln_base_remove(), _isdln_base_append(),
_isdln_base_makeempty();
extern struct dlink *_isdln_base_prev(), *_isdln_base_next(), *_isdln_base_first();
extern void _mngfcb_insert(), _mngfcb_delete();
extern Fcb *_mngfcb_find();
extern Bytearray *_mngfcb_victim();
extern char *_getisfname();
extern Bytearray _makeisfhandle();
extern Bytearray _makeisfhandle();
extern Fcb *_openfcb();
extern Time _amtime_set(), _amtime_get();
extern void _islock_closefile(), _islock_unlockfile();
extern Keydesc2 *_isfcb_findkey(), *_isfcb_indfindkey();
extern void stkey(), ldkey();
extern Issort *_issort_create();
extern char *_issort_read();
extern void _issort_destroy(), _issort_insert(), _issort_sort(),
_issort_rewind();
extern void _iskeycmp_set();
extern int _iskeycmp();
extern char *_isbsearch();
extern void _iskey_extract();
extern Blkno _isindfreel_alloc();
extern void _isindfreel_free();
extern long _fl_getpos();
extern Btree *_isbtree_create();
extern void _isbtree_destroy(), _isbtree_search(), _isbtree_insert(),
_isbtree_remove();
extern char *_isbtree_current(), *_isbtree_next();
extern void _iskey_fillmin(), _iskey_fillmax();
extern Bufhdr *_allockpage();
extern void _del1key();
extern int _add1key(), _change1key();
extern void _delkeys();
extern char *_ismap_getaddr();
extern void _ismap_endop(), _ismap_unmapfcb();
extern void _isam_entryhook(), _isam_exithook();
#define stshort(n,p) stint((n), (p))
#define ldshort(p) ldint(p)
#define strecno(n,p) stlong((long)(n), (p))
#define ldrecno(p) ((Recno)ldlong(p))
#define stblkno(n,p) stlong((long)(n), (p))
#define ldblkno(p) ((Blkno)ldlong(p))
extern int _flrec_read(), _flrec_write(), _flrec_rewrite(), _flrec_delete(),
_flrec_wrrec();
extern int _vlrec_read(), _vlrec_write(), _vlrec_rewrite(), _vlrec_delete(),
_vlrec_wrrec();
/*------------ UNIX file formats ---------------------------------------------*/
#define ISCNTLPGOFF ((Blkno) 0) /* offset of Control Page */
/* internal key descriptor */
#define KP2_START_OFF 0 /* see struct keypart2 */
#define KP2_LENGTH_OFF SHORTSIZE
#define KP2_TYPE_OFF (2*SHORTSIZE)
#define KP2_OFFSET_OFF (3*SHORTSIZE)
#define KP2_LEN (4*SHORTSIZE)
#define K2_FLAGS_OFF 0 /* see struct keydesc2 */
#define K2_NPARTS_OFF SHORTSIZE
#define K2_LEN_OFF (2*SHORTSIZE)
#define K2_ROOT_OFF (3*SHORTSIZE)
#define K2_KEYID_OFF (3*SHORTSIZE+BLKNOSIZE)
#define K2_KEYPART_OFF (3*SHORTSIZE+2*BLKNOSIZE)
#define K2_LEN (3*SHORTSIZE+2*BLKNOSIZE+ NPARTS2*KP2_LEN)
#define NULL_BLKNO 0L
#define NULL_RECNO 0L
#define PAGE1_BLKNO 0 /* Block number of control page */
/*------------------------- Control Page layout -----------------------------*/
/* Magic number (must be equal to "NetISAM") */
#define CP_MAGIC_OFF 0
#define CP_MAGIC_LEN 8
/* Version stamp */
#define CP_VERSION_OFF (CP_MAGIC_OFF+CP_MAGIC_LEN)
#define CP_VERSION_LEN 8
/* Application stamp */
#define CP_APPLMAGIC_OFF (CP_VERSION_OFF+ CP_VERSION_LEN)
#define CP_APPLMAGIC_LEN ISAPPLMAGICLEN
/* Block size */
#define CP_BLOCKSIZE_OFF (CP_APPLMAGIC_OFF+CP_APPLMAGIC_LEN)
#define CP_BLOCKSIZE_LEN SHORTSIZE
/* file size in blocks */
#define CP_DATSIZE_OFF (CP_BLOCKSIZE_OFF+CP_BLOCKSIZE_LEN)
#define CP_DATSIZE_LEN BLKNOSIZE
/* file size in blocks */
#define CP_INDSIZE_OFF (CP_DATSIZE_OFF+CP_DATSIZE_LEN)
#define CP_INDSIZE_LEN BLKNOSIZE
/* file size in blocks */
#define CP_VARSIZE_OFF (CP_INDSIZE_OFF+CP_INDSIZE_LEN)
#define CP_VARSIZE_LEN BLKNOSIZE
/* 0/1 flag telling whether file supports variable length records. */
#define CP_VARFLAG_OFF (CP_VARSIZE_OFF+CP_VARSIZE_LEN)
#define CP_VARFLAG_LEN SHORTSIZE
/* number of record in the file */
#define CP_NRECORDS_OFF (CP_VARFLAG_OFF+CP_VARFLAG_LEN)
#define CP_NRECORDS_LEN LONGSIZE
/* minimum record length */
#define CP_MINRECLEN_OFF (CP_NRECORDS_OFF+CP_NRECORDS_LEN)
#define CP_MINRECLEN_LEN SHORTSIZE
/* maximum record length */
#define CP_MAXRECLEN_OFF (CP_MINRECLEN_OFF+CP_MINRECLEN_LEN)
#define CP_MAXRECLEN_LEN SHORTSIZE
/*
* Left 0 and not used in NetISAM 1.0.
* Will be set at restructuring to some optimal value x
* (minreclen <= x <= maxreclen).
* Record with length will be stored in .rec file only.
* In NetISAM 1.0 x == minreclen.
*/
/* split record record length */
#define CP_SPLITRECLEN_OFF (CP_MAXRECLEN_OFF+CP_MAXRECLEN_LEN)
#define CP_SPLITRECLEN_LEN SHORTSIZE
/* Recno of last record */
#define CP_LASTRECNO_OFF (CP_SPLITRECLEN_OFF+CP_SPLITRECLEN_LEN)
#define CP_LASTRECNO_LEN RECNOSIZE
/* Head of deleted records list */
#define CP_FREERECNO_OFF (CP_LASTRECNO_OFF+CP_LASTRECNO_LEN)
#define CP_FREERECNO_LEN RECNOSIZE
/* 0/1 flag telling whether file has a primary key */
#define CP_HASPRIMKEY_OFF (CP_FREERECNO_OFF+CP_FREERECNO_LEN)
#define CP_HASPRIMKEY_LEN SHORTSIZE
/* Last key indentifier. */
#define CP_LASTKEYID_OFF (CP_HASPRIMKEY_OFF+CP_HASPRIMKEY_LEN)
#define CP_LASTKEYID_LEN LONGSIZE
/* Stamp 1 of last change */
#define CP_CHANGESTAMP1_OFF (CP_LASTKEYID_OFF+CP_LASTKEYID_LEN)
#define CP_CHANGESTAMP1_LEN LONGSIZE
/* Stamp 2 of last change */
#define CP_CHANGESTAMP2_OFF (CP_CHANGESTAMP1_OFF+CP_CHANGESTAMP1_LEN)
#define CP_CHANGESTAMP2_LEN LONGSIZE
/* .ind file free list */
#define CP_INDFREELIST_OFF (CP_CHANGESTAMP2_OFF+CP_CHANGESTAMP2_LEN)
#define CP_INDFREELIST_LEN BLKNOSIZE
/* number of keys */
#define CP_NKEYS_OFF (CP_INDFREELIST_OFF+CP_INDFREELIST_LEN)
#define CP_NKEYS_LEN SHORTSIZE
/* use 4 bytes of reserved space */
#define CP_VAREND_OFF (CP_NKEYS_OFF+CP_NKEYS_LEN)
#define CP_VAREND_LEN LONGSIZE
/* use 4 bytes of reserved space for time stamp*/
#define CP_UNIQUE_OFF (CP_VAREND_OFF+CP_VAREND_LEN)
#define CP_UNIQUE_LEN LONGSIZE
/* reserve some space for future */
#define CP_RESERVE_OFF (CP_UNIQUE_OFF+CP_UNIQUE_LEN)
#define CP_RESERVE_LEN 120 /* 128 was reserved originally */
/* table of key descriptors */
#define CP_KEYS_OFF (CP_RESERVE_OFF+CP_RESERVE_LEN)
#define MAXNKEYS2 ((ISCNTLSIZE - CP_KEYS_OFF) / K2_LEN)
#define MAXNKEYS 17
#if (MAXNKEYS2 < MAXNKEYS)
Cause a compiler error here. There is not enought space in the control
page to hold MAXNKEYS.
#endif
/*------ page type indicator values -------------*/
#define PT_INDEX 1 /* B-tree page */
#define PT_FREELIST 2 /* free list */
/*-------------- B-Tree page layout -----------------------------------*/
/* page type */
#define BT_TYPE_OFF 0
#define BT_TYPE_LEN SHORTSIZE
/* level (leaves have level 0) */
#define BT_LEVEL_OFF (BT_TYPE_OFF+BT_TYPE_LEN)
#define BT_LEVEL_LEN SHORTSIZE
/* page capacity */
#define BT_CAPAC_OFF (BT_LEVEL_OFF+BT_LEVEL_LEN)
#define BT_CAPAC_LEN SHORTSIZE
/* current number of keys */
#define BT_NKEYS_OFF (BT_CAPAC_OFF+BT_CAPAC_LEN)
#define BT_NKEYS_LEN SHORTSIZE
/* array of key entries */
#define BT_KEYS_OFF (BT_NKEYS_OFF+BT_NKEYS_LEN)
/* down pointers are stored at the end of the page */
/*----------- Free List Page Layout --------------------------------------*/
/* page type */
#define FL_TYPE_OFF 0
#define FL_TYPE_LEN SHORTSIZE
/* pointer to next block in the list */
#define FL_NEXT_OFF (FL_TYPE_OFF + FL_TYPE_LEN)
#define FL_NEXT_LEN BLKNOSIZE
/* number of free page pointers */
#define FL_NPOINTERS_OFF (FL_NEXT_OFF + FL_NEXT_LEN)
#define FL_NPOINTERS_LEN SHORTSIZE
/* free page pointers table */
#define FL_POINTERS_OFF (FL_NPOINTERS_OFF + FL_NPOINTERS_LEN)
/* maximum number of pointers that can be stored in a page */
#define FL_MAXNPOINTERS ((ISPAGESIZE - FL_POINTERS_OFF) / BLKNOSIZE)
#define FREELIST_NOPAGE ((Blkno) -1)
/* .var file related defines */
#define VR_FRAMELEN_OFF 0
#define VR_TAILLEN_OFF 2
/* maximum and minimum values are in B-tree seaches */
#if LONG_BIT == 64
#define ISMAXLONG { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
#define ISMINLONG { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#else
#define ISMAXLONG { 0x7f, 0xff, 0xff, 0xff }
#define ISMINLONG { 0x80, 0x00, 0x00, 0x00 }
#endif
#define ISMAXSHORT { 0x7f, 0xff }
#define ISMINSHORT { 0x80, 0x00 }
#define ISMINCHAR ('\0')
#define ISMAXCHAR ('\377')
#define ISMINBIN ('\0')
#define ISMAXBIN ('\377')
/* double and float are declared using IEEE bit paterns */
#define ISMAXDOUBLE { 0x7f, 0xf0, 0, /* rest is 0 */ }
#define ISMINDOUBLE { 0xff, 0xf0, 0, /* rest is 0 */ }
#define ISMAXFLOAT { 0x7f, 0x80, 0, /* rest is 0 */ }
#define ISMINFLOAT { 0xff, 0x80, 0, /* rest is 0 */ }
/* Hide these from user till we return error code */
extern char isstat3;
extern char isstat4;
#define OP_BUILD 0
#define OP_OPEN 1
#endif

View File

@@ -0,0 +1,651 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isamaddindex.c /main/3 1995/10/23 11:34:12 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isamaddindex.c 1.14 89/09/14 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isaddindex.c
*
* Description:
* Add secondary index
*
*
*/
#include "isam_impl.h"
#include <sys/types.h>
#include <sys/stat.h>
extern int _iskeycmp();
static void _readallrecords(), _attach_dups_serial();
static Blkno _buildbtree();
static int _duplicate_exist();
static checkavailfd();
/*
* _amaddindex(isfhandle, keydesc, errcode)
*
* _amaddindex() build a secondary index
*
* Input params:
* isfhandle Handle of ISAM file
* keydesc Key descriptor
*
* Output params:
* errcode error status of the operation
*
*/
/*ARGSUSED*/
int
_amaddindex(isfhandle, keydesc, errcode)
Bytearray *isfhandle;
struct keydesc *keydesc;
struct errcode *errcode;
{
Fcb *fcb = NULL;
Keydesc2 keydesc2;
int err;
_isam_entryhook();
/*
* Check if 1 UNIX file decriptor is available.
*/
checkavailfd();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
/*
* Check that the limit on the number of keys is not exceeded.
*/
if (fcb->nkeys >= MAXNKEYS) {
_amseterrcode(errcode, ETOOMANY);
goto ERROR;
}
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r(fcb);
/*
* Check key descriptor for validity.
*/
if (_validate_keydesc(keydesc, fcb->minreclen) != ISOK) {
_amseterrcode(errcode, EBADKEY);
goto ERROR;
}
/*
* Convert key descriptor to internal form.
*/
_iskey_xtoi (&keydesc2, keydesc);
/* Check if key already exists. */
if (_isfcb_findkey(fcb ,&keydesc2) != (Keydesc2 *) 0) {
_amseterrcode(errcode, EKEXISTS);
goto ERROR;
}
/*
* Open (or even create) .ind file if that is not open (created) yet.
*/
if (_open2_indfile(fcb) != ISOK) {
_amseterrcode(errcode, EACCES);
goto ERROR;
}
/*
* Create index structure.
*/
if ((err = _create_index(fcb ,&keydesc2)) != ISOK) {
_amseterrcode(errcode, err);
goto ERROR;
}
/*
* Add key descriptor to FCB.
*/
if (_isfcb_altkeyadd(fcb, &keydesc2) == ISERROR) {
_amseterrcode(errcode, ETOOMANY);
goto ERROR;
}
_amseterrcode(errcode, ISOK);
_issignals_mask();
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
/*
* Update CNTL Page from the FCB.
*/
(void)_isfcb_cntlpg_w(fcb);
_issignals_unmask();
_isam_exithook();
return (ISOK);
ERROR:
_isdisk_rollback();
_isdisk_inval();
/*
* Restore FCB from CNTL page.
*/
if (fcb) (void)_isfcb_cntlpg_r(fcb);
_isam_exithook();
return (ISERROR);
}
/*
* _amaddprimary(isfhandle, keydesc, errcode)
*
* _amaddprimary() build primary key
*
* Input params:
* isfhandle Handle of ISAM file
* keydesc Key descriptor
*
* Output params:
* errcode error status of the operation
*
*/
/*ARGSUSED*/
int
_amaddprimary(isfhandle, keydesc, errcode)
Bytearray *isfhandle;
struct keydesc *keydesc;
struct errcode *errcode;
{
Fcb *fcb = NULL;
Keydesc2 keydesc2;
int err;
_isam_entryhook();
/*
* Check if 1 UNIX file decriptor is available.
*/
checkavailfd();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
/*
* Check that the limit on the numbrer of keys is not exceeded.
*/
if (fcb->nkeys >= MAXNKEYS) {
_amseterrcode(errcode, ETOOMANY);
goto ERROR;
}
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r(fcb);
/*
* Check key descriptor for validity.
*/
if (_validate_keydesc(keydesc, fcb->minreclen) != ISOK) {
_amseterrcode(errcode, EBADKEY);
goto ERROR;
}
/*
* Convert key descriptor to internal form.
*/
_iskey_xtoi (&keydesc2, keydesc);
/* Check if key already exists. */
if (_isfcb_findkey(fcb ,&keydesc2) != (Keydesc2 *) 0) {
_amseterrcode(errcode, EKEXISTS);
goto ERROR;
}
/*
* Check that primary key does not already exist.
*/
if (!FCB_NOPRIMARY_KEY(fcb)) {
_amseterrcode(errcode, EKEXISTS);
goto ERROR;
}
/*
* Open (or even create) .ind file if that is not open (created) yet.
*/
if (_open2_indfile(fcb) != ISOK) {
_amseterrcode(errcode, EACCES);
goto ERROR;
}
/*
* Create index structure.
*/
if ((err = _create_index(fcb ,&keydesc2)) != ISOK) {
_amseterrcode(errcode, err);
goto ERROR;
}
/*
* Add key descriptor to FCB.
*/
if (_isfcb_primkeyadd(fcb, &keydesc2) == ISERROR) {
_amseterrcode(errcode, ETOOMANY);
goto ERROR;
}
_amseterrcode(errcode, ISOK);
_issignals_mask();
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
/*
* Update CNTL Page from the FCB.
*/
(void)_isfcb_cntlpg_w(fcb);
_issignals_unmask();
_isam_exithook();
return (ISOK);
ERROR:
_isdisk_rollback();
_isdisk_inval();
/*
* Restore FCB from CNTL page.
*/
if (fcb) (void)_isfcb_cntlpg_r(fcb);
_isam_exithook();
return (ISERROR);
}
/*
* _create_index()
*
* Read data file, extract key from record, sort keys, create index.
* Check unique constraint, create duplicate serial numbers.
*/
int _create_index(fcb, pkeydesc2)
Fcb *fcb;
Keydesc2 *pkeydesc2;
{
Issort *srt;
int keylength = pkeydesc2->k2_len;
/*
* Set comparison function for sorting.
*
* nparts + 1 is used to compare keys that allow duplicates.
* The (nparts + 1) comparison will never be reached on ISNODUPS key.
*/
_iskeycmp_set(pkeydesc2, pkeydesc2->k2_nparts+1);
/*
* Handle empty file as a special case, to avoid nasty behavior
* in buildbtree() arithmetics.
*/
if (fcb->nrecords == 0L) {
pkeydesc2->k2_rootnode = _buildbtree(fcb, pkeydesc2, (Issort *) NULL);
return (ISOK);
}
/*
* Create a sorter for this key descriptor.
*/
srt = _issort_create(keylength, (int)fcb->nrecords, _iskeycmp);
/*
* Read sequentially all records, extract keys, and
* insert the keys into the sorter.
*/
_readallrecords(fcb, srt, pkeydesc2);
_issort_sort(srt); /* Sort the keys */
/*
* Check for potential duplicates if the index is ISNODUPS.
*/
if (!ALLOWS_DUPS2(pkeydesc2)) {
if (_duplicate_exist(srt, keylength)) {
_issort_destroy(srt);
return (EDUPL);
}
}
/*
* Attach duplicate serial numbers to the keys that are ISDUPS.
*/
if (ALLOWS_DUPS2(pkeydesc2)) {
_attach_dups_serial(srt, pkeydesc2);
}
/*
* Allocate and build the B-tree
*/
pkeydesc2->k2_rootnode = _buildbtree(fcb, pkeydesc2, srt);
_issort_destroy(srt); /* Destroy sorter */
return (ISOK);
}
/*
* _readallrecords()
*
* REad all records, extract keys, and insert them into sorter.
*/
Static void
_readallrecords(fcb, srt, pkeydesc2)
Fcb *fcb;
Issort *srt;
Keydesc2 *pkeydesc2;
{
char record [ISMAXRECLEN];
char keybuf [MAXKEYSIZE];
Recno recnum;
int reclen = 0;
int (*rec_read)() = (fcb->varflag?_vlrec_read:_flrec_read);
for (recnum = 1; recnum <= fcb->lastrecno; recnum++) {
if (rec_read(fcb, record, recnum, &reclen) != ISOK)
continue; /* Skip deleted record */
/*
* Zero out the entire key buffer to allow for using
* memcmp() as comparison function to compare whole keys.
*/
memset(keybuf, 0, pkeydesc2->k2_len);
/*
* Extract key parts from record buffer.
*/
_iskey_extract(pkeydesc2, record, keybuf);
/*
* Add recno to key
*/
strecno(recnum, keybuf + KEY_RECNO_OFF);
_issort_insert(srt, keybuf); /* Insert key into sorter */
}
}
/*
* _attach_dups_serial()
*
* Attach serial numbers to duplicate keys
*/
Static void
_attach_dups_serial(srt, pkeydesc2)
Issort *srt;
Keydesc2 *pkeydesc2;
{
int netkeylength = pkeydesc2->k2_len - RECNOSIZE - DUPIDSIZE;
char *curkey;
char *lastkey = NULL;
int dup_serial = 1;
_issort_rewind(srt);
while (curkey = _issort_read(srt)) {
if (lastkey && memcmp(lastkey + RECNOSIZE + DUPIDSIZE,
curkey + RECNOSIZE + DUPIDSIZE,
netkeylength) == 0)
dup_serial++;
else
dup_serial = 1;
/*
* Store serial number in the key.
*/
stdupser(dup_serial, curkey + KEY_DUPS_OFF);
lastkey = curkey;
}
}
/*
* _buildbtree()
*
* Create B-tree.
*/
Static Blkno
_buildbtree(fcb, pkeydesc2, srt)
Fcb *fcb;
Keydesc2 *pkeydesc2;
Issort *srt;
{
Bufhdr *_allockpage();
int depth;
int nrecords = fcb->nrecords;
int keyspernode[ISMAXBTRLEVEL];
int one_more[ISMAXBTRLEVEL];
char *nodebuf[ISMAXBTRLEVEL];
Bufhdr *nodebufhd[ISMAXBTRLEVEL];
Blkno pageblkno[ISMAXBTRLEVEL];
int curindex[ISMAXBTRLEVEL];
char *keyp;
int keylength = pkeydesc2->k2_len;
int leafcapac = getkeysperleaf(keylength);
int nleafcapac = getkeyspernode(keylength);
int perleaf;
int blocks_in_this_level, blocks_in_prev_level;
int slack = ISLEAFSLACK;
int i;
/*
* Handle an empty B-tree as a special case.
*/
if (fcb->nrecords == 0) {
(void)_allockpage(fcb, leafcapac, 0, pageblkno + 0);
return (pageblkno[0]);
}
/*
* COMPRESS changes the fill factor to 100%
*/
if ((pkeydesc2->k2_flags & COMPRESS) == COMPRESS)
slack = 0;
/*
* Figure out fill factors for each level.
*/
perleaf = ((double)leafcapac * (100.0 - (double) slack)) / 100.0;
/*
* Make it more robust.
*/
if (perleaf >= leafcapac)
perleaf = leafcapac;
if (perleaf < leafcapac/2 + 1)
perleaf = leafcapac/2 + 1;
/*
* Iterativelly determince values in keyspernode[] and one_mode[]
*/
blocks_in_this_level = nrecords / perleaf;
if (blocks_in_this_level * leafcapac < nrecords)
blocks_in_this_level++;
keyspernode[0] = nrecords / blocks_in_this_level;
one_more[0] = nrecords % blocks_in_this_level;
for (depth = 1; blocks_in_this_level > 1; depth++) {
blocks_in_prev_level = blocks_in_this_level;
blocks_in_this_level = (blocks_in_prev_level-1) / nleafcapac + 1;
keyspernode[depth] = blocks_in_prev_level / blocks_in_this_level;
one_more[depth] = blocks_in_prev_level % blocks_in_this_level;
}
if (depth >= ISMAXBTRLEVEL)
_isfatal_error("Too many levels in B-tree");
/*
* Make sure that we start reading keys from the beginning.
*/
_issort_rewind(srt);
/*
* Boot the Main loop.
*/
for (i = 0; i < depth ; i++) {
curindex[i] = ISPAGESIZE; /* Any big number will do */
one_more[i]++;
nodebufhd[i] = NULL;
}
/*
* Main loop.
*/
while ((keyp = _issort_read(srt)) != (char *) NULL) {
if (curindex[0] >= keyspernode[0] + (one_more[0] > 0)) {
/*
* Commit all changed buffers here to avoid buffer pool overflow.
*/
if (nodebufhd[0]) {
_isdisk_commit1(nodebufhd[0]);
_isdisk_sync();
}
/* Allocate new leaf. */
nodebufhd[0] = _allockpage(fcb, leafcapac, 0, pageblkno+0);
nodebuf[0] = nodebufhd[0]->isb_buffer;
one_more[0]--;
curindex[0] = 0;
}
/* Copy key into the page. */
memcpy( nodebuf[0] + BT_KEYS_OFF + keylength * curindex[0],keyp,
keylength);
stshort((short) curindex[0] + 1, nodebuf[0] + BT_NKEYS_OFF);
if (curindex[0]++ == 0) { /* Store first key in */
/* higher levels */
for (i = 1;i < depth; i++) {
if (curindex[i] >= keyspernode[i] + (one_more[i] > 0)) {
/* Unfix buffer. */
if (nodebufhd[i])
_isdisk_commit1(nodebufhd[i]);
nodebufhd[i] = _allockpage(fcb, nleafcapac, i, pageblkno+i);
nodebuf[i] = nodebufhd[i]->isb_buffer;
one_more[i]--;
curindex[i] = 0;
}
/* Copy key into page. */
memcpy( nodebuf[i] + BT_KEYS_OFF + keylength * curindex[i],keyp,
keylength);
/* Store pointer to level below. */
stblkno(pageblkno[i-1], nodebuf[i] + ISPAGESIZE -
(curindex[i]+1) * BLKNOSIZE);
stshort((short) curindex[i] + 1, nodebuf[i] + BT_NKEYS_OFF);
if (curindex[i]++ > 0) {
break;
}
}
}
}
return (pageblkno [depth - 1]); /* Return blkno of B-tree root */
}
/*
* _duplicate_exist()
*
* Return 1 if there are duplicates in the sorted key object.
*/
Static int _duplicate_exist(srt, keylength)
Issort *srt;
int keylength;
{
char *curkey;
char *lastkey = (char *) 0;
int netkeylength = keylength - RECNOSIZE;
_issort_rewind(srt);
while (curkey = _issort_read(srt)) {
if (lastkey && memcmp(lastkey + RECNOSIZE, curkey + RECNOSIZE,
netkeylength) == 0)
return 1; /* Duplicate key found */
lastkey = curkey;
}
return 0; /* No duplicates found */
}
Static
checkavailfd()
{
Fcb *fcb;
Bytearray *isfhandle2;
/*
* Check that there are UNIX file descriptors available.
*/
while (_watchfd_check() < 1) {
/*
* Find victim (LRU FCB) and close it.
*/
if((isfhandle2 = _mngfcb_victim()) == NULL)
_isfatal_error ("_openfcb() cannot find LRU victim");
fcb = _mngfcb_find(isfhandle2);
(void) _watchfd_decr(_isfcb_nfds(fcb));
_isfcb_close(fcb);
_mngfcb_delete(isfhandle2);
}
}

View File

@@ -0,0 +1,11 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isamdelcurr.c /main/3 1995/10/23 11:34:21 rswiston $ */
/*
* This file is obsolete and should be removed when convenient.
* The only function that was here (_amdelcurr) was moved into
* isdelcurr.c where the only reference to it existed, and the
* function was made static.
*/

View File

@@ -0,0 +1,138 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isamdelrec.c /main/3 1995/10/23 11:34:30 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isamdelrec.c 1.6 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isamdelrec.c
*
* Description: _amdelrec()
* Delete record from ISAM file.
*
*
*/
#include "isam_impl.h"
void _delkeys();
/*
* _amdelrec(isfhandle, recnum, errcode)
*
* _amdelrec() deletes a record from ISAM file.
*
* Input params:
* isfhandle Handle of ISAM file
* recnum record number of the record to be deleted
*
* Output params:
* errcode error status of the operation
*
*/
int
_amdelrec(isfhandle, recnum, errcode)
Bytearray *isfhandle;
Recno recnum;
struct errcode *errcode;
{
Fcb *fcb = NULL;
char recbuf[ISMAXRECLEN];
int reclen;
int (*rec_read)();
int (*rec_delete)();
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
rec_delete = (fcb->varflag?_vlrec_delete:_flrec_delete);
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r2(fcb);
/*
* We must read the record first to be able to delete keys.
*/
if (rec_read(fcb, recbuf, recnum, &reclen) != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
if (rec_delete(fcb, recnum) != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
fcb->nrecords--;
/*
* Delete associated entries from all indexes.
*/
_delkeys(fcb, recbuf, recnum);
_amseterrcode(errcode, ISOK);
_issignals_mask();
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
/*
* Update CNTL Page from the FCB.
*/
(void)_isfcb_cntlpg_w2(fcb);
_issignals_unmask();
_isam_exithook();
return (ISOK);
ERROR:
_isdisk_rollback();
_isdisk_inval();
/*
* Restore FCB from CNTL page.
*/
if (fcb) (void)_isfcb_cntlpg_r2(fcb);
_isam_exithook();
return (ISERROR);
}
/*
* _isdelkeys()
*
* Delete key entry from all indexes.
*/
void
_delkeys(fcb, record, recnum)
register Fcb *fcb;
char *record;
Recno recnum;
{
int nkeys = fcb->nkeys;
register int i;
for (i = 0; i < nkeys; i++) {
_del1key(fcb, fcb->keys + i, record, recnum);
}
}

View File

@@ -0,0 +1,90 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isamerror.c /main/3 1995/10/23 11:34:39 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isamerror.c 1.4 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isamerror.c
*
* Description:
* Error handling functions for the Access Method layer.
*
*
*/
#include "isam_impl.h"
#define ESENTINEL -100 /* Must not be a valid errno */
static struct errstattab {
int iserrno;
char isstat1;
char isstat2;
} errstattab[] = {
{ ISOK, '0', '0'},
{ ENOREC, '2', '3'},
{ ENOCURR, '2', '1'},
{ EENDFILE, '1', '0'},
{ EDUPL, '2', '2'},
{ ENOTOPEN, '9', '0'},
{ EBADARG, '9', '0'},
{ EBADKEY, '9', '0'},
{ ETOOMANY, '9', '0'},
{ EBADFILE, '9', '0'},
{ ENOTEXCL, '9', '0'},
{ ELOCKED, '9', '0'},
{ EKEXISTS, '9', '0'},
{ EPRIMKEY, '9', '0'},
{ EFLOCKED, '9', '0'},
{ EFNAME, '9', '0'},
{ EFATAL, '9', '0'},
/* Unix errors */
{ ENOENT, '9', '0'},
{ EACCES, '9', '0'},
{ EEXIST, '9', '0'},
{ ENOSPC, '9', '0'},
/* search sentinel */
{ ESENTINEL, '9', '0'}
};
/*
* _amseterrcode(errcode, is_errno, is_stat1, is_stat2, is_stat3, is_stat4)
*
* Set errcode block with ISAM error codes.
*/
void
_amseterrcode(errcode, is_errno)
struct errcode *errcode;
int is_errno;
{
register struct errstattab *p;
errcode->iserrno = is_errno;
/*
* Search errstattab to get appropriate isstat[12] values.
*/
for (p = errstattab; p->iserrno != ESENTINEL; p++) {
if (p->iserrno == is_errno) {
errcode->isstat[0] = p->isstat1;
errcode->isstat[1] = p->isstat2;
break;
}
}
if (is_errno == 0 && isdupl == 1)
errcode->isstat[1] = '2'; /* Indicate allowed duplicates */
}

View File

@@ -0,0 +1,46 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isamhooks.c /main/3 1995/10/23 11:34:48 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isamhooks.c 1.7 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isamhooks.c
*
* Description:
* Entry and exit hooks that are called upon every entry (and exit)
* to any Access Module Function.
*
*
*/
#include "isam_impl.h"
extern struct dlink *pavail;
/*
* _isam_entryhook()
*
*/
void
_isam_entryhook()
{
isdupl = 0; /* Reset duplicate indicator */
_setiserrno2(0, '0', '0');
}
/*
* _isam_exithook()
*
*/
void
_isam_exithook()
{
_isdisk_inval(); /* Invalidate all buffers */
}

View File

@@ -0,0 +1,300 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: isamopen.c /main/5 1998/04/10 08:03:57 mgreess $ */
#ifndef lint
static char sccsid[] = "@(#)isamopen.c 1.10 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isamopen.c
*
* Description: _amopen()
* Open an ISAM file.
*
*
*/
#include <stdlib.h>
#include "isam_impl.h"
/*
* _amopen(isfname, varflag, minlen, maxlen, primkey,
* isfhandle, curpos, errcode)
*
* _amopen() opens an ISAM file.
*
* Input params:
* isfname ISAM file name
*
* Output params:
* isfhandle a file handle to be used in subsequent operations on the file
* varflag TRUE if file is for variable length records
* minlen, maxlen minimum and maximum record length
* curpos initial current record position
* errcode {iserrno, isstat1-4}
*
* _amopen() returns 0 if successful, or -1 to indicate an error.
*/
/* ARGSUSED */
int
_amopen(isfname, openmode, varflag, minlen, maxlen,
isfhandle, curpos, errcode)
char *isfname;
enum openmode openmode;
Bool *varflag;
int *minlen, *maxlen;
Bytearray *isfhandle;
Bytearray *curpos;
struct errcode *errcode;
{
Fcb *fcb;
Bytearray isfhandle0;
Crp *crp;
int err;
_isam_entryhook();
/*
* Make isfhandle0.
*/
isfhandle0 = _makeisfhandle(isfname);
/*
* Invalidate the FCB cache entry to avoid a problem found when using
* multiple servers.
*/
if ((fcb = _mngfcb_find(&isfhandle0)) != NULL) {
(void) _watchfd_decr(_isfcb_nfds(fcb));
_isfcb_close(fcb);
_mngfcb_delete(&isfhandle0);
}
/*
* Get the FCB that corresponds to the isfhandle handle.
*/
if ((fcb = _openfcb(&isfhandle0, errcode)) == NULL) {
goto ERROR;
}
/*
* Check if the FCB allows writes if INOUT or OUTPUT is needed.
*/
if (fcb->rdonly==TRUE && (openmode==OM_INOUT || openmode==OM_OUTPUT)) {
_amseterrcode(errcode, EACCES);
goto ERROR;
}
/*
* Fill output parameters.
*/
*minlen = fcb->minreclen;
*maxlen = fcb->maxreclen;
*varflag = fcb->varflag;
*isfhandle = isfhandle0;
/*
* Initial current record position.
*/
if (FCB_NOPRIMARY_KEY(fcb)) {
/* Use physical order. */
crp = (Crp *) _ismalloc(sizeof(*crp));
memset ((char *) crp, 0, sizeof(*crp));
crp->keyid = PHYS_ORDER;
crp->flag = CRP_BEFOREANY;
curpos->length = sizeof(*crp);
curpos->data = (char *) crp;
}
else {
/*
* Use primary key order.
*/
crp = (Crp *) _ismalloc((unsigned)(sizeof(*crp) + fcb->keys[0].k2_len));
memset((char *) crp, 0, (sizeof(*crp) + fcb->keys[0].k2_len));
crp->keyid = fcb->keys[0].k2_keyid;
crp->flag = CRP_BEFOREANY;
_iskey_fillmin(&fcb->keys[0], crp->key);
curpos->length = sizeof(*crp) + fcb->keys[0].k2_len;
curpos->data = (char *) crp;
/*
* Set full key length as the number of bytes to match in key comparison
*/
crp->matchkeylen = fcb->keys[0].k2_len - RECNOSIZE;
if (ALLOWS_DUPS2(&fcb->keys[0]))
crp->matchkeylen -= DUPIDSIZE;
}
_isam_exithook();
return (ISOK);
ERROR:
_bytearr_free(&isfhandle0);
_isam_exithook();
return (ISERROR);
}
/*
* fcb = _openfcb(isfhandle, errcode)
*
* Try to locate FCB in the FCB cache. If not found, open the FCB and
* insert it into the cache.
*
* Return a pointer to the FCB, or NULL in the case of any error.
*/
#define FDNEEDED 3 /* Needs 3 UNIX fd to open a file*/
Fcb *
_openfcb(isfhandle, errcode)
Bytearray *isfhandle;
struct errcode *errcode;
{
Fcb *fcb;
Bytearray *isfhandle2;
char errbuf[BUFSIZ];
char *errmsg0;
if ((fcb = _mngfcb_find(isfhandle)) != NULL)
goto out;
/*
* Check that there are UNIX file descriptors available.
*/
while (_watchfd_check() < FDNEEDED) {
/*
* Find victim (LRU FCB) and close it.
*/
if((isfhandle2 = _mngfcb_victim()) == NULL)
_isfatal_error ("_openfcb() cannot find LRU victim");
fcb = _mngfcb_find(isfhandle2);
(void) _watchfd_decr(_isfcb_nfds(fcb));
_isfcb_close(fcb);
_mngfcb_delete(isfhandle2);
}
/*
* Open files, create FCB block.
*/
if ((fcb = _isfcb_open(_getisfname(isfhandle), errcode)) == NULL) {
return (NULL);
}
/*
* Check that ISAM file is not corrupted (only check magic number).
*/
if (_check_isam_magic(fcb) != ISOK) {
_amseterrcode(errcode, EBADFILE);
_isfcb_close(fcb);
return (NULL);
}
/*
* Read information from CNTL PAGE and store it in the FCB.
*/
if (_isfcb_cntlpg_r(fcb) == ISERROR)
_isfatal_error("_openfcb() cannot read CNTL PAGE");
/*
* Register UNIX file descriptors consumed.
*/
(void) _watchfd_incr(_isfcb_nfds(fcb));
/*
* Insert new entry into the FCB cache.
*/
_mngfcb_insert(fcb, isfhandle);
out:
/*
* Check that all file descriptors are open. This is needed to handle
* user errors such as removing .ind or .var files.
*/
if (fcb->varflag==TRUE && fcb->varfd == -1) {
char *fmt = "%s.var has been removed";
if (strlen(fmt) + strlen(fcb->isfname) + 1 >= BUFSIZ)
errmsg0 = (char*) malloc(strlen(fmt) + strlen(fcb->isfname) + 1);
else
errmsg0 = errbuf;
(void)sprintf(errmsg0, fmt, fcb->isfname);
_isam_warning(errmsg0);
_amseterrcode(errcode, EBADFILE);
if (errmsg0 != errbuf) free(errmsg0);
goto err;
}
if ((fcb->nkeys > 1 || !FCB_NOPRIMARY_KEY(fcb)) && fcb->indfd == -1) {
char *fmt = "%s.ind has been removed";
if (strlen(fmt) + strlen(fcb->isfname) + 1 >= BUFSIZ)
errmsg0 = (char*) malloc(strlen(fmt) + strlen(fcb->isfname) + 1);
else
errmsg0 = errbuf;
(void)sprintf(errmsg0, fmt, fcb->isfname);
_isam_warning(errmsg0);
_amseterrcode(errcode, EBADFILE);
if (errmsg0 != errbuf) free(errmsg0);
goto err;
}
return (fcb);
err:
/*
* Delete FCB and remove it from FCB cache. Close UNIX fds.
*
* This is needed to recover netisamd server if users remove .ind or
* or .var files.
*/
(void) _watchfd_decr(_isfcb_nfds(fcb));
_isfcb_close(fcb);
_mngfcb_delete(isfhandle);
return (NULL);
}
/*
* isfname = _getisfname(isfhandle)
*
* Get ISAM file name from ISAM file handle.
*/
char *
_getisfname(isfhandle)
Bytearray *isfhandle;
{
return (isfhandle->data);
}
/*
* isfhandle = _makeisfhandle(isfname)
*
* Make ISAM file handle.
*/
Bytearray
_makeisfhandle(isfname)
char *isfname;
{
return (_bytearr_new((u_short)(strlen(isfname) + 1), isfname));
}

View File

@@ -0,0 +1,191 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isamwrite.c /main/3 1995/10/23 11:35:14 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isamwrite.c 1.6 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isamwrite.c
*
* Description: _amwrite()
* Write record to ISAM file.
*
*
*/
#include "isam_impl.h"
static int _addkeys2 ();
extern long *ismaxlong;
/*
* _amwrite(isfhandle, record, reclen, curpos,
* recnum, errcode)
*
* _amwrite() writes a new record to ISAM file.
*
* Input params:
* isfhandle Handle of ISAM file
* record record
* reclen length of the record
* curpos current record position
*
* Output params:
* curpos new current position
* recnum record number
* errcode error status of the operation
*
*/
int
_amwrite(isfhandle, record, reclen, curpos, recnum, errcode)
Bytearray *isfhandle;
char *record;
int reclen;
Bytearray *curpos;
Recno *recnum;
struct errcode *errcode;
{
Fcb *fcb = NULL;
Recno recnum2;
Crp *crp;
int err;
int (*rec_write)();
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
rec_write = (fcb->varflag?_vlrec_write:_flrec_write);
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r2(fcb);
if (rec_write(fcb, record, &recnum2, reclen) == ISERROR) {
_isfatal_error("_amwrite() cannot write record");
}
/*
* Update all keys.
*/
if ((err = _addkeys2(fcb, record, recnum2, curpos)) != ISOK) {
_amseterrcode(errcode, err);
goto ERROR;
}
fcb->nrecords++;
*recnum = recnum2;
_amseterrcode(errcode, ISOK);
_issignals_mask();
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
/*
* Return new current record position.
*/
crp = (Crp *) curpos->data;
crp->flag = CRP_ON;
crp->recno = recnum2;
/*
* Update CNTL Page from the FCB.
*/
(void)_isfcb_cntlpg_w2(fcb);
_issignals_unmask();
_isam_exithook();
return (ISOK);
ERROR:
_isdisk_rollback();
_isdisk_inval();
/*
* If error is not EDUPL position undefined.
*/
if (errcode->iserrno != EDUPL) {
((Crp *)curpos->data)->flag = CRP_UNDEF;
}
/*
* Restore FCB from CNTL page.
*/
if (fcb) (void)_isfcb_cntlpg_r2(fcb);
_isam_exithook();
return (ISERROR);
}
/*
* _addkeys()
*
* Insert key entry to all indexes.
*
* Returns ISOK, or EDUPS.
*/
int _addkeys (fcb, record, recnum)
register Fcb *fcb;
char *record;
Recno recnum;
{
int nkeys = fcb->nkeys;
register int i;
int err;
for (i = 0; i < nkeys; i++) {
if ((err = _add1key(fcb, fcb->keys + i, record, recnum,
(char*)NULL)) != ISOK)
return (err);
}
return (ISOK);
}
Static int
_addkeys2 (fcb, record, recnum, curpos)
Fcb *fcb;
char *record;
Recno recnum;
Bytearray *curpos;
{
int nkeys = fcb->nkeys;
register int i;
int err;
Crp *crp;
int keyid;
Keydesc2 *keydesc2;
crp = (Crp *)curpos->data;
keyid = crp->keyid;
for (i = 0; i < nkeys; i++) {
keydesc2 = fcb->keys + i;
if ((err =_add1key(fcb, keydesc2, record, recnum,
(keydesc2->k2_keyid == keyid) ?
crp->key : (char *) NULL)) != ISOK)
return (err);
}
return (ISOK);
}

View File

@@ -0,0 +1,80 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isapplmr.c /main/3 1995/10/23 11:35:25 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isapplmr.c 1.5 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isapplmr.c
*
* Description:
* Read Application magic string
*/
#include "isam_impl.h"
#include <sys/file.h>
#include <sys/time.h>
#include "isam_impl.h"
/*
* string = isapplmr(isfd)
*
* Isapplmr() returns the aplication magic string written to the ISAM file
* by isapplmw() function. No magic string is returned as "". The value
* of -1 returned indicates an error (iserrno is set).
*
*/
int
_isapplmr(isfd, buffer)
int isfd;
char *buffer;
{
register Fab *fab;
Fcb *fcb = NULL;
char cntl_page[CP_NKEYS_OFF];
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISINPUT, or ISINOUT.
*/
if (fab->openmode != OM_INPUT && fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(&fab->isfhandle, &fab->errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
_isseekpg(fcb->datfd, ISCNTLPGOFF);
(void)read(fcb->datfd, cntl_page, sizeof(cntl_page));
strncpy(buffer, cntl_page + CP_APPLMAGIC_OFF, CP_APPLMAGIC_LEN);
_amseterrcode(&fab->errcode, ISOK);
_isam_exithook();
_seterr_errcode(&fab->errcode);
return (ISOK); /* Successful write */
}

View File

@@ -0,0 +1,93 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isapplmw.c /main/3 1995/10/23 11:35:35 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isapplmw.c 1.5 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isapplmw.c
*
* Description:
* Write Application magic string
*/
#include "isam_impl.h"
#include <sys/file.h>
#include <sys/time.h>
/*
* string = isapplmw(isfd)
*
* Isapplmw() writes an application specific 'magic string' into ISAM
* file. The 'file' program (using /etc/magic) may be used to report
* this magic string.
*
*/
int
_isapplmw(isfd, magicstring)
int isfd;
char *magicstring;
{
register Fab *fab;
int ret;
Fcb *fcb;
char cntl_page[CP_NKEYS_OFF];
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISOUTPUT, or ISINOUT.
*/
if (fab->openmode != OM_OUTPUT && fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check the length of the magic string
*/
if ((int)strlen(magicstring) > CP_APPLMAGIC_LEN) {
_setiserrno2(EBADARG, '9', '0');
return (ISERROR);
}
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(&fab->isfhandle, &fab->errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
/* Write the new data */
_isseekpg(fcb->datfd, ISCNTLPGOFF);
(void)read(fcb->datfd, cntl_page, sizeof(cntl_page));
strncpy(cntl_page + CP_APPLMAGIC_OFF, magicstring, CP_APPLMAGIC_LEN);
_isseekpg(fcb->datfd, ISCNTLPGOFF);
(void)write(fcb->datfd, cntl_page, sizeof(cntl_page));
_amseterrcode(&fab->errcode, ISOK);
_isam_exithook();
ret = ISOK;
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}

View File

@@ -0,0 +1,62 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isbsearch.c /main/3 1995/10/23 11:35:44 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isbsearch.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isbsearch.c
*
* Description:
* Binary search function.
* If differs from bsearch(3) in that if an exact match is not found,
* the next lower key is returned. If key is lower than any key in table,
* NULL value is returned.
*
*/
char *_isbsearch (key,table,nelems,keylen,cmpf)
char *key;
char *table;
int nelems;
int keylen;
int (*cmpf) ();
{
register int len,l1,result; /* current length of array to search */
register char *p,*low;
if (nelems <= 0) return (char *) 0;
/* Check if key is lower than any key in the table. */
result = (*cmpf) (key,table);
if (result < 0 ) return (char *) 0; /* Key is lower */
else if (result == 0) return table; /* Exact match */
for (low = table,len = nelems; len > 0;) {
l1 = len >> 1;
p = low + keylen * l1;
if ((result = (*cmpf) (key,p)) == 0) /* Exact match found */
return p;
if (result > 0 ) { /* Key is in higher half */
len -= l1 + 1;
low = p + keylen;
}
else { /* Key is in lower half */
len = l1 ;
}
}
/* No matching key found, return next lower key */
return (result>0)?p:(p-keylen);
}

View File

@@ -0,0 +1,194 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isbtree.c /main/3 1995/10/23 11:35:52 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isbtree.c 1.4 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isbtree.c
*
* Description:
* B-tree operations: SEARCH
*
*/
#include "isam_impl.h"
extern int _iskeycmp();
/*
* _isbtree_create()
*
* Create a B-tree path object that will used in subsequent operations.
*/
Btree *
_isbtree_create(fcb, pkeydesc2)
Fcb *fcb;
Keydesc2 *pkeydesc2;
{
register Btree *p;
p = (Btree *) _ismalloc(sizeof(*p));
memset((char *)p, 0, sizeof(*p));
p->fcb = fcb;
p->keydesc2 = pkeydesc2;
return (p);
}
/*
* _isbtr_destroy()
*
* Destroy B-tree path object
*/
void
_isbtree_destroy(btree)
register Btree *btree;
{
register int i;
for (i = 0; i < btree->depth;i++) {
_isdisk_unfix(btree->bufhdr[i]);
}
free((char *)btree);
}
/*
* _isbtree_search()
*
* Descend the B-tree, position pointer on or before the matched key.
*/
void
_isbtree_search(btree, key)
register Btree *btree;
char *key; /* Search for this key */
{
Keydesc2 *pkeydesc2 = btree->keydesc2;
Blkno rootblkno = pkeydesc2->k2_rootnode;
int keylength = pkeydesc2->k2_len;
int index; /* Index to tables in btree */
/* Has value of 1, next 2, etc. */
int elevation; /* Level - leaves have value 0 */
register char *p; /* Pointer to key page */
int nkeys; /* Number of keys in the page */
char *key2; /* Equal or next lower key */
int curpos; /* index of key2 in key page */
Blkno blkno;
/* Set comparison function. */
_iskeycmp_set(pkeydesc2, pkeydesc2->k2_nparts + 1); /* +1 for recno field */
index = 0;
blkno = rootblkno;
do {
btree->bufhdr[index] =
_isdisk_fix(btree->fcb, btree->fcb->indfd, blkno, ISFIXREAD);
p = btree->bufhdr[index]->isb_buffer; /* pointer to buffer */
/* Load some fields from the key page. */
nkeys = ldshort(p+BT_NKEYS_OFF); /* Number of keys in the page */
elevation = ldshort(p+BT_LEVEL_OFF); /* Level of the page */
/* Binary search in the key page to find equal or next lowere key. */
key2 = _isbsearch(key, p+BT_KEYS_OFF, nkeys, keylength, _iskeycmp);
curpos = (key2) ? ((key2 - p - BT_NKEYS_OFF) / keylength) : 0;
btree->curpos[index] =
(key2 == (char *)0 && elevation==0)? -1 : curpos;
if (elevation > 0)
blkno = ldblkno(p + ISPAGESIZE - (curpos + 1) * BLKNOSIZE);
index++;
} while (elevation > 0);
btree->depth = index;
}
/*
* _isbtree_current()
*
* Get pointer to the current key
*/
char *
_isbtree_current(btree)
register Btree *btree;
{
int curpos;
assert(btree->depth > 0);
if ((curpos = btree->curpos[btree->depth - 1]) == -1)
return (NULL);
else
return (btree->bufhdr[btree->depth - 1]->isb_buffer
+ BT_KEYS_OFF + curpos * btree->keydesc2->k2_len);
}
/*
* _isbtree_next()
*
* Get pointer to the next key
*/
char *
_isbtree_next(btree)
register Btree *btree;
{
int curpos;
int depth = btree->depth;
register char *p;
register int level;
Blkno blkno;
assert(depth > 0);
/*
* Move up along the path, find first block where we can move to the right.
*/
for (level = depth - 1; level >= 0; level--) {
p = btree->bufhdr[level]->isb_buffer;
if (btree->curpos[level] < ldshort(p + BT_NKEYS_OFF) - 1)
break;
}
if (level < 0) {
/* Logical end of the index file. No next record. */
return (NULL);
}
curpos = ++(btree->curpos[level]);
while (++level < depth) {
/* Get block number to block in next lower level. */
if (level > 0)
blkno = ldblkno(p + ISPAGESIZE - (curpos + 1) * BLKNOSIZE);
/* Unfix page in this level, fetch its right brother. */
_isdisk_unfix(btree->bufhdr[level]);
btree->bufhdr[level] =
_isdisk_fix(btree->fcb, btree->fcb->indfd, blkno, ISFIXREAD);
p = btree->bufhdr[level]->isb_buffer;
curpos = btree->curpos[level] = 0;
}
return (p + BT_KEYS_OFF + curpos * btree->keydesc2->k2_len);
}

View File

@@ -0,0 +1,275 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isbtree2.c /main/3 1995/10/23 11:36:02 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isbtree2.c 1.5 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isbtree2.c
*
* Description:
* B-tree operations: INSERT
*
*/
#include "isam_impl.h"
extern int _iskeycmp();
Static insert_key();
/* _isbtree_insert() - Insert entry into B-tree ----------------------------*/
void
_isbtree_insert(btree, key)
register Btree *btree;
char *key;
{
Keydesc2 *pkeydesc2 = btree->keydesc2;
int keylength = pkeydesc2->k2_len;
int nkeys; /* Number of keys in the page */
int capac;
char keybuf[MAXKEYSIZE];
register int i;
Blkno blkno;
char *pkp, *pkp2, *pkp3;
Bufhdr *kp2bhdr, *kp3bhdr;
Blkno blkno2, blkno3;
int level;
int halfcapac;
/*
* Set key comparison function.
*/
_iskeycmp_set(pkeydesc2, pkeydesc2->k2_nparts+1); /* +1 for recno field */
/*
* Initialize data structure before main loop.
*/
blkno = NULL_BLKNO;
memcpy( keybuf,key, keylength);
/*
* Main loop:
* Starting from the leaf, insert key after current search position.
* If necessary make block split and propage changes to upper levels.
* Root split is handled differently because we don't want to change
* root block number.
*/
for (i = btree->depth - 1; i >= 0; i--) {
/* We have to fix the block for update. */
btree->bufhdr[i] = _isdisk_refix(btree->bufhdr[i], ISFIXWRITE);
pkp = btree->bufhdr[i]->isb_buffer;
level = ldshort(pkp + BT_LEVEL_OFF);
capac = ldshort(pkp + BT_CAPAC_OFF); /* Block capacity */
nkeys = ldshort(pkp + BT_NKEYS_OFF); /* Number of keys in block */
assert(level + i + 1 == btree->depth);
assert(nkeys <= capac);
if (nkeys == capac) {
/*
* This block must be split.
* Allocate new block, move half of the entries into the new
* block, and insert the key into the appropriate
* block. If this block is not root, the loop will iterate
* to update upper levels.
*/
/* Get new page. */
kp2bhdr = _allockpage(btree->fcb, capac, level, &blkno2);
pkp2 = kp2bhdr->isb_buffer;
halfcapac = (nkeys+1) >> 1; /* Same as nkeys/2 + 1 */
splitblock(btree, pkp, pkp2, btree->curpos[i]);
if (btree->curpos[i] > halfcapac - 2) {
/* Insert entry into right block. */
insert_key(btree, pkp2, btree->curpos[i] - halfcapac, keybuf,
blkno);
}
else {
/* Insert entry into left block. */
insert_key(btree, pkp, btree->curpos[i], keybuf, blkno);
if (btree->curpos[i] == -1) /* Leftmost entry inserted - */
leftkey_up(btree, i); /* propagate to upper levels. */
}
/* Set variables for next loop iteration. */
memcpy( keybuf,pkp2 + BT_KEYS_OFF, keylength); /* Leftmost key */
blkno = blkno2;
/*
* Next loop iteration will insert entry pointing to
* new allocated page into next upper level.
*/
}
else {
/*
* Block split is not necessary. Simply insert key into
* the block. If the inserted key becomes the leftmost entry
* in the block, update upper levels.
*/
insert_key(btree, pkp, btree->curpos[i], keybuf, blkno);
if (btree->curpos[i] == -1 && i > 0)
leftkey_up(btree, i);
break; /* from main loop */
}
}
if (i < 0) {
/*
* Root was split.
* Allocate new page. However, to keep root block the same,
* the new page is used for the left son of root.
*
* pkp is the new root, pkp3 is the left son,
* and pkp3 is the right of the root.
*/
kp3bhdr = _allockpage(btree->fcb, capac, 1, &blkno3);
pkp3 = kp3bhdr->isb_buffer;
memcpy( pkp3,pkp, ISPAGESIZE);
stshort((short) getkeyspernode(keylength), pkp + BT_CAPAC_OFF);
stshort((short) 0, pkp + BT_NKEYS_OFF);
stshort((short)btree->depth, pkp + BT_LEVEL_OFF);
insert_key(btree, pkp, -1, pkp3 + BT_KEYS_OFF, blkno3);
insert_key(btree, pkp, 0 , keybuf, blkno);
}
}
/*--------- insert supporting local functions -------------------------------*/
/* leftkey_up() - Update upper levels with new leftmost entry -----------*/
leftkey_up(btree, level)
register Btree *btree;
int level;
{
int keylength = btree->keydesc2->k2_len;
char *pkp;
char *key;
pkp = btree->bufhdr[level]->isb_buffer;
key = pkp + BT_KEYS_OFF; /* Leftmost key */
while (--level >= 0) {
btree->bufhdr[level] = _isdisk_refix(btree->bufhdr[level], ISFIXWRITE);
pkp = btree->bufhdr[level]->isb_buffer;
memcpy( pkp + BT_KEYS_OFF + (btree->curpos[level] * keylength),key,
keylength);
if (btree->curpos[level] > 0)
break;
}
}
/* insert_key - Insert key into block ------------------------*/
Static insert_key(btree, pkp, pos, key, blkno)
register Btree *btree;
char *pkp;
int pos;
char *key;
Blkno blkno;
{
int keylength = btree->keydesc2->k2_len;
int nkeys = ldshort(pkp + BT_NKEYS_OFF);
int capac = ldshort(pkp + BT_CAPAC_OFF);
int level = ldshort(pkp + BT_LEVEL_OFF);
assert(nkeys < capac);
/* Shift nkeys - pos - 1 entries to the right. */
/* memmove() handle overlaps correctly */
memmove(pkp + BT_KEYS_OFF + (pos + 2) * keylength,
pkp + BT_KEYS_OFF + (pos + 1) * keylength,
(nkeys - pos - 1) * keylength);
/* Copy new key entry into the block. */
memcpy( pkp + BT_KEYS_OFF + (pos + 1) * keylength,key, keylength);
/* For non-leaf nodes, insert block number into table of down pointers. */
if (level > 0) {
memcpy(pkp + ISPAGESIZE - (nkeys + 1) * BLKNOSIZE,
pkp + ISPAGESIZE - nkeys * BLKNOSIZE,
(nkeys - pos - 1) * BLKNOSIZE);
stblkno(blkno, pkp + ISPAGESIZE - (pos + 2) * BLKNOSIZE);
}
stshort((short) (nkeys + 1), pkp + BT_NKEYS_OFF);
}
/* splitblock() - Split block into two -----------------------------*/
splitblock(btree, fullpage, newpage, pos)
register Btree *btree;
register char *fullpage, *newpage;
int pos;
{
int keylength = btree->keydesc2->k2_len;
int nkeys, capac, level;
int halfcapac;
int newpage_nkeys;
int fullpage_nkeys;
nkeys = ldshort(fullpage + BT_NKEYS_OFF);
capac = ldshort(fullpage + BT_NKEYS_OFF);
level = ldshort(fullpage + BT_LEVEL_OFF);
assert(nkeys == capac);
halfcapac = (capac + 1) >> 1; /* same as capac/2 + 1 */
if (pos > halfcapac - 2) {
/* New entry will go into right page(fullpage). */
fullpage_nkeys = halfcapac;
newpage_nkeys = halfcapac - 1;
}
else {
/* New entry will go into left page (newpage). */
fullpage_nkeys = halfcapac - 1;
newpage_nkeys = halfcapac;
}
/* Move newpage_nkeys keys into newpage. */
memcpy(newpage + BT_KEYS_OFF,
fullpage + BT_KEYS_OFF + fullpage_nkeys * keylength,
keylength * newpage_nkeys);
/* If non-leaf, move corresponding entries from block number table. */
if (level > 0) {
memcpy(newpage + ISPAGESIZE - newpage_nkeys * BLKNOSIZE,
fullpage + ISPAGESIZE - nkeys * BLKNOSIZE,
newpage_nkeys * BLKNOSIZE);
}
stshort((short) fullpage_nkeys, fullpage + BT_NKEYS_OFF);
stshort((short) newpage_nkeys, newpage + BT_NKEYS_OFF);
}

View File

@@ -0,0 +1,326 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isbtree3.c /main/3 1995/10/23 11:36:12 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isbtree3.c 1.5 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isbtree3.c
*
* Description:
* B-tree operations: REMOVE
*
*/
#include "isam_impl.h"
extern int _iskeycmp();
static remove_entry();
/* _isbtree_remove() - Remove entry from B-tree ----------------------------*/
void
_isbtree_remove(btree)
register Btree *btree;
{
struct keydesc2 *pkeydesc2 = btree->keydesc2;
int nkeys; /* Number of keys in the page */
register int i;
char *pkp, *pkp2, *pkp3;
struct bufhdr *kp2bhdr;
Blkno blkno2;
int level;
int capac, halfcapac;
int move_keys;
/* Set comparison function. */
_iskeycmp_set(pkeydesc2, pkeydesc2->k2_nparts+1); /* +1 for recno field */
/*
* Main loop.
* Remove he current entry from leaf.
* If it was leftmost entry, propagate new leftmost to upper levels.
* If block has less than capac/2 + 1 entries, either move some entries
* from next left or right block, or merge with next left or right
* block.
*/
for (i = btree->depth - 1; i >= 0; i--) {
/* Re-fix the current page for update. */
btree->bufhdr[i] = _isdisk_refix(btree->bufhdr[i], ISFIXWRITE);
pkp = btree->bufhdr[i]->isb_buffer;
level = ldshort(pkp + BT_LEVEL_OFF);
capac = ldshort(pkp + BT_CAPAC_OFF); /* Block capacity */
nkeys = ldshort(pkp + BT_NKEYS_OFF); /* Number of keys in block */
halfcapac = (capac+1) >> 1; /* same as capac/2 + 1 */
assert(level + i + 1 == btree->depth);
assert(i == 0 || nkeys >= halfcapac);
/* Remove entry from this page. */
remove_entry(btree, pkp, btree->curpos[i]);
nkeys--;
/* Must propagate new leftmost key up. */
if (btree->curpos[i] == 0 && i > 0)
leftkey_up(btree, i);
if (nkeys >= halfcapac || i == 0) {
/*
* Page is still balanced. No changes are necessary.
* Also, no chages are needed if this is root block.
*/
break;
}
else {
if(btree->curpos[i-1] > 0) {
/*
* Block pkp is not the leftmost descendent of its parent.
* Either merge with left brother, or move a few entries
* from it.
*/
pkp3 = btree->bufhdr[i-1]->isb_buffer;
blkno2 = ldblkno(pkp3 + ISPAGESIZE -
(btree->curpos[i-1]) * BLKNOSIZE);
/* Fix the left brother. */
kp2bhdr = _isdisk_fix(btree->fcb, btree->fcb->indfd,
blkno2, ISFIXWRITE);
pkp2 = kp2bhdr->isb_buffer;
if (ldshort(pkp2 + BT_NKEYS_OFF) + nkeys > capac) {
/*
* Current page cannot be merged with the left brother.
* Move some entries from the left brother into current.
*/
move_keys = (ldshort(pkp2 + BT_NKEYS_OFF) - halfcapac +1)/2;
assert(move_keys > 0);
move_from_left (btree, pkp2, pkp, move_keys);
leftkey_up(btree, i); /* Propagate new leftmost key */
break; /* From main loop */
}
else {
/*
* Current page and left brotehr will be merged.
* Move all entries from current into left, and free
* current.
*/
/* Move all entries from current into left. */
move_from_right(btree, pkp2, pkp, nkeys);
/* Free current page. */
_isindfreel_free(btree->fcb, btree->bufhdr[i]->isb_blkno);
btree->bufhdr[i] = kp2bhdr; /* Update search path */
/* The loop must iterate to delete entry in parent block. */
}
}
else {
/*
* Block pkp is the leftmost descendent of its parent.
* Either merge with right brother, or move a few entries
* from it.
*/
pkp3 = btree->bufhdr[i-1]->isb_buffer;
blkno2 = ldblkno(pkp3 + ISPAGESIZE -
(btree->curpos[i-1] + 2) * BLKNOSIZE);
/* Fix the right brother. */
kp2bhdr = _isdisk_fix(btree->fcb, btree->fcb->indfd,
blkno2, ISFIXWRITE);
pkp2 = kp2bhdr->isb_buffer;
if (ldshort(pkp2 + BT_NKEYS_OFF) + nkeys > capac) {
/*
* Current page cannot be merged with the right brother.
* Move some entries from the right brother into current.
*/
move_keys = (ldshort(pkp2 + BT_NKEYS_OFF) - halfcapac +1)/2;
assert(move_keys > 0);
move_from_right(btree, pkp, pkp2, move_keys);
/* Update search path to go through right brother. */
btree->curpos[i-1]++;
btree->bufhdr[i] = kp2bhdr;
btree->curpos[i] = 0;
leftkey_up(btree, i); /* Propagate new leftmost key */
break; /* From main loop */
}
else {
/*
* Current page and right brother will be merged.
* Move all entries from right into current, and free
* right.
*/
/* Move all entries from right brother into current. */
move_from_right(btree, pkp, pkp2, ldshort(pkp2 + BT_NKEYS_OFF));
/* Free right brother page. */
_isindfreel_free(btree->fcb, kp2bhdr->isb_blkno);
/* Update search path to point at right brother*/
btree->curpos[i-1]++;
/* The loop must iterate to delete entry in parent block. */
}
}
}
} /* end of main loop */
if (btree->depth > 1) {
pkp = btree->bufhdr[0]->isb_buffer;
if (ldshort(pkp + BT_NKEYS_OFF) < 2) {
/*
* Root now has only 1 entry and it is not the sole block.
* Replace root with its only descendant, don't change
* root blkno.
*/
pkp2 = btree->bufhdr[1]->isb_buffer;
memcpy( pkp,pkp2, ISPAGESIZE);
/* Free page. */
_isindfreel_free(btree->fcb, btree->bufhdr[1]->isb_blkno);
}
}
}
/*--------- remove supporting local functions -------------------------------*/
static remove_entry(btree, pkp, pos)
register Btree *btree;
char *pkp;
int pos;
{
int keylength = btree->keydesc2->k2_len;
int nkeys = ldshort(pkp + BT_NKEYS_OFF);
int level = ldshort(pkp + BT_LEVEL_OFF);
assert(nkeys > 0);
assert(pos >= 0 && pos < nkeys);
/* Shift nkeys - pos - 1 entries to the left. */
memcpy(pkp + BT_KEYS_OFF + pos * keylength,
pkp + BT_KEYS_OFF + (pos + 1) * keylength,
(nkeys - pos - 1) * keylength);
/* For non-leaf nodes, remove block number from table of down pointers. */
if (level > 0) {
memmove(pkp + ISPAGESIZE - (nkeys - 1) * BLKNOSIZE,
pkp + ISPAGESIZE - nkeys * BLKNOSIZE,
(nkeys - pos - 1) * BLKNOSIZE);
}
stshort((short) (nkeys - 1), pkp + BT_NKEYS_OFF);
}
move_from_right(btree, l, r, move_keys)
Btree *btree;
char *l, *r;
int move_keys;
{
int keylength = btree->keydesc2->k2_len;
int lnkeys = ldshort(l + BT_NKEYS_OFF);
int rnkeys = ldshort(r + BT_NKEYS_OFF);
int level = ldshort(r + BT_LEVEL_OFF);
/* Move move_keys from l into r block. */
memcpy( l + BT_KEYS_OFF + lnkeys * keylength,r + BT_KEYS_OFF,
move_keys * keylength);
/* Move remaining entries in r to the left side. */
memcpy( r + BT_KEYS_OFF,r + BT_KEYS_OFF + move_keys * keylength,
(rnkeys - move_keys) * keylength);
/* If non-leaf, move the pointers stored at the end of block. */
if (level > 0) {
memcpy(l + ISPAGESIZE - (lnkeys + move_keys) * BLKNOSIZE,
r + ISPAGESIZE - move_keys * BLKNOSIZE,
move_keys * BLKNOSIZE);
memmove(r + ISPAGESIZE - (rnkeys - move_keys) * BLKNOSIZE,
r + ISPAGESIZE - rnkeys * BLKNOSIZE,
(rnkeys - move_keys) * BLKNOSIZE);
}
lnkeys += move_keys;
rnkeys -= move_keys;
stshort((short) lnkeys, l + BT_NKEYS_OFF);
stshort((short) rnkeys, r + BT_NKEYS_OFF);
}
move_from_left(btree, l, r, move_keys)
Btree *btree;
char *l, *r;
int move_keys;
{
int keylength = btree->keydesc2->k2_len;
int lnkeys = ldshort(l + BT_NKEYS_OFF);
int rnkeys = ldshort(r + BT_NKEYS_OFF);
int level = ldshort(r + BT_LEVEL_OFF);
/* Move entries in r to the right side to create space for move_keys. */
memmove( r + BT_KEYS_OFF + move_keys * keylength,r + BT_KEYS_OFF,
rnkeys * keylength);
/* Move move_keys from l into r block. */
memcpy( r + BT_KEYS_OFF,l + BT_KEYS_OFF + (lnkeys - move_keys) * keylength,
move_keys * keylength);
/* If non-leaf, move the pointers stored at the end of block. */
if (level > 0) {
memcpy(r + ISPAGESIZE - (rnkeys + move_keys) * BLKNOSIZE,
r + ISPAGESIZE - rnkeys * BLKNOSIZE,
rnkeys * BLKNOSIZE);
memcpy(r + ISPAGESIZE - move_keys * BLKNOSIZE,
l + ISPAGESIZE - lnkeys * BLKNOSIZE,
move_keys * BLKNOSIZE);
}
lnkeys -= move_keys;
rnkeys += move_keys;
stshort((short) lnkeys, l + BT_NKEYS_OFF);
stshort((short) rnkeys, r + BT_NKEYS_OFF);
}

View File

@@ -0,0 +1,351 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isbuild.c /main/3 1995/10/23 11:36:21 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isbuild.c 1.12 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isbuild.c
*
* Description:
* Create an ISAM file.
*/
#include "isam_impl.h"
#include <netdb.h>
#include <sys/file.h>
#include <sys/time.h>
extern char _isam_version[];
static char *_version_ = _isam_version;
static int _ambuild();
/*
* isfd = isbuild(isfname, recordlength, primkey, mode)
*
* Isbuild() determines on which machine the ISAM file is to be built,
* checks the permissions for creating a file by this user running on
* this client machine by using the access(2) UNIX call.
* If the file is remote, it is created by the netisamd daemon running
* on the machine hosting the ISAM file. The chown(2) is then used to
* change the ownership of the file to the client.
* All UNIX files created will have their permissions set to 0666, allowing
* thus both read and write access to anybody.
*
* Isbuild() returns an ISAM file descriptor (isfd) is the call was successful,
* or a value of -1 if the call failed.
*
* Errors:
* EBADARG Improper mode parameter
* EBADARG isreclen >= recordlength and ISVARLEN specified
* E2BIG recordlength greater than system imposed limit (8196)
* EBADKEY Invalid key descriptor
* EBADFILE ISAM file is corrupted or it is not an NetISAM file
* EFNAME Invalid ISAM file name
* ETOOMANY Too many ISAM file descriptors are in use (128 is the limit)
*
* The following error numbers are "borrowed" from UNIX.
* EACCES UNIX file system protection denies creation of the file
* EEXIST - ISAM file already exists
* EEXIST - A UNIX file with the same name exists
*/
int
isbuild(isfname, recordlength, primkey, mode)
char *isfname;
int recordlength;
struct keydesc *primkey;
int mode;
{
Fab *fab;
Isfd isfd;
enum openmode openmode;
int minreclen; /* Minimum record length */
int origumask;
/* Get file open mode part of the mode parameter. */
if ((openmode = _getopenmode(mode)) == OM_BADMODE) {
_setiserrno2(EBADARG, '9', '0');
return (NOISFD);
}
/*
* Minimum record length.
*/
minreclen = ((mode & ISLENMODE) == ISVARLEN) ? isreclen : recordlength;
/* Check recordlength against system imposed limit. */
if (recordlength > ISMAXRECLEN) {
_setiserrno2(E2BIG, '9', '0');
return (NOISFD);
}
/* Check that ssminreclen >= ISMINRECLEN. */
if (minreclen < ISMINRECLEN) {
_setiserrno2(EBADARG, '9', '0');
return (NOISFD);
}
/* Check that minreclen <= recordlength */
if (minreclen > recordlength) {
_setiserrno2(EBADARG, '9', '0');
return (NOISFD);
}
/* Create a Fab object. */
fab = _fab_new(isfname,
openmode,
(Bool)((mode & ISLENMODE) == ISVARLEN),
minreclen,
recordlength);
if (fab == NULL) {
return (NOISFD); /* iserrno is set by fab_new */
}
/* Get an ISAM file descriptor for this fab */
if ((isfd = _isfd_insert(fab)) == NOISFD) {
/* Table of ISAM file descriptors would overflow. */
_fab_destroy(fab);
_setiserrno2(ETOOMANY, '9', '0');
return (NOISFD);
}
FAB_ISFDSET(fab, isfd);
/*
* Extract umask. It is send to the Acces Layer (which may reside
* on a remote machine).
*/
origumask = umask(0);
(void)umask(origumask);
/*
* Call lower layers.
*/
if (_ambuild(fab->isfname, fab->openmode, fab->varlength,
fab->minreclen, fab->maxreclen, primkey, getuid(),
getgid(), origumask, &fab->isfhandle, &fab->curpos,
&fab->errcode)) {
_seterr_errcode(&fab->errcode);
_fab_destroy(fab);
return (NOISFD);
}
return ((int)isfd); /* Successful isopen() */
}
/*
* _ambuild(isfname, openmode, varflag, minlen, maxlen,
* primkey, owner, group, umask, isfhandle, curpos, errcode)
*
* _ambuild() creates a new ISAM file with the name isfname.
*
* Input params:
* isfname ISAM file name
* varflag is 0/1 flag set to 1 if the file is for variable lengths records
* minlen minimum length of record in bytes
* maxlen maximum length of record in bytes
* primkey definition of the primary key
* owner, group set the ownership of the file to this user and group
* umask application's value of umask
*
* Output params:
* isfhandle a file handle to be used in subsequent operations on the file
* curpos initial current record position
* errcode {iserrno, isstat1-4}
*
* _ambuild() returns 0 if successful, or -1 to indicate an error.
*/
#define FDNEEDED 3 /* Needs at most 3 UNIX fds to open ISAM file */
/* ARGSUSED */
static int
_ambuild(isfname, openmode, varflag, minlen, maxlen, primkey,
owner, group, umask, isfhandle, curpos, errcode)
char *isfname;
enum openmode openmode;
Bool varflag;
int minlen, maxlen;
struct keydesc *primkey;
int owner, group;
Bytearray *isfhandle;
Bytearray *curpos;
struct errcode *errcode;
int umask;
{
Fcb *fcb = NULL;
Bytearray *isfhandle2;
Bytearray isfhandle0;
Keydesc2 keydesc2;
int err;
Crp *crp;
_isam_entryhook();
/*
* Validate the primary key descriptor.
*/
if (!USE_PHYS_ORDER(primkey) &&
_validate_keydesc(primkey, minlen) == ISERROR) {
_amseterrcode(errcode, EBADKEY);
goto ERROR;
}
/*
* Make isfhandle0.
*/
isfhandle0 = _makeisfhandle(isfname);
/*
* Check that there is not entry with the same name in FCB cache.
*/
if ((fcb = _mngfcb_find(&isfhandle0)) != NULL) {
fcb = _mngfcb_find(&isfhandle0);
(void) _watchfd_decr(_isfcb_nfds(fcb));
_isfcb_close(fcb);
_mngfcb_delete(&isfhandle0);
}
/*
* Check that there are UNIX file descriptors available.
*/
while (_watchfd_check() < FDNEEDED) {
/*
* Find victim (LRU FCB) and close it.
*/
if((isfhandle2 = _mngfcb_victim()) == NULL)
_isfatal_error ("_openfcb() cannot find LRU victim");
fcb = _mngfcb_find(isfhandle2);
(void) _watchfd_decr(_isfcb_nfds(fcb));
_isfcb_close(fcb);
_mngfcb_delete(isfhandle2);
}
/*
* Create UNIX files, return isfhandle and File Control Block (fcb).
*/
if ((fcb = _isfcb_create(isfname, 1, (primkey->k_nparts != 0), (int)varflag,
owner, group, umask, errcode)) == NULL) {
goto ERROR;
}
/*
* Add length info to the FCB.
*/
_isfcb_setreclength(fcb, varflag, minlen, maxlen);
if (!USE_PHYS_ORDER(primkey)) {
/*
* Convert key descriptor to internal form.
*/
_iskey_xtoi (&keydesc2, primkey);
/*
* Create index structure.
*/
if ((err = _create_index(fcb , &keydesc2)) != ISOK) {
_amseterrcode(errcode, err);
goto ERROR;
}
/*
* Add primary key descriptor to FCB.
*/
if (_isfcb_primkeyadd(fcb, &keydesc2) == ISERROR) {
_amseterrcode(errcode, ETOOMANY);
goto ERROR;
}
}
/*
* Initial current record position.
*/
if (FCB_NOPRIMARY_KEY(fcb)) {
/* Use physical order. */
crp = (Crp *) _ismalloc(sizeof(*crp));
memset ((char *) crp, 0, sizeof(*crp));
crp->keyid = PHYS_ORDER;
crp->flag = CRP_BEFOREANY;
curpos->length = sizeof(*crp);
curpos->data = (char *) crp;
}
else {
/*
* Use primary key order.
*/
crp = (Crp *) _ismalloc((unsigned)(sizeof(*crp) + fcb->keys[0].k2_len));
memset((char *) crp, 0, (sizeof(*crp) + fcb->keys[0].k2_len));
crp->keyid = fcb->keys[0].k2_keyid;
crp->flag = CRP_BEFOREANY;
_iskey_fillmin(&fcb->keys[0], crp->key);
curpos->length = sizeof(*crp) + fcb->keys[0].k2_len;
curpos->data = (char *) crp;
/*
* Set full key length as the number of bytes to match in key comparison
*/
crp->matchkeylen = fcb->keys[0].k2_len - RECNOSIZE;
if (ALLOWS_DUPS2(&fcb->keys[0]))
crp->matchkeylen -= DUPIDSIZE;
}
_amseterrcode(errcode, ISOK);
/*
* Register the number of UNIX fd consumed.
*/
(void) _watchfd_incr(_isfcb_nfds(fcb));
/*
* Insert new entry into FCB cache.
*/
_mngfcb_insert(fcb, &isfhandle0);
*isfhandle = isfhandle0;
/* Commit all work in disk cache. */
_issignals_mask();
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
/*
* Create Control Page (CNTLPAGE).
*/
if (_isfcb_cntlpg_w(fcb) == ISERROR) {
_issignals_unmask();
goto ERROR;
}
_issignals_unmask();
_isam_exithook();
return (ISOK);
ERROR:
if (fcb != NULL) {
_isfcb_remove(fcb);
_isfcb_close(fcb);
}
_bytearr_free(&isfhandle0);
_isam_exithook();
return (ISERROR);
}

View File

@@ -0,0 +1,103 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isbytearray.c /main/3 1995/10/23 11:36:32 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isbytearray.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isbytearray.c
*
* Description:
* Byte array handling functions.
*
*/
#include "isam_impl.h"
/*
* _bytearr_getempty()
*
* Return an empty byte array.
*/
Bytearray
_bytearr_getempty()
{
static Bytearray empty_bytearray = { 0, NULL};
return (empty_bytearray);
}
/*
* bytearray = _bytearr_new(len, data)
*
* Create a byte array object.
*/
Bytearray
_bytearr_new(len, data)
u_short len;
char *data;
{
Bytearray bytearray;
bytearray.length = len;
bytearray.data = _ismalloc(len);
memcpy( bytearray.data,data, (int)len);
return (bytearray);
}
/*
* new = _bytearr_dup(old)
*
* Duplicate a byte array object.
*/
Bytearray
_bytearr_dup(old)
Bytearray *old;
{
return (_bytearr_new(old->length, old->data));
}
/*
* _bytearr_free(barrray)
*
* Free byte array buffer, set barray to an empty byte array.
*/
void
_bytearr_free(barray)
register Bytearray *barray;
{
if (barray->data)
free(barray->data);
*barray = _bytearr_getempty();
}
/*
* _bytearr_cmp(l, r)
*
* Compare two byte array objects. Return 0 if they are equal, non-zero if
* they differ.
*/
int
_bytearr_cmp(l,r)
register Bytearray *l, *r;
{
if (l->length == r->length)
return (memcmp(l->data, r->data, (int)l->length));
else
return (1); /* not equal */
}

View File

@@ -0,0 +1,180 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: ischange1key.c /main/3 1995/10/23 11:36:41 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)ischange1key.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* ischange1key.c
*
* Description:
* Update an index if necessary.
*
*
*/
#include "isam_impl.h"
extern long *ismaxlong;
int
_change1key(fcb, pkeydesc2, record, oldrecord, recnum, newkey)
Fcb *fcb;
Keydesc2 *pkeydesc2;
char *record;
char *oldrecord;
Recno recnum;
char *newkey;
{
char keybuf1[MAXKEYSIZE];
char keybuf2[MAXKEYSIZE];
Btree *btree;
char *pkey;
/*
* Special case when there is no primary key.
*/
if (pkeydesc2->k2_nparts == 0)
return (ISOK);
/* Get old key value. */
memset((char *)keybuf1, 0, pkeydesc2->k2_len);
_iskey_extract(pkeydesc2, oldrecord, keybuf1);
strecno(recnum, keybuf1);
/* Get new key value. */
memset((char *)keybuf2, 0, pkeydesc2->k2_len);
_iskey_extract(pkeydesc2, record, keybuf2);
strecno(recnum, keybuf2);
/*
* See if the key changed.
*/
if (memcmp(keybuf1, keybuf2, pkeydesc2->k2_len)) {
/*
* Delete the old key entry from B tree.
*/
btree = _isbtree_create(fcb, pkeydesc2);
_isbtree_search(btree, keybuf1);
if (ALLOWS_DUPS2(pkeydesc2)) {
/*
* We must now scan all the duplicates till we found one with
* matching recno. We are positioned just before the first duplicate.
* Remember that the duplicates are ordered by their serial number.
*
* If too many duplicate entries exists, the performance will be
* poor.
*/
while ((pkey = _isbtree_next(btree)) != NULL) {
if (ldrecno(pkey + KEY_RECNO_OFF) == recnum)
break; /* We found the entry */
}
if (pkey == NULL)
_isfatal_error("_del1key() cannot find entry in B tree");
_isbtree_remove(btree);
}
else {
if ((pkey = _isbtree_current(btree)) == NULL ||
ldrecno(pkey + KEY_RECNO_OFF) != recnum)
_isfatal_error("_del1key() cannot find entry in B tree");
_isbtree_remove(btree);
}
_isbtree_destroy(btree);
/*
* Insert new key entry into B tree.
*/
btree = _isbtree_create(fcb, pkeydesc2);
if (ALLOWS_DUPS2(pkeydesc2)) {
/*
* Duplicates allowed on this key.
* Try to read the last duplicate (with the highest serial number).
* If such duplicate exists, the inserted key entry will be
* assigned next higher value for duplicate serial number.
* If there is no such duplicate, assign duplicate serial number 1.
*/
strecno(recnum, keybuf2 + KEY_RECNO_OFF);
memcpy( keybuf2 + KEY_DUPS_OFF,(char *)ismaxlong, LONGSIZE);
_isbtree_search(btree, keybuf2);
if ((pkey = _isbtree_current(btree)) != NULL &&
memcmp(pkey + RECNOSIZE + DUPIDSIZE,
keybuf2 + RECNOSIZE + DUPIDSIZE,
pkeydesc2->k2_len - RECNOSIZE - DUPIDSIZE) == 0) {
/*
* A duplicate exists. Assign +1 value for the new serial
* number.
*/
stlong(ldlong(pkey + KEY_DUPS_OFF) + 1, keybuf2 + KEY_DUPS_OFF);
/*
* Indicate that there are allowed duplicate key values.
*/
isdupl = 1;
}
else {
/*
* This is the first duplicate. Assign serial number 1.
*/
stlong(1L, keybuf2 + KEY_DUPS_OFF);
}
_isbtree_insert(btree, keybuf2);
_isbtree_destroy(btree);
}
else {
/* Duplicates not allowed on this key.
* Set TID part to maximum value, causing the search path
* to point just past the possible duplicate in the key file
* If there is no duplicate, this is the correct spot to
* insert the new key entry.
*/
memcpy( keybuf2 + KEY_RECNO_OFF,(char *)ismaxlong, LONGSIZE);
_isbtree_search (btree, keybuf2);
if ((pkey = _isbtree_current(btree)) != NULL &&
memcmp(pkey + RECNOSIZE, keybuf2 + RECNOSIZE,
pkeydesc2->k2_len - RECNOSIZE) == 0) {
_isbtree_destroy(btree);
return (EDUPL);
}
strecno(recnum, keybuf2 + KEY_RECNO_OFF);
_isbtree_insert(btree, keybuf2);
_isbtree_destroy(btree);
}
}
/*
* Return new key position.
*/
if (newkey != NULL)
memcpy( newkey,keybuf2, pkeydesc2->k2_len);
return (ISOK);
}

View File

@@ -0,0 +1,75 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isclose.c /main/3 1995/10/23 11:36:50 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isclose.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isclose.c
*
* Description:
* Close an ISAM file
*/
#include "isam_impl.h"
#include <sys/time.h>
/*
* isclose(isfd)
*
* Isclose() closes the ISAM file associated with the file descriptor isfd.
* There may be other ISAM file descriptors in use which are associated
* with the same ISAM file; are not effected by isclose().
*
* Isclose() returns -1 if an errors was detected, or 0 if the file was closed
* successfully.
*
* Errors:
* ENOTOPEN isfd is not ISAM file descriptor of an open ISAM file.
*/
int
isclose(isfd)
int isfd;
{
Fab *fab;
Fcb *fcb;
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(&fab->isfhandle, &fab->errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
/*
* Delete FCB and remove it from FCB cache. Close UNIX fds.
*
* This is desirable when ISAM files are removed from other processes,
* or simply by 'rm file.*'.
*/
(void) _watchfd_decr(_isfcb_nfds(fcb));
_isfcb_close(fcb);
_mngfcb_delete(&fab->isfhandle);
_isam_exithook();
_fab_destroy(fab); /* Deallocate Fab object */
_isfd_delete(isfd);
return (ISOK);
}

View File

@@ -0,0 +1,104 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iscntl.c /main/3 1995/10/23 11:36:59 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iscntl.c 1.8 94/11/17";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iscntl.c
*
* Description:
* Generic control function
*/
#include <varargs.h>
#include "isam_impl.h"
/*
* err = iscntl(isfd, args)
*
* Functions:
*
* iscntl(isfd, ISCNTL_RPCS_TO_SET, tout) - Set timeout for short operations
* iscntl(isfd, ISCNTL_RPCL_TO_SET, tout) - Set timeout for long operations
* iscntl(isfd, ISCNTL_RPCS_TO_GET) - Get timeout for short operations
* iscntl(isfd, ISCNTL_RPCL_TO_GET) - Get timeout for long operations
* iscntl(isfd, ISCNTL_TCP_TO_SET) - Set TCP reconnect timeout
* iscntl(isfd, ISCNTL_TCP_TO_GET) - Get TCP reconnect timeout
*
* iscntl(isfd, ISCNTL_APPLMAGIC_WRITE, string) - Write application magic
* iscntl(isfd, ISCNTL_APPLMAGIC_READ, buf) - Read application magic
*
* iscntl(ALLISFD, ISCNTL_FDLIMIT_SET, n) - Set limit on UNIX fd use
* iscntl(ALLISFD, ISCNTL_FDLIMIT_GET) - Set limit on UNIX fd use
*
* oldfunc = iscntl(ALLISFD, ISCNTL_FATAL, func) - Set fatal error handler
* int func(msg) - Apllication handler
* if 0 is returned, NetISAM will use openlog("NetISAM") and
* syslog(ERR_LOG, msg) to log the error.
*
* iscntl(ALLISFD, ISCNTL_MASKSIGNALS, bool) 1 mask, 0 don't mask
*
* iscntl(isfd, ISCNTL_FSYNC) - synchronize a file's in-core state
* with that on disk
*
*/
typedef int (* intfunc)();
int
iscntl(isfd, func, va_alist)
int isfd;
int func;
va_dcl
{
extern int (*_isfatal_error_set_func())();
va_list pvar;
int ret;
va_start(pvar);
switch (func) {
case ISCNTL_MASKSIGNALS:
ret = _issignals_cntl(va_arg(pvar, int));
break;
case ISCNTL_FATAL:
ret = (int)_isfatal_error_set_func(va_arg(pvar, intfunc));
break;
case ISCNTL_FDLIMIT_SET:
ret = _watchfd_max_set(va_arg(pvar, int));
break;
case ISCNTL_FDLIMIT_GET:
ret = _watchfd_max_get();
break;
case ISCNTL_APPLMAGIC_WRITE:
ret = _isapplmw(isfd, (va_arg(pvar, char *)));
break;
case ISCNTL_APPLMAGIC_READ:
ret = _isapplmr(isfd, (va_arg(pvar, char *)));
break;
case ISCNTL_FSYNC:
ret = _isfsync(isfd);
break;
default:
_setiserrno2(EBADARG, '9', '0');
ret = ISERROR;
}
va_end(pvar);
return (ret);
}

View File

@@ -0,0 +1,98 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iscurpos.c /main/3 1995/10/23 11:37:08 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iscurpos.c 1.5 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* @(#)iscurpos.c 1.2 95/01/06
*
* Description:
* Save and restore current record position functions.
*/
#include "isam_impl.h"
#include <sys/file.h>
/*
* err = isgetcurpos(isfd, len, buf)
*
* Get current record position and save it in user buffer.
*
* The user buffer buf is filled with (if the information is N bytes):
* buf[0], buf[1] total length as u_short (set to N + 2)
* buf[2] .. buf[N + 1] current record position information
*/
int
isgetcurpos(isfd, len, buf)
int isfd;
int *len;
char **buf;
{
Fab *fab;
u_short total_len;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
total_len = sizeof(total_len) + fab->curpos.length;
if (*buf != NULL && *len < (int)total_len) {
_setiserrno2(E2BIG, '9', '0');
return (ISERROR);
}
if (*buf == NULL) {
*len = total_len;
*buf = _ismalloc((unsigned int)total_len);
}
memcpy(*buf, (char *) &total_len, sizeof(total_len));
memcpy(*buf+sizeof(total_len), fab->curpos.data, (int)fab->curpos.length);
return (ISOK);
}
/*
* err = issetcurpos(isfd, buf)
*
* Get current record position and save it in user buffer.
*/
int
issetcurpos(isfd, buf)
int isfd;
char *buf;
{
Fab *fab;
u_short len;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
memcpy((char *)&len, buf, sizeof(len));
len -= sizeof (len);
_bytearr_free(&fab->curpos);
fab->curpos = _bytearr_new(len, buf + sizeof(len));
return (ISOK);
}

View File

@@ -0,0 +1,323 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isdatconv.c /main/3 1995/10/23 11:37:16 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isdatconv.c 1.5 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isdatconv.c
*
* Description:
* Conversion function between machine dependent and the X/OPEN
* machine independent formats.
*
* Some pieces of code may not be very "structured", but they result in
* optimized code with the -O compiler option.
*
*/
#include "isam_impl.h"
#define BLANK ' '
/* conversion functions for sparc architecture */
/* ldlong() - Load a long integer from a potentially unaligned address */
long
ldlong(p)
register char *p;
{
int i;
#if LONG_BIT == 64
register unsigned long val;
#else
register unsigned int val;
#endif
val = 0;
for (i=0; i<LONGSIZE ; i++)
val = (val << 8) + *((unsigned char *)p++);
return ((long)val);
}
/* stlong() - Store a long integer at a potentially unaligned address */
int
stlong(val, p)
register long val;
register char *p;
{
int i;
p += LONGSIZE;
for (i=0; i<LONGSIZE ; i++)
*--p = (val >> 8*i) & 255;
return(0);
}
/* ldint() - Load a short integer from a potentially unaligned address */
short
ldint(p)
register char *p;
{
register unsigned int val;
val = *((unsigned char *)p++);
val = (val << 8) + *((unsigned char *)p++);
return ((short)val);
}
/* ldunshort - load a unshort integer : for 64K record length */
u_short
ldunshort(p)
register char *p;
{
register unsigned int val;
val = *((unsigned char *)p++);
val = (val << 8) + *((unsigned char *)p++);
return ((u_short)val);
}
/* stint() - Store a short integer at a potentially unaligned address */
int
stint(val, p)
register short val;
register char *p;
{
p += SHORTSIZE;
*--p = val & 255;
*--p = (val >> 8) & 255;
return(0);
}
/* ldchar() - Load character field */
int
ldchar(src, len, dst)
char *src;
register char *dst;
int len;
{
register char *p;
if (len <= 0)
return;
/* Load the entire string. */
memcpy((void *) dst, (const void *) src, len);
/* Remove trailing blanks. */
p = dst + len;
while (--p >= dst) {
if (*p != BLANK) {
break;
}
}
*++p = '\0';
}
int
stchar(src, dst, len)
register char *src;
register char *dst;
register int len;
{
register char c;
if (len <= 0)
return;
/* Copy up to NULL character. */
do {
if ((c = *src++) == '\0')
break;
*dst++ = c;
} while (--len > 0);
/* Pad with blanks. */
if (len > 0)
(void) memset((void *) dst, BLANK, len);
}
/* ldchar2() - Load character field (C style, NULL padded) */
int
ldchar2(src, len, dst)
char *src;
register char *dst;
int len;
{
register char *p;
if (len <= 0)
return;
/* Load the entire string. */
memcpy((void *) dst, (const void *) src, len);
*(dst + len) = NULL;
}
int
stchar2(src, dst, len)
register char *src;
register char *dst;
register int len;
{
register char c;
if (len <= 0)
return;
/* Copy up to a NULL character. */
do {
if ((c = *src++) == '\0')
break;
*dst++ = c;
} while (--len > 0);
/* Pad with NULLs. */
if (len > 0)
memset(dst, 0, len);
}
/* ldfloat() - Load a float number from a potentially unaligned address */
float
ldfloat(p)
register char *p;
{
union {
float fval;
int ival;
} uval;
register unsigned int val;
val = *((unsigned char *)p++);
val = (val << 8) + *((unsigned char *)p++);
val = (val << 8) + *((unsigned char *)p++);
val = (val << 8) + *((unsigned char *)p++);
uval.ival = val;
return (uval.fval);
}
/* stfloat() - Store a float number at a potentially unaligned address */
int
stfloat(f, p)
float f; /* Bug - it is passed as double */
register char *p;
{
register unsigned val;
union {
float fval;
int ival;
} uval;
uval.fval = f; /* This fixes compiler bug */
val = uval.ival;
p += LONGSIZE;
*--p = val & 255;
*--p = (val >> 8) & 255;
*--p = (val >> 16) & 255;
*--p = (val >> 24) & 255;
return(0);
}
#if sparc | mc68000 /* MRJ */
/* ldbld() - Load a double float number from a potentially unaligned address */
double
lddbl(p)
register char *p;
{
double val;
memcpy((void *)&val, (const void *) p, DOUBLESIZE);
return (val);
}
/* stdbl() - Store a double float number at a potentially unaligned address */
int
stdbl(val, p)
double val;
register char *p;
{
memcpy ( p,(char *)&val, DOUBLESIZE);
}
#else /* 386i -- do it the long way round.... */
/* ldbld() - Load a double float number from a potentially unaligned address */
double
lddbl(p)
register char *p;
{
union {
double rval;
char sval[DOUBLESIZE];
} x;
char *q;
int i;
q = x.sval;
p += DOUBLESIZE;
for (i=0; i<DOUBLESIZE; i++)
*q++ = *--p;
return (x.rval);
}
/* stdbl() - Store a double float number at a potentially unaligned address */
int
stdbl(val, p)
double val;
register char *p;
{
union {
double rval;
char sval[DOUBLESIZE];
} x;
char *q;
int i;
x.rval = val;
q = x.sval;
p += DOUBLESIZE;
for (i=0; i<DOUBLESIZE; i++)
*--p = *q++ ;
return(0);
}
#endif /* sparc */

View File

@@ -0,0 +1,78 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isdel1key.c /main/3 1995/10/23 11:37:24 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isdel1key.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isdel1key.c
*
* Description:
* Delete a key entry from index
*
*
*/
#include "isam_impl.h"
void
_del1key(fcb, pkeydesc2, record, recnum)
Fcb *fcb;
Keydesc2 *pkeydesc2;
char *record;
Recno recnum;
{
char keybuf[MAXKEYSIZE];
Btree *btree;
char *pkey;
/*
* Special case when there is no primary key.
*/
if (pkeydesc2->k2_nparts == 0)
return;
memset((char *)keybuf, 0,pkeydesc2->k2_len);
_iskey_extract(pkeydesc2,record,keybuf);
strecno(recnum, keybuf);
btree = _isbtree_create(fcb, pkeydesc2);
_isbtree_search(btree, keybuf);
if (ALLOWS_DUPS2(pkeydesc2)) {
/*
* We must now scan all the duplicates till we found one with
* matching recno. We are positioned just before the first duplicate.
* Remember that the duplicates are ordered by their serial number.
*
* If too many duplicate entries exists, the performance will be
* poor.
*/
while ((pkey = _isbtree_next(btree)) != NULL) {
if (ldrecno(pkey + KEY_RECNO_OFF) == recnum)
break; /* We found the entry */
}
if (pkey == NULL)
_isfatal_error("_del1key() cannot find entry in B tree");
_isbtree_remove(btree);
}
else {
if ((pkey = _isbtree_current(btree)) == NULL ||
ldrecno(pkey + KEY_RECNO_OFF) != recnum)
_isfatal_error("_del1key() cannot find entry in B tree");
_isbtree_remove(btree);
}
_isbtree_destroy(btree);
}

View File

@@ -0,0 +1,190 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isdelcurr.c /main/3 1995/10/23 11:37:32 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isdelcurr.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isdelcurr.c
*
* Description:
* Delete current record from ISAM file.
*/
#include "isam_impl.h"
#include <sys/time.h>
static int _amdelcurr();
/*
* err = isdelcurr(isfd, record)
*
* Isdelcurr() modifies the current record in ISAM file.
* All indexes of the ISAM file are updated.
*
* Current record position is not changed.
* isrecnum is set to to the deleted record.
*
* Returns 0 if successful, or -1 of any error.
*
* Errors:
* ELOCKED The record or file has been locked by another process.
* ENOTOPEN isfd does not correspond to an open ISAM file, or the
* ISAM file was not opened with ISINOUT mode.
* ENOCURR Record with record number recnum does not exist, or it
* was deleted by another process.
*/
int
isdelcurr(isfd)
int isfd;
{
int _am_delcurr();
register Fab *fab;
int ret;
int recnum;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISINOUT.
*/
if (fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
if ((ret = _amdelcurr(&fab->isfhandle, &fab->curpos,
&recnum, &fab->errcode)) == ISOK) {
isrecnum = recnum; /* Set isrecnum */
}
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}
/*
* _amdelcurr(isfhandle, curpos, recnum, errcode)
*
* _amdelcurr() deletes a record from ISAM file.
*
* Input params:
* isfhandle Handle of ISAM file
* curpos Curent record position
*
* Output params:
* recnum record number of the deleted record
* errcode error status of the operation
*
*/
static int
_amdelcurr(isfhandle, curpos, recnum, errcode)
Bytearray *isfhandle;
Bytearray *curpos;
Recno *recnum;
struct errcode *errcode;
{
Fcb *fcb = NULL;
Crp *crp;
char recbuf[ISMAXRECLEN];
int reclen;
int (*rec_read)();
int (*rec_delete)();
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
rec_delete = (fcb->varflag?_vlrec_delete:_flrec_delete);
/*
* Get info from current record position structure.
*/
crp = (Crp *) curpos->data;
if (crp->flag != CRP_ON) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r2(fcb);
/*
* We must read the record first to be able to delete keys.
*/
if (rec_read(fcb, recbuf, crp->recno, &reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
if (rec_delete(fcb, crp->recno) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
*recnum = crp->recno;
fcb->nrecords--;
/*
* Delete associated entries from all indexes.
*/
_delkeys(fcb, recbuf, crp->recno);
_amseterrcode(errcode, ISOK);
_issignals_mask();
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
/*
* Update CNTL Page from the FCB.
*/
(void)_isfcb_cntlpg_w2(fcb);
_issignals_unmask();
_isam_exithook();
return (ISOK);
ERROR:
_isdisk_rollback();
_isdisk_inval();
/*
* Restore FCB from CNTL page.
*/
if (fcb) (void)_isfcb_cntlpg_r2(fcb);
_isam_exithook();
return (ISERROR);
}

View File

@@ -0,0 +1,75 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isdelrec.c /main/3 1995/10/23 11:37:39 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isdelrec.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isdelrec.c
*
* Description:
* Delete a record in ISAM file.
*/
#include "isam_impl.h"
#include <sys/time.h>
/*
* err = isdelrec(isfd, recnum)
*
* Isdelete() deletes a record from ISAM file. The record is identified
* by its record number. All indexes of the ISAM file are updated.
*
* Current record position is not changed.
* isrecnum is set to recnum.
*
*
* Returns 0 if successful, or -1 of any error.
*
* Errors:
* ELOCKED The file has been locked by another process.
* ENOTOPEN isfd does not correspond to an open ISAM file, or the
* ISAM file was not opened with ISINOUT mode.
* ENOREC Record with record number recnum does not exist.
*/
int
isdelrec(isfd, recnum)
int isfd;
long recnum;
{
int _amdelrec();
register Fab *fab;
int ret;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISINOUT.
*/
if (fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
if ((ret = _amdelrec(&fab->isfhandle, recnum, &fab->errcode)) == ISOK) {
isrecnum = recnum; /* Set isrecnum */
}
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}

View File

@@ -0,0 +1,507 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isdiskbufs2.c /main/3 1995/10/23 11:37:47 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isdiskbufs2.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* _isdiskbufs.c
*
* Description:
* ISAM disk buffer managament
*
*/
/************************ NON MAPPED I/O version ***************************/
#include "isam_impl.h"
extern struct dlink *_isdln_next(), *_isdln_first();
#define ISMAXBUFFERS 200 /* Use 20 buffers */
#define ISHASHHDRS 256 /* Must be a power of two */
#define ISHASHMASK (ISHASHHDRS-1)
#define __hashblkno(fcb,blkno) (((int)(fcb)+(blkno)) & ISHASHMASK)
#define base ((char *)0)
#define _isdln_insert(l,e) _isdln_base_insert(base,(l),(e))
#define _isdln_append(l,e) _isdln_base_append(base,(l),(e))
#define _isdln_remove(e) _isdln_base_remove(base,(e))
#define _isdln_first(l) _isdln_base_first(base,(l))
#define _isdln_next(l) _isdln_base_next(base,(l))
#define _isdln_prev(l) _isdln_base_prev(base,(l))
#define _isdln_makeempty(l) _isdln_base_makeempty(base,(l))
#define _isdln_isempty(l) _isdln_base_isempty(base,(l))
/*---------------------- Local data ---------------------------------------*/
static Bufhdr *_getavail(), *_findblock();
static void _disk_init(), _commit1buffer(), _rollback1buffer(), _flush1buffer();
static void _makenodata();
Bufhdr bufhdrs [ISMAXBUFFERS];
struct dlink hashhdrs [ISHASHHDRS]; /* Heads of hashed lists */
struct dlink availlist; /* Available buffer list */
struct dlink *pavail = &availlist;
struct dlink changelist; /* Change buffer list */
struct dlink *pchangl = &changelist;
struct dlink fixlist; /* Fixed buffer list */
struct dlink *pfixl = &fixlist;
static int availn; /* Number of available buffers */
static int minavailn; /* Minimum available buffers */
static int maxavailn; /* Stop flushing when
* when maxavailn buffers
* are available */
#define ISB_FIXED (ISB_RFIXED | ISB_WFIXED)
#define MINAVAILN 40 /* in procent of total # buffers */
#define MAXAVAILN 60 /* in procent of total # buffers */
Bufhdr *
_isdisk_fix(fcb, unixfd, blkno, mode)
Fcb *fcb;
int unixfd; /* .rec, .ind., .var */
Blkno blkno;
int mode;
{
register Bufhdr *p, *p2;
struct dlink *hashl;
/*
* Initialize some local data.
*/
_disk_init();
if (fcb->datfd == unixfd)
assert(blkno != 0); /* Never access control page */
hashl = (hashhdrs +__hashblkno(fcb,blkno));
/* Try to find the page in buffer pool. */
if ((p = _findblock(fcb, unixfd, blkno)) == NULL) {
/* Page is not in the pool - install it. */
if (mode != ISFIXNOREAD) {
p = _getavail(); /* Get free page from pool */
_isdln_insert(hashl,&p->isb_hash); /* Insert into hash list */
_isseekpg(unixfd, blkno);
_isreadpg(unixfd, p->isb_buffer);
p->isb_flags = ISB_READ;
p->isb_oldcopy = NULL;
p->isb_fcb = fcb;
p->isb_unixfd = unixfd;
p->isb_blkno = blkno;
}
else
p = NULL;
}
if (p && (p->isb_flags & ISB_FIXED)==0) {
/* Remove buffer from pavail (or pchangl) list. */
_isdln_remove(&p->isb_aclist);
if (!(p->isb_flags & ISB_CHANGE))
availn--;
}
if (mode == ISFIXREAD) {
assert(p);
if(!(p->isb_flags & ISB_FIXED)) {
/* Add buffer to pfixl list. */
_isdln_append(pfixl,&p->isb_flist);
p->isb_flags |= ISB_RFIXED;
}
return (p);
} /* if (p) */
else {
/* If buffer is already fixed for write, no other actions are necces. */
if (p && p->isb_flags & ISB_FIXED) {
assert((p->isb_flags & ISB_RFIXED) == 0); /* Buffer cannot be */
/* fixed for read when is fixed */
/* being fixed for write */
return (p);
}
/* Create shadow page */
p2 = _getavail(); /* Get free page from pool */
availn--;
_isdln_remove(&p2->isb_aclist); /* Remove from pavail */
_isdln_insert(hashl,&p2->isb_hash); /* Insert into hash list */
_isdln_insert(pfixl,&p2->isb_flist); /* Insert into pfixl list */
p2->isb_fcb = fcb;
p2->isb_unixfd = unixfd;
p2->isb_blkno = blkno;
p2->isb_flags = ISB_READ|ISB_WFIXED; /* Mark buffer as dirty */
if (mode == ISFIXWRITE) /* Copy buffer content */
memcpy(p2->isb_buffer,p->isb_buffer,ISPAGESIZE);
p2->isb_oldcopy = p;
/* Make old copy */
if (p) {
assert ((p->isb_flags & ISB_FIXED) == 0);
assert((p->isb_flags & ISB_OLDCOPY) == 0);
p->isb_flags |= ISB_OLDCOPY;
_isdln_remove(&p->isb_hash);
}
return (p2);
}
}
void
_isdisk_unfix (p)
register Bufhdr *p;
{
if (!(p->isb_flags & ISB_FIXED))
assert(p->isb_flags & ISB_FIXED);
if (p->isb_flags & ISB_WFIXED) /* Unfix at commit/abort time */
return;
p->isb_flags &= ~ISB_FIXED; /* Clear bit */
_isdln_remove(&p->isb_flist); /* Remove from pfixl */
/* Append to pavail or pchangl list. */
if (p->isb_flags & ISB_CHANGE)
_isdln_append(pchangl,&p->isb_aclist); /* Append to pchangl list */
else {
_isdln_append(pavail,&p->isb_aclist); /* Append to pavail list */
availn++;
}
}
void
_isdisk_commit1 (p)
Bufhdr *p;
{
_commit1buffer(p);
}
void
_isdisk_commit()
{
register Bufhdr *p;
struct dlink *e;
while ((e = _isdln_first(pfixl)) != pfixl) {
p = GETBASE(e,bufhdr,isb_flist); /* Get pointer to bufhdr */
assert(p->isb_flags & ISB_WFIXED);
_commit1buffer(p);
}
}
void
_isdisk_rollback()
{
register Bufhdr *p;
struct dlink *e;
while ((e = _isdln_first(pfixl)) != pfixl) {
p = GETBASE(e,bufhdr,isb_flist); /* Get pointer to bufhdr */
assert(p->isb_flags & ISB_FIXED);
if (p->isb_flags & ISB_WFIXED)
_rollback1buffer(p);
else
_isdisk_unfix(p);
}
}
Bufhdr *
_isdisk_refix(p, newmode)
Bufhdr *p;
int newmode;
{
Blkno blkno = p->isb_blkno;
Fcb *fcb = p->isb_fcb;
int unixfd = p->isb_unixfd;
assert(newmode == ISFIXWRITE);
if (p->isb_flags & ISB_RFIXED) {
_isdisk_unfix(p);
return (_isdisk_fix(fcb, unixfd, blkno, ISFIXWRITE));
}
else
return (p);
}
void
_isdisk_sync()
{
extern time_t _istimeget();
register Bufhdr *p;
struct dlink *e;
while ((e = _isdln_first(pchangl)) != pchangl) {
p = GETBASE(e,bufhdr,isb_aclist); /* Get pointer to bufhdr */
assert(p->isb_flags & ISB_CHANGE);
assert((p->isb_flags & ISB_FIXED)==0);
_flush1buffer(p);
}
}
void
_isdisk_inval()
{
extern time_t _istimeget();
register Bufhdr *p;
struct dlink *e;
/* ensure pavail is initialized before using it */
if (pavail->dln_forward == 0) {
_isdln_makeempty(pavail);
}
e = pavail;
while ((e = _isdln_prev(e)) != pavail) {
p = GETBASE(e,bufhdr,isb_aclist); /* Get pointer to bufhdr */
if ((p->isb_flags & ISB_READ) == 0)
break;
_isdln_remove(&p->isb_hash);
p->isb_flags = ISB_NODATA; /* Mark as no data in the buffer */
}
}
#if ISDEBUG
_isdisk_dumphd()
{
register Bufhdr *p;
int i;
(void)printf("\nInd isfd blkno mode temp oldcopy\n");
for (p = bufhdrs, i = 0; i < ISMAXBUFFERS; p++,i++)
if (p->isb_flags != ISB_NODATA)
(void) printf("%3d: %3d %6d %2x %3d\n",i,
_isfd_getisfd(p->isb_pisfd),
p->isb_blkno,p->isb_flags,
p->isb_oldcopy?(p->isb_oldcopy - bufhdrs):-1);
}
aclistdump(lh)
struct dlink *lh;
{
register Bufhdr *p;
struct dlink *e;
for (e = _isdln_first(lh); e != lh; e = _isdln_next(e)) {
p = GETBASE(e,bufhdr,isb_aclist); /* Get pointer to bufhdr */
(void) printf("%3d: %3d %6d %2x %3d\n",p-bufhdrs,
_isfd_getisfd(p->isb_pisfd),
p->isb_blkno,p->isb_flags,
p->isb_oldcopy?(p->isb_oldcopy - bufhdrs):-1);
}
}
flistdump(lh)
struct dlink *lh;
{
register Bufhdr *p;
struct dlink *e;
for (e = _isdln_first(lh); e != lh; e = _isdln_next(e)) {
p = GETBASE(e,bufhdr,isb_flist); /* Get pointer to bufhdr */
(void) printf("%3d: %3d %6d %2x %3d\n",p-bufhdrs,
_isfd_getisfd(p->isb_pisfd),
p->isb_blkno,p->isb_flags,
p->isb_oldcopy?(p->isb_oldcopy - bufhdrs):-1);
}
}
#endif
/*------------------------ Local functions ---------------------------------*/
Static void
_disk_init()
{
static Bool initialized = FALSE;
register int i;
if (initialized == TRUE)
return;
initialized = TRUE;
/* Initialize hash queue list heads. */
for (i = 0; i < ISHASHHDRS; i++) {
_isdln_makeempty(hashhdrs+i);
}
/* initialize pavail, pchangel, and pfixl lists to empty. */
_isdln_makeempty(pavail);
_isdln_makeempty(pchangl);
_isdln_makeempty(pfixl);
/* Link all buffers into pavail list. */
for (i = 0; i < ISMAXBUFFERS; i++) {
bufhdrs[i].isb_buffer = _ismalloc(ISPAGESIZE);
_isdln_append(pavail,&bufhdrs[i].isb_aclist);
availn++;
}
/* Set maxavailn and minavailn. */
minavailn = (ISMAXBUFFERS * MINAVAILN) / 100;
maxavailn = (ISMAXBUFFERS * MAXAVAILN) / 100;
}
/* _getavail() - get available buffer in disk */
Static Bufhdr *
_getavail()
{
register Bufhdr *p;
register struct dlink *q;
if ((q = _isdln_first(pavail)) == pavail) {
_isfatal_error("No buffer in pool available");
}
p = GETBASE(q,bufhdr,isb_aclist);
if (p->isb_flags & ISB_READ) { /* Remove from hash queue */
_isdln_remove(&p->isb_hash);
p->isb_flags = ISB_NODATA; /* Mark as no data in the buffer */
}
return ((Bufhdr *) p);
}
/* _findblock() - Find block in buffer pool */
Static Bufhdr *
_findblock(fcb, unixfd, blkno)
Fcb *fcb;
int unixfd;
Blkno blkno;
{
register Bufhdr *p;
struct dlink *lh, *e;
int hashval;
hashval = __hashblkno(fcb,blkno);
lh = hashhdrs + hashval; /* lh is list head */
for (e = _isdln_first(lh); e != lh; e = _isdln_next(e)) {
p = GETBASE(e,bufhdr,isb_hash); /* Get pointer to bufhdr */
if (p->isb_blkno == blkno && p->isb_fcb == fcb && p->isb_unixfd == unixfd) {
assert(p->isb_flags != ISB_NODATA);
return(p);
}
}
return (NULL);
}
/* _commit1buffer() - Commit changes to buffer */
Static void
_commit1buffer(p)
register Bufhdr *p;
{
assert(p->isb_flags & ISB_WFIXED); /* Fixed for read buffers should */
/* go through _isdisk_unfix() */
/* Free old permanent buffer if any exists. */
if (p->isb_oldcopy) {
_makenodata(p->isb_oldcopy); /* Make this buffer available */
}
/* Remove buffer from list of fixed buffers. */
/* Append buffer to list of changed buffers. */
_isdln_remove(&p->isb_flist);
_isdln_append(pchangl,&p->isb_aclist);
p->isb_flags &= ~ISB_FIXED;
p->isb_flags |= ISB_CHANGE;
}
/* _rollback1buffer() - Rollback changes to buffer */
Static void
_rollback1buffer(p)
register Bufhdr *p;
{
register Bufhdr *p2;
assert(p->isb_flags & ISB_WFIXED); /* Fixed for read buffers should */
/* go through _isdisk_unfix() */
/* Re-install old copy if that exists. */
if ((p2 = p->isb_oldcopy) != NULL) {
if (p2->isb_flags & ISB_CHANGE) {
_isdln_append(pchangl,&p2->isb_aclist);
}
else {
_isdln_append(pavail,&p2->isb_aclist);
availn++;
}
p2->isb_flags &= ~ISB_OLDCOPY; /* Clear bit */
/* See implementation of _isdln_append() that this will work. */
_isdln_append(&p->isb_hash,&p2->isb_hash); /* Insert into hash list */
}
_isdln_remove(&p->isb_hash); /* Remove bufer from hash list */
_isdln_remove(&p->isb_flist); /* Remove bufer from pfixl */
_makenodata(p); /* Make this buffer available */
}
/* _makenodata() - make buffer available with no data in it*/
Static void
_makenodata(p)
register Bufhdr *p;
{
assert(p->isb_flags & ISB_READ);
p->isb_flags = ISB_NODATA;
_isdln_insert(pavail,&p->isb_aclist);
availn++;
}
/* _flush1buffer() - flush buffer to disk */
Static void
_flush1buffer(p)
register Bufhdr *p;
{
assert(p->isb_flags & ISB_CHANGE);
_isseekpg(p->isb_unixfd, p->isb_blkno);
_iswritepg(p->isb_unixfd, p->isb_buffer);
p->isb_flags &= ~ISB_CHANGE; /* clear change flag */
_isdln_remove(&p->isb_aclist); /* Remove from pchangl */
_isdln_append(pavail,&p->isb_aclist); /* Append to pavail */
availn++;
}

View File

@@ -0,0 +1,103 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: isdlink.c /main/4 1999/09/29 15:03:15 mgreess $ */
#ifndef lint
static char sccsid[] = "@(#)isdlink.c 1.4 89/09/01 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isdlink.c
*
* Description:
* Double link list functions
*/
#include "isam_impl.h"
/* _isdln_base_insert () - Insert element into list (at the front) -----------*/
void _isdln_base_insert (base,l,e)
register char *base;
register struct dlink *l,*e;
{
e->dln_forward = l->dln_forward;
l->dln_forward = (char *)e - base;
e->dln_backward = (char *)l - base;
((struct dlink *)(base + e->dln_forward))->dln_backward = (char *)e - base;
}
/* _isdln_base_append () - Append element to list (at the end) -------------*/
void _isdln_base_append (base,l,e)
register char *base;
register struct dlink *l,*e;
{
e->dln_backward = l->dln_backward;
l->dln_backward = (char *)e - base;
e->dln_forward = (char *)l - base;
((struct dlink *)(base + e->dln_backward))->dln_forward = (char *)e - base;
}
/* _isdln_base_remove () - Remove element from list -------------------------*/
void _isdln_base_remove (base,e)
register char *base;
register struct dlink *e;
{
((struct dlink *)(base + e->dln_backward))->dln_forward = e->dln_forward;
((struct dlink *)(base + e->dln_forward))->dln_backward = e->dln_backward;
}
/* _isdln_base_first () - Return first element of the list -------------------*/
struct dlink * _isdln_base_first(base,l)
register char *base;
register struct dlink *l;
{
struct dlink *val = (struct dlink *)(base + l->dln_forward);
if (val == NULL) {
if (NULL == (struct dlink *)(base + l->dln_forward) &&
NULL == (struct dlink *)(base + l->dln_backward))
_isdln_base_makeempty(base, l);
val = l;
}
return(val);
}
/* _isdln_base_next () - Return next element in the list --------------------*/
struct dlink * _isdln_base_next(base,l)
register char *base;
register struct dlink *l;
{
return (((struct dlink *)(base + l->dln_forward)));
}
/* _isdln_base_prev () - Return previous element in the list ----------------*/
struct dlink * _isdln_base_prev(base,l)
register char *base;
register struct dlink *l;
{
return (((struct dlink *)(base + l->dln_backward)));
}
/* _isdln_base_makeempty () - Make head of empty list -----------------------*/
void _isdln_base_makeempty(base,l)
register char *base;
register struct dlink *l;
{
l->dln_forward = l->dln_backward = (char *)l - base;
}
/* _isdln_base_isempty () - Test if list is empty---------------------------*/
int _isdln_base_isempty(base,l)
register char *base;
register struct dlink *l;
{
return (l->dln_forward == (char *)l - base &&
l->dln_backward == (char *)l - base);
}

View File

@@ -0,0 +1,170 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iserase.c /main/3 1995/10/23 11:38:08 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iserase.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iserase.c
*
* Description:
* Erase an ISAM file.
*/
#include "isam_impl.h"
#include <sys/time.h>
static void _unlink_datfile(), _unlink_indfile(), _unlink_varfile();
static int _amerase();
/*
* isfd = iserase(isfname, mode)
*
*
* Errors:
* EBADFILE ISAM file is corrupted or it is not an NetISAM file
* EFLOCKED The file is exclusively locked by other process.
* EFNAME Invalid ISAM file name
* EFNAME ISAM file does not exist
* ETOOMANY Too many ISAM file descriptors are in use (128 is the limit)
*
* The following error code is "borrowed" from UNIX:
* EACCES UNIX file system protection denies access to the file:
* - mode is INOUT or OUTPUT and ISAM file is on
* a Read-Only mounted file system
* - UNIX file permissions don't allow access to the file
*/
int
iserase(isfname)
char *isfname;
{
Isfd isfd, isfd_nfs;
Fab *fab, *fab_nfs;
/*
* Open the file
*/
if ((isfd = isopen(isfname, ISINOUT)) == -1)
return (ISERROR); /* iserrno is set */
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_isfatal_error("iserase() cannot find FAB");
_setiserrno2(EFATAL, '9', '0');
return ISERROR;
}
if (_amerase(&fab->isfhandle, &fab->errcode)
&& fab->errcode.iserrno != ENOENT) {
_seterr_errcode(&fab->errcode);
(void)isclose(isfd);
return (ISERROR);
}
_fab_destroy(fab); /* Deallocate Fab object */
_isfd_delete(isfd);
return (ISOK); /* Successful iserase() */
}
/*
* _amerase(isfhandle)
*
* _amerase() erases ISAM file
*
* Input params:
* isfhandle Handle of ISAM file
*
* Output params:
* errcode Error code
*
*/
static int
_amerase(isfhandle, errcode)
Bytearray *isfhandle;
struct errcode *errcode;
{
Fcb *fcb;
char *isfname = _getisfname(isfhandle);
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
goto ERROR;
}
/*
* Delete FCB and remove it from FCB cache.
*/
(void) _watchfd_decr(_isfcb_nfds(fcb));
_isfcb_close(fcb);
_mngfcb_delete(isfhandle);
/*
* Unlink all UNIX files.
*/
_unlink_datfile(isfname);
_unlink_indfile(isfname);
_unlink_varfile(isfname);
_isam_exithook();
return (ISOK);
ERROR:
_isam_exithook();
return (ISERROR);
}
Static void
_unlink_datfile(isfname)
char *isfname;
{
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makedat_isfname(namebuf);
(void)unlink(namebuf);
}
Static void
_unlink_indfile(isfname)
char *isfname;
{
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makeind_isfname(namebuf);
(void)unlink(namebuf);
}
Static void
_unlink_varfile(isfname)
char *isfname;
{
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makevar_isfname(namebuf);
(void)unlink(namebuf);
}

View File

@@ -0,0 +1,140 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iserror.c /main/3 1995/10/23 11:38:16 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iserror.c 1.10 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iserror.c
*
* Description:
* NetISAM error handling functions.
*
*/
#include "isam_impl.h"
#include <errno.h>
#include <syslog.h>
#ifdef __ultrix__
#define LOG_USER LOG_INFO
#endif
/*
* _isfatal_error(msg)
*
* Fatal error. Display message and terminate program.
*/
static int (*fatal_error_user_handler)(); /* set by iscntl(..,ISCNTL_FATAL,..) */
void
_isfatal_error(msg)
char *msg;
{
int logerr;
if (fatal_error_user_handler) {
logerr = fatal_error_user_handler(msg); /* User returns 1 in order
* to use syslog()
*/
}
else
logerr = 1;
if (logerr) {
openlog("NetISAM", LOG_PID, LOG_USER);
/* Free one UNIX for syslog */
(void)close(0);
syslog(LOG_ERR, "Fatal error: %s - UNIX errno %d", msg, errno);
closelog();
}
exit (1);
}
void
_isfatal_error1(msg)
char *msg;
{
extern int _is_rpcnetisamd; /* is 1 if this is rpc.netisamd */
extern int _is_netisamlockd; /* is 1 if this is netisamlockd */
int logerr;
if (fatal_error_user_handler) {
logerr = fatal_error_user_handler(msg); /* User returns 1 in order
* to use syslog()
*/
}
else
logerr = 1;
if (logerr) {
openlog("NetISAM", LOG_PID, LOG_USER);
/* Free one UNIX for syslog */
(void)close(0);
syslog(LOG_ERR, "Fatal error: %s - UNIX errno %d", msg, errno);
closelog();
}
}
_isam_warning(msg)
char *msg;
{
openlog("NetISAM", LOG_PID, LOG_USER);
syslog(LOG_ERR, msg);
}
/* Set user specified fatal_error handler */
int (*_isfatal_error_set_func(func))()
int (*func)();
{
int (*oldfunc)();
oldfunc = fatal_error_user_handler;
fatal_error_user_handler = func;
return (oldfunc);
}
/*
* _setiserrno2(error, isstat1, isstat2)
*
* Set iserrno variable.
*/
void
_setiserrno2(error, is1, is2)
int error;
int is1, is2;
{
iserrno = error;
isstat1 = is1;
isstat2 = is2;
}
/*
* _seterr_errcode(errcode)
*
* Set all error and status variable from errcode structure.
*/
void
_seterr_errcode(errcode)
register struct errcode *errcode;
{
iserrno = errcode->iserrno;
isstat1 = errcode->isstat[0];
isstat2 = errcode->isstat[1];
isstat3 = errcode->isstat[2];
isstat4 = errcode->isstat[3];
}

View File

@@ -0,0 +1,80 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isfab.c /main/3 1995/10/23 11:38:24 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isfab.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfab.c
*
* Description:
* The ISAM file access block functions.
*
*/
#include "isam_impl.h"
/*
* fab = *fab_new(isfname, mode, varlen, minreclen, maxreclen)
*
* Fab_new() creates an File access block (fab object) that is used
* for all subsequent operations in this file. Return a pointer to
* the fab object, or NULL in the case of an error.
*/
Fab *
_fab_new(isfname, openmode,
varlen, minreclen, maxreclen)
char *isfname; /* Local path on the host */
enum openmode openmode;
Bool varlen; /* 0/1 flag */
int minreclen, maxreclen;
{
register Fab *fab;
/* Allocate memory for the fab object. */
fab = (Fab *) _ismalloc(sizeof(*fab));
memset((char *)fab, 0, sizeof(*fab));
if (fab == NULL) {
iserrno = EFATAL;
return (NULL);
}
/* Set fields in the fab objects. */
fab->openmode = openmode;
fab->varlength = varlen;
fab->minreclen = minreclen;
fab->maxreclen = maxreclen;
fab->isfname = _isallocstring(isfname);
if (fab->isfname == NULL) {
free((char *)fab);
iserrno = EFATAL;
return (NULL);
}
return (fab);
}
void
_fab_destroy(fab)
register Fab *fab;
{
assert(fab != NULL);
assert(fab->isfname != NULL);
_isfreestring(fab->isfname);
_bytearr_free(&fab->isfhandle);
_bytearr_free(&fab->curpos);
free((char *)fab);
}

View File

@@ -0,0 +1,873 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isfcb.c /main/3 1995/10/23 11:38:34 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isfcb.c 1.9 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfcb.c
*
* Description: _ambuild()
* File Control Block functions
*
*
*/
#include "isam_impl.h"
#include <sys/stat.h>
static int _create_datfile(), _create_indfile(), _create_varfile();
static void _remove_datfile(), _remove_indfile(), _remove_varfile();
Static int _open_datfile(), _open_indfile(), _open_varfile();
/*
* _isfcb_create(isfname, crdat, crind, crvar, owner, group, u_mask, errcode)
*
* Create ISAM file: create UNIX files (dat/ind/var),
* and initialize File Control Block.
*
* Return 0 if create is successful, or -1 if any error. In the case of
*an error, the errcode block is set.
*/
Fcb *
_isfcb_create(isfname, crdat, crind, crvar, owner, group, u_mask, errcode)
char *isfname;
int crdat, crind, crvar; /* 0/1 flags */
int owner, group;
struct errcode *errcode;
int u_mask;
{
register Fcb *fcb;
int dat_fd = -1;
int ind_fd = -1;
int var_fd = -1;
int oldumask = umask (u_mask); /* Change umask to client's */
/*
* Create the UNIX file for .rec file.
*/
if (crdat && (dat_fd = _create_datfile (isfname)) == -1) {
_amseterrcode(errcode, errno);
goto ERROR;
}
/*
* If a primary is specified, create .ind file.
*/
if (crind && (ind_fd = _create_indfile (isfname)) == -1) {
_amseterrcode(errcode, errno);
goto ERROR;
}
/*
* If the ISAM file is for variable length records, create .var file.
*/
if (crvar && (var_fd = _create_varfile (isfname)) == -1) {
_amseterrcode(errcode, errno);
goto ERROR;
}
/*
* Change user and group onwer ship of the file.
* This has affect only when executed by the netisamd daemon.
*/
if (dat_fd != -1)
(void) fchown(dat_fd, owner, group);
if (ind_fd != -1)
(void) fchown(ind_fd, owner, group);
if (var_fd != -1)
(void) fchown(var_fd, owner, group);
/*
* Allocate File Control Block.
*/
fcb = (Fcb *) _ismalloc(sizeof(*fcb));
memset ((char *) fcb, 0, sizeof(*fcb));
fcb->isfname = _isallocstring(isfname);
fcb->rdonly = FALSE;
fcb->datfd = dat_fd;
fcb->indfd = ind_fd;
fcb->varfd = var_fd;
fcb->datsize = N_CNTL_PAGES; /* Control Pages */
fcb->indfreelist = FREELIST_NOPAGE;
/* Key descriptor */
fcb->nkeys = 1;
fcb->keys = (Keydesc2 *) _ismalloc(sizeof(fcb->keys[0]));
memset((char *)fcb->keys, 0, sizeof(fcb->keys[0]));
return (fcb);
ERROR:
/* Undo whatever was done. */
if (dat_fd != -1) {
(void) close(dat_fd);
_remove_datfile(isfname);
}
if (ind_fd != -1) {
(void) close(ind_fd);
_remove_indfile(isfname);
}
if (var_fd != -1) {
(void) close(var_fd);
_remove_varfile(isfname);
}
(void) umask(oldumask);
return (NULL);
}
/*
* _isfcb_setlength(fcb, varflag, minreclen, maxreclen)
*
* Set FCB attributes pertaining to record length.
*/
void
_isfcb_setreclength(fcb, varflag, minreclen, maxreclen)
register Fcb *fcb;
Bool varflag;
int minreclen, maxreclen;
{
fcb->varflag = varflag;
fcb->minreclen = minreclen;
fcb->maxreclen = maxreclen;
}
/*
* _isfcb_open(isfname, errcode)
*
* Open ISAM file: open UNIX files and create File Control Block.
*
* Return 0 if open is successful, or -1 if any error. In the case of an error,
* the errcode block is set.
*
* Note that rdonly is not fuly implemented. Now, all ISAM files are assumed
* to have permissions set to 0666 and may be opened in RW mode.
* If read-only media are used then the _open_datfile() function would have to
* try first to open the file in RW mode, and of that failed, try to
* open it in RO mode. The rdonly flag is used to reject any isamopen() with
* INOUT or OUTPUT mode on such files.
*/
Fcb *
_isfcb_open(isfname, errcode)
char *isfname;
struct errcode *errcode;
{
register Fcb *fcb;
int dat_fd = -1;
int ind_fd = -1;
int var_fd = -1;
Bool rdonly; /* set to 1 if file is Read-Only */
/*
* Open the UNIX file for .rec file.
*/
if ((dat_fd = _open_datfile (isfname, &rdonly)) == -1 || errno == EMFILE) {
_amseterrcode(errcode, errno);
return (NULL);
}
/*
* Open .ind file.
*/
ind_fd = _open_indfile (isfname, rdonly);
/*
* Open .var file.
*/
var_fd = _open_varfile (isfname, rdonly);
/*
* Allocate File Control Block.
*/
fcb = (Fcb *) _ismalloc(sizeof(*fcb));
memset ((char *) fcb, 0, sizeof(*fcb));
fcb->isfname = _isallocstring(isfname);
fcb->rdonly = rdonly;
fcb->datfd = dat_fd;
fcb->indfd = ind_fd;
fcb->varfd = var_fd;
/* Key descriptor */
fcb->nkeys = 1;
fcb->keys = (Keydesc2 *) _ismalloc(sizeof(fcb->keys[0]));
memset((char *)fcb->keys, 0, sizeof(fcb->keys[0]));
return (fcb);
}
/*
* _isfcb_nfds(fcb)
*
* Return the number of UNIX fd consumed by the fcb block.
*/
int
_isfcb_nfds(fcb)
register Fcb *fcb;
{
register int count = 0;
if (fcb->datfd != -1)
count++;
if (fcb->indfd != -1)
count++;
if (fcb->varfd != -1)
count++;
return (count);
}
/*
* _isfcb_remove(fcb)
*
* Remove UNIX files associated with an FCB.
*/
void
_isfcb_remove(fcb)
register Fcb *fcb;
{
if (fcb->datfd)
_remove_datfile(fcb->isfname);
if (fcb->indfd)
_remove_indfile(fcb->isfname);
if (fcb->varfd)
_remove_varfile(fcb->isfname);
}
/*
* _isfcb_close(fcb)
*
* Close UNIX files associated with an FCB, deallocate the FCB block.
*/
void
_isfcb_close(fcb)
register Fcb *fcb;
{
assert (fcb != NULL);
assert (fcb->isfname != NULL);
(void) close(fcb->datfd);
(void) close(fcb->indfd);
(void) close(fcb->varfd);
_isfreestring(fcb->isfname);
free((char *)fcb->keys);
free((char *)fcb);
}
/*
* _isfcb_cntlpg_w(fcb)
*
* Write information from the control block to the disk.
* Note that the Control Page transfer bypasses the disk buffer manager.
*
* Return 0 if write was successful, return -1 if any error.
*/
int
_isfcb_cntlpg_w(fcb)
register Fcb *fcb;
{
char cntl_page[ISCNTLSIZE];
int dat_fd = fcb->datfd;
int i;
/* Clear the page. */
memset (cntl_page, 0, sizeof(cntl_page));
/* Set Magic number. */
(void)strcpy(cntl_page + CP_MAGIC_OFF, ISMAGIC);
/* Set Block size */
stshort(ISPAGESIZE, cntl_page + CP_BLOCKSIZE_OFF);
/* Set NetISAM version stamp. */
(void)strcpy(cntl_page + CP_VERSION_OFF, ISVERSION);
/* .rec file size in blocks. */
stlong((long)fcb->datsize, cntl_page + CP_DATSIZE_OFF);
/* .ind file size in blocks. */
stlong((long)fcb->indsize, cntl_page + CP_INDSIZE_OFF);
/* .var file size in blocks. */
stlong((long)fcb->varsize, cntl_page + CP_VARSIZE_OFF);
/* Variable length 0/1 flag. */
stshort((short)fcb->varflag, cntl_page + CP_VARFLAG_OFF);
/* Number of records. */
stlong((long)fcb->nrecords, cntl_page + CP_NRECORDS_OFF);
/* Minimum and maximum record length. */
stshort((short)fcb->minreclen, cntl_page + CP_MINRECLEN_OFF);
stshort((short)fcb->maxreclen, cntl_page + CP_MAXRECLEN_OFF);
/* Last record number. */
strecno(fcb->lastrecno, cntl_page + CP_LASTRECNO_OFF);
/* Free record number. */
strecno(fcb->freerecno, cntl_page + CP_FREERECNO_OFF);
/* Number of keys */
stshort((short)fcb->nkeys, cntl_page + CP_NKEYS_OFF);
/* Last key id */
stlong((long)fcb->lastkeyid, cntl_page + CP_LASTKEYID_OFF);
/* ind. free list head */
stlong((long)fcb->indfreelist, cntl_page + CP_INDFREELIST_OFF);
/* offset of the end of .var file */
stlong((long)fcb->varend, cntl_page + CP_VAREND_OFF);
/* Key descriptors. */
for (i = 0; i < fcb->nkeys; i++) {
stkey(fcb->keys + i, cntl_page + CP_KEYS_OFF + i * K2_LEN);
}
/* Increment stamp1 and stamp2 to indicate change in the Control Page. */
fcb->changestamp1++;
fcb->changestamp2++;
stlong((long)fcb->changestamp1, cntl_page + CP_CHANGESTAMP1_OFF);
stlong((long)fcb->changestamp2, cntl_page + CP_CHANGESTAMP2_OFF);
/*
* Write the buffer to the disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
_iswritepg(dat_fd, cntl_page);
_iswritepg(dat_fd, cntl_page + ISPAGESIZE);
return (ISOK);
}
/*
* _isfcb_cntlpg_w2(fcb)
*
* Write information from the control block to the disk.
* Write only selected fields of the control block to avoid the overhead
* of coding and decoding.
* Note that the Control Page transfer bypasses the disk buffer manager.
*
* Return 0 if write was successful, return -1 if any error.
*/
int
_isfcb_cntlpg_w2(fcb)
register Fcb *fcb;
{
char cntl_page[CP_VAREND_OFF+CP_VAREND_LEN];
int dat_fd = fcb->datfd;
/*
* Read the page from disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
(void)read(dat_fd, cntl_page, sizeof(cntl_page));
/* .rec file size in blocks. */
stlong((long)fcb->datsize, cntl_page + CP_DATSIZE_OFF);
/* .ind file size in blocks. */
stlong((long)fcb->indsize, cntl_page + CP_INDSIZE_OFF);
/* .var file size in blocks. */
stlong((long)fcb->varsize, cntl_page + CP_VARSIZE_OFF);
/* Number of records. */
stlong((long)fcb->nrecords, cntl_page + CP_NRECORDS_OFF);
/* Last record number. */
strecno(fcb->lastrecno, cntl_page + CP_LASTRECNO_OFF);
/* Free record number. */
strecno(fcb->freerecno, cntl_page + CP_FREERECNO_OFF);
/* ind. free list head */
stlong((long)fcb->indfreelist, cntl_page + CP_INDFREELIST_OFF);
/* end of .var file */
stlong((long)fcb->varend, cntl_page + CP_VAREND_OFF);
/* Increment stamp2 to indicate change in the Control Page. */
fcb->changestamp2++;
stlong((long)fcb->changestamp2, cntl_page + CP_CHANGESTAMP2_OFF);
/*
* Write the buffer to the disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
(void)write(dat_fd, cntl_page, sizeof(cntl_page));
return (ISOK);
}
/*
* _isfcb_cntlpg_r(fcb)
*
* Read information from control page and store it in the FCB.
* Note that the Control Page transfer bypasses the disk buffer manager.
*
* Return 0 if read was successful, return -1 if any error.
*/
int
_isfcb_cntlpg_r(fcb)
register Fcb *fcb;
{
char cntl_page[ISCNTLSIZE];
int dat_fd = fcb->datfd;
int i;
/*
* Read the page from the disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
_isreadpg(dat_fd, cntl_page);
_isreadpg(dat_fd, cntl_page + ISPAGESIZE);
/* block size */
fcb->blocksize = ldshort(cntl_page + CP_BLOCKSIZE_OFF);
/* .rec file size in blocks. */
fcb->datsize = ldlong(cntl_page + CP_DATSIZE_OFF);
/* .ind file size in blocks. */
fcb->indsize = ldlong(cntl_page + CP_INDSIZE_OFF);
/* .var file size in blocks. */
fcb->varsize = ldlong(cntl_page + CP_VARSIZE_OFF);
/* Variable length 0/1 flag. */
fcb->varflag = (Bool)ldshort(cntl_page + CP_VARFLAG_OFF);
/* Number of records. */
fcb->nrecords = ldlong(cntl_page + CP_NRECORDS_OFF);
/* Minimum and maximum record length. */
fcb->minreclen = ldunshort(cntl_page + CP_MINRECLEN_OFF);
fcb->maxreclen = ldunshort(cntl_page + CP_MAXRECLEN_OFF);
/* Last record number. */
fcb->lastrecno = ldrecno(cntl_page + CP_LASTRECNO_OFF);
/* Free record number. */
fcb->freerecno = ldrecno(cntl_page + CP_FREERECNO_OFF);
/* Last key id */
fcb->lastkeyid = ldlong(cntl_page + CP_LASTKEYID_OFF);
/* .ind free list head. */
fcb->indfreelist = ldlong(cntl_page + CP_INDFREELIST_OFF);
/* end of .var file */
fcb->varend = ldlong(cntl_page + CP_VAREND_OFF);
/* Number of keys */
fcb->nkeys = ldshort(cntl_page + CP_NKEYS_OFF);
/*
* Read key descriptors.
*/
fcb->keys = (Keydesc2 *)
_isrealloc((char *)fcb->keys,
(unsigned) (sizeof(Keydesc2) * fcb->nkeys));
memset((char *)fcb->keys, 0, sizeof(Keydesc2) * fcb->nkeys);
for (i = 0; i < fcb->nkeys; i++) {
ldkey(fcb->keys + i, cntl_page + CP_KEYS_OFF + i * K2_LEN);
}
/* Changestamp1 */
fcb->changestamp1 = ldlong(cntl_page + CP_CHANGESTAMP1_OFF);
/* Changestamp2 */
fcb->changestamp2 = ldlong(cntl_page + CP_CHANGESTAMP2_OFF);
/*
* Open .ind file in situations when some other process has created
* keys and this process has just learned it now.
*/
if (fcb->nkeys > 1 || !FCB_NOPRIMARY_KEY(fcb)) {
/*
if (_open2_indfile(fcb) != ISOK)
_isfatal_error("_open2_indfile()");
*/
(void)_open2_indfile(fcb);
}
return (ISOK);
}
/*
* _isfcb_cntlpg_r2(fcb)
*
* Read information from the control block on the disk.
* Read only selected fields of the control block to avoid the overhead
* of coding and decoding.
* Note that the Control Page transfer bypasses the disk buffer manager.
*
* Return 0 if write was successful, return -1 if any error.
*/
int
_isfcb_cntlpg_r2(fcb)
register Fcb *fcb;
{
char cntl_page[CP_VAREND_OFF+CP_VAREND_LEN];
int dat_fd = fcb->datfd;
/*
* Read the page from disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
(void)read(dat_fd, cntl_page, sizeof(cntl_page));
/*
* Check changestamp1. If the stamp has changed, we must read the entire
* page and update the FCB.
*/
if (ldlong(cntl_page + CP_CHANGESTAMP1_OFF) != fcb->changestamp1) {
(void)_isfcb_cntlpg_r(fcb);
}
/*
*_isfcb_cntlpg_r2() is called if transaction is rolled back.
* We cannot test changestamp2; we must read the info into the FCB
* always.
*/
#if 0
/*
* Check changestamp2. If the stamp has not changed, the FCB contains
* up-to-date information.
*/
if (ldlong(cntl_page + CP_CHANGESTAMP2_OFF) == fcb->changestamp2) {
return (ISOK);
}
#endif
/* .rec file size in blocks. */
fcb->datsize = ldlong(cntl_page + CP_DATSIZE_OFF);
/* .ind file size in blocks. */
fcb->indsize = ldlong(cntl_page + CP_INDSIZE_OFF);
/* .var file size in blocks. */
fcb->varsize = ldlong(cntl_page + CP_VARSIZE_OFF);
/* Number of records. */
fcb->nrecords = ldlong(cntl_page + CP_NRECORDS_OFF);
/* Last record number. */
fcb->lastrecno = ldrecno(cntl_page + CP_LASTRECNO_OFF);
/* Free record number. */
fcb->freerecno = ldrecno(cntl_page + CP_FREERECNO_OFF);
/* .ind free list head. */
fcb->indfreelist = ldlong(cntl_page + CP_INDFREELIST_OFF);
/* end of .var file */
fcb->varend = ldlong(cntl_page + CP_VAREND_OFF);
/* Changestamp2 */
fcb->changestamp2 = ldlong(cntl_page + CP_CHANGESTAMP2_OFF);
return (ISOK);
}
/*
* _create_datfile(isfname)
*
* Create .rec file for ISAM file isfname.
*/
Static int
_create_datfile(isfname)
char *isfname;
{
int fd;
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makedat_isfname(namebuf);
fd = open (namebuf, O_CREAT | O_EXCL | O_RDWR, 0666);
if (fd > -1) {
fcntl(fd, F_SETFD, 1); /* Close on exec */
}
return (fd);
}
/*
* _create_indfile(isfname)
*
* Create .ind file for ISAM file isfname.
*/
Static int
_create_indfile(isfname)
char *isfname;
{
int fd;
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makeind_isfname(namebuf);
fd = open (namebuf, O_CREAT | O_EXCL | O_RDWR, 0666);
if (fd > -1) {
fcntl(fd, F_SETFD, 1); /* Close on exec */
}
return (fd);
}
/*
* _create_varfile(isfname)
*
* Create .var file for ISAM file isfname.
*/
Static int
_create_varfile(isfname)
char *isfname;
{
int fd;
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makevar_isfname(namebuf);
fd = open (namebuf, O_CREAT | O_EXCL | O_RDWR, 0666);
if (fd > -1) {
fcntl(fd, F_SETFD, 1); /* Close on exec */
}
return (fd);
}
/*
* _remove_datfile(isfname)
*
* Remove .rec file for ISAM file isfname.
*/
Static void
_remove_datfile(isfname)
char *isfname;
{
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makedat_isfname(namebuf);
(void) unlink(namebuf);
}
/*
* _remove_indfile(isfname)
*
* Remove .ind file for ISAM file isfname.
*/
Static void
_remove_indfile(isfname)
char *isfname;
{
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makeind_isfname(namebuf);
(void) unlink(namebuf);
}
/*
* _remove_varfile(isfname)
*
* Remove .var file for ISAM file isfname.
*/
Static void
_remove_varfile(isfname)
char *isfname;
{
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makevar_isfname(namebuf);
(void) unlink(namebuf);
}
/*
* _open_datfile(isfname)
*
* Open .rec file for ISAM file isfname.
*/
Static int
_open_datfile(isfname, rdonly)
char *isfname;
Bool *rdonly;
{
char namebuf[MAXPATHLEN];
int ret;
(void) strcpy(namebuf, isfname);
_makedat_isfname(namebuf);
if ((ret = open (namebuf, O_RDWR)) != -1) {
*rdonly = FALSE;
fcntl(ret, F_SETFD, 1); /* Close on exec */
return (ret);
}
*rdonly = TRUE;
ret = open (namebuf, O_RDONLY);
if (ret > -1) {
fcntl(ret, F_SETFD, 1); /* Close on exec */
}
return (ret);
}
/*
* _open_indfile(isfname)
*
* Open .ind file for ISAM file isfname.
*/
Static int
_open_indfile(isfname, rdonly)
char *isfname;
Bool rdonly;
{
int fd;
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makeind_isfname(namebuf);
fd = open (namebuf, (rdonly==TRUE)?O_RDONLY:O_RDWR);
if (fd > -1) {
fcntl(fd, F_SETFD, 1); /* Close on exec */
}
return (fd);
}
/*
* _open_varfile(isfname)
*
* Open .var file for ISAM file isfname.
*/
Static int
_open_varfile(isfname, rdonly)
char *isfname;
Bool rdonly;
{
int fd;
char namebuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
_makevar_isfname(namebuf);
fd = open (namebuf, (rdonly==TRUE)?O_RDONLY:O_RDWR);
if (fd > -1) {
fcntl(fd, F_SETFD, 1); /* Close on exec */
}
return (fd);
}
int
_check_isam_magic(fcb)
Fcb *fcb;
{
char magicbuffer[CP_MAGIC_LEN];
(void)lseek(fcb->datfd, 0L, 0);
if (read(fcb->datfd, magicbuffer, CP_MAGIC_LEN) < CP_MAGIC_LEN ||
/* The following test for compatibilty with `SunISAM 1.0 Beta files. */
strncmp(magicbuffer, "SunISAM", strlen(ISMAGIC)) != 0 &&
strncmp(magicbuffer, ISMAGIC, strlen(ISMAGIC)) != 0) {
return ISERROR;
}
else
return ISOK;
}
/*
* _open2_indfile(fcb)
*
* Open (or create) .ind file for ISAM file if the .ind file
* is not open already (or does not exist).
*/
int
_open2_indfile(fcb)
Fcb *fcb;
{
char namebuf[MAXPATHLEN];
struct stat buf;
int openmode;
if (fcb->indfd != -1)
return (ISOK);
(void) strcpy(namebuf, fcb->isfname);
_makeind_isfname(namebuf);
(void)fstat(fcb->datfd, &buf);
openmode = (fcb->rdonly) ? O_RDONLY : O_RDWR;
if (fcb->indsize == 0)
openmode |= O_CREAT;
fcb->indfd = open(namebuf, openmode, buf.st_mode);
if (fcb->indfd > -1) {
fcntl(fcb->indfd, F_SETFD, 1); /* Close on exec */
}
if(fcb->indfd == -1 && (openmode & O_CREAT)) {
_isfatal_error("Cannot create .ind file");
}
if (fcb->indfd != -1) {
(void) _watchfd_incr(1);
(void)fchown(fcb->indfd, buf.st_uid, buf.st_gid);
}
return ((fcb->indfd == -1) ? ISERROR : ISOK);
}

View File

@@ -0,0 +1,219 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isfcbindex.c /main/3 1995/10/23 11:38:43 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isfcbindex.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfcbindex.c
*
* Description:
* Functions that deal with the key descriptors in FCB
*
*
*/
#include "isam_impl.h"
Static int _keypart2cmp();
/*
* _isfcb_primkeyadd(fcb, keydesc2)
*
* Add priamry key descriptor to FCB.
*
*/
int
_isfcb_primkeyadd(fcb, keydesc2)
Fcb *fcb;
Keydesc2 *keydesc2;
{
/*
* Assign keyid.
*/
keydesc2->k2_keyid = ++fcb->lastkeyid;
fcb->keys[0] = *keydesc2;
return (ISOK);
}
/*
* _isfcb_primkeyel(fcb)
*
* Delete primary key
*
*/
int
_isfcb_primkeydel(fcb)
Fcb *fcb;
{
if (FCB_NOPRIMARY_KEY(fcb))
return (EBADARG);
memset((char *)&fcb->keys[0], 0, sizeof(fcb->keys[0]));
return (ISOK);
}
/*
* _isfcb_altkeyadd(fcb, keydesc2)
*
* Add alternate key descriptor to FCB.
*
*/
int
_isfcb_altkeyadd(fcb, keydesc2)
Fcb *fcb;
Keydesc2 *keydesc2;
{
assert (fcb->nkeys < MAXNKEYS);
/*
* Assign keyid.
*/
keydesc2->k2_keyid = ++fcb->lastkeyid;
/*
* Reallocate fcb->keys table.
*/
fcb->keys = (Keydesc2 *)
_isrealloc((char *)fcb->keys,
(unsigned) (sizeof(Keydesc2) * (fcb->nkeys + 1)));
fcb->keys[fcb->nkeys] = *keydesc2;
fcb->nkeys++;
return (ISOK);
}
/*
* pkeydesc2 = _isfcb_findkey(fcb, keydesc2)
*
* Find key descriptor.
*
*/
Keydesc2 *
_isfcb_findkey(fcb, keydesc2)
register Fcb *fcb;
Keydesc2 *keydesc2;
{
int nkeys = fcb->nkeys;
register Keydesc2 *kp2;
register int j, i;
int nparts;
for (i = 0; i < nkeys; i++) {
kp2 = fcb->keys + i;
if (keydesc2->k2_nparts == kp2->k2_nparts) {
nparts = keydesc2->k2_nparts;
for (j = 0; j < nparts; j++) {
if (_keypart2cmp(keydesc2->k2_part + j, kp2->k2_part + j) != 0)
break;
}
if (j == nparts)
return (kp2);
}
}
return ((struct keydesc2 *) 0); /* Key descriptor not found */
}
/*
* pkeydesc2 = _isfcb_altkeydel(fcb, keydesc2)
*
* Delete key descriptor from FCB.
*
*/
int
_isfcb_altkeydel(fcb, keydesc2)
register Fcb *fcb;
Keydesc2 *keydesc2;
{
int nkeys = fcb->nkeys;
register int i, j;
register Keydesc2 *kp2;
int nparts;
for (i = 0; i < nkeys; i++) {
kp2 = fcb->keys + i;
if (keydesc2->k2_nparts == kp2->k2_nparts) {
nparts = keydesc2->k2_nparts;
for (j = 0; j < nparts; j++) {
if (_keypart2cmp(keydesc2->k2_part + j, kp2->k2_part + j) != 0)
break;
}
if (j == nparts)
break; /* Key found */
}
}
if (i >= nkeys)
return (EBADKEY); /* Key descriptor not found */
if (i == 0) {
return (EPRIMKEY); /* Cannot delete primary key */
}
/*
* Shift the end of the table toward the beginning to delete the entry.
*/
if (i < nkeys - 1) {
memcpy( (char *)(fcb->keys + i),(char *)(fcb->keys + i + 1),
(nkeys - 1 - i) * sizeof (fcb->keys[0]));
}
fcb->nkeys--;
return (ISOK);
}
/* compare key parts */
Static int
_keypart2cmp(l,r)
register struct keypart2 *l, *r;
{
return !(l->kp2_type == r->kp2_type && l->kp2_start == r->kp2_start &&
l->kp2_leng == r->kp2_leng);
}
/*
* pkeydesc2 = _isfcb_indfindkey(fcb, keyind)
*
* Find key descriptor by its keyind value.
*
*/
Keydesc2 *
_isfcb_indfindkey(fcb, keyid)
register Fcb *fcb;
int keyid;
{
int nkeys = fcb->nkeys;
register Keydesc2 *keys = fcb->keys;
register int i;
for (i = 0; i < nkeys; i++) {
if (keys[i].k2_keyid == keyid)
break;
}
return ((i == nkeys) ? NULL : keys + i);
}

View File

@@ -0,0 +1,127 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isfcbwatchfd.c /main/3 1995/10/23 11:38:51 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isfcbwatchfd.c 1.8 93/09/07 Copyr 1988-1993 Sun Microsystems, Inc";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfcbwatchfd.c
*
* Description:
* Watch the limit on UNIX file descriptors used by the FCB module.
*/
#if defined(_AIX)
#define _POSIX_SYSCONF
#endif
#if defined(_AIX)
#define _POSIX_SYSCONF
#endif
#include "isam_impl.h"
#include <sys/time.h>
#include <sys/resource.h>
#ifdef _POSIX_SYSCONF
#include <unistd.h>
#endif /* _POSIX_SYSCONF */
static int _limit = MAXFCB_UNIXFD; /* Imposed limit */
static int _in_use = 0; /* Current number of
* open file descriptors
*/
/*
* _watchfd_incr(n)
*
* Register that n additional UNIX file descriptors were open.
*
* Return the new number of open file descriptors.
*/
int
_watchfd_incr(n)
{
_in_use += n;
assert(_in_use <= _limit);
return (_in_use);
}
/*
* _watch_decr(n)
*
* Register that n open file descriptors were closed.
*
* Return the new number of open file descriptors.
*/
int
_watchfd_decr(n)
{
_in_use -= n;
assert(_in_use >= 0);
return (_in_use);
}
/*
* _watch_check()
*
* Return number of fd that are still available.
*/
int
_watchfd_check()
{
return (_limit - _in_use);
}
/*
* _watchfd_max_set(n)
*
* Set the maximum number of UNIX fds that may be comsumed by ISAM files.
*/
int
_watchfd_max_set(n)
int n;
{
int oldlimit = _limit;
#ifdef _POSIX_SYSCONF
if (n < 3 || n > sysconf(_SC_OPEN_MAX)) {
#else
int dtab_size = 0;
struct rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
dtab_size = rl.rlim_cur;
if (n < 3 || n > dtab_size) {
#endif
_setiserrno2(EBADARG, '9', '0');
return (ISERROR);
}
_limit = n;
return (oldlimit);
}
/*
* _watchfd_max_get()
*
* Get the maximum number of UNIX fds that may be comsumed by ISAM files.
*/
int
_watchfd_max_get()
{
return (_limit);
}

View File

@@ -0,0 +1,85 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isfd.c /main/3 1995/10/23 11:39:10 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isfd.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfd.c
*
* Description:
* The ISAM file descriptors (isfd) are used as index to a table of
* pointers to File Access Block objects. Isfd.c maintains the table
* of the pointers (isfdtab).
*
*/
#include "isam_impl.h"
static Fab *isfdtab[MAXISFD]; /* Table of pointers */
/*
* _isfd_insert(fab)
*
* Insert a pointer to an Fab object to table of ISAM file descriptors.
* Return an ISAM file descriptor, or NOISFD if the table is full.
*/
Isfd
_isfd_insert(fab)
Fab *fab;
{
register Isfd i;
for (i = 0; i < MAXISFD; i++) {
if (isfdtab[i] == NULL) /* Empty entry found */
break;
}
if (i == MAXISFD)
return (NOISFD); /* isfdtab is full */
isfdtab[i] = fab;
return (i);
}
/*
* _isfd_find(isfd)
*
* Return a pointer to Fab object associated with the ISAM file
* descriptor isfd. If isfd is not a file descriptor of an open ISAM file,
* return NULL.
*/
Fab *
_isfd_find(isfd)
register Isfd isfd;
{
if (isfd < 0 || isfd >= MAXISFD || isfdtab[isfd] == NULL)
return (NULL);
else
return (isfdtab[isfd]);
}
/*
* _isfd_delete(isfd)
*
* Delete an entry from isfdtab. No check is made the entry exists.
*/
void
_isfd_delete(isfd)
register Isfd isfd;
{
if (isfd >= 0 && isfd < MAXISFD)
isfdtab[isfd] = NULL;
}

View File

@@ -0,0 +1,156 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isfileio.c /main/3 1995/10/23 11:39:26 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isfileio.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfileio.c
*
* Description:
* I/O operations on UNIX files associated with FCB
*/
#include "isam_impl.h"
static int _getoffset();
static Blkno _getblkno();
/*
* _cp_tofile(fcb, unixfd, data, pos, len)
*
* Copy data to a file associated with FCB (unixfd distinguishes among
* .rec, .ind., and .var file). The data are copied from buffer data to
* the file at offset pos. The number of bytes to copy is in len.
*/
void
_cp_tofile(fcb, unixfd, data, pos, len)
Fcb *fcb;
int unixfd;
char *data;
long pos;
int len;
{
int offset; /* Offset within a page */
Blkno blkno;
Bufhdr *bufhdr;
int nbytes;
/*
* Data may span multiple blocks.
*/
while (len > 0) {
blkno = _getblkno(pos);
offset = _getoffset(pos);
nbytes = (len < ISPAGESIZE - offset) ? len : ISPAGESIZE - offset;
bufhdr = _isdisk_fix(fcb, unixfd, blkno, ISFIXWRITE);
memcpy( bufhdr->isb_buffer + offset,data, nbytes);
_isdisk_unfix(bufhdr);
pos += nbytes;
data += nbytes;
len -= nbytes;
}
}
/*
* _cp_fromfile(fcb, unixfd, data, pos, len)
*
* Copy data from a file associated with FCB (unixfd distinguishes among
* .rec, .ind., and .var file). The data are copied to buffer data from
* the file at offset pos. The number of bytes to copy is in len.
*/
void
_cp_fromfile(fcb, unixfd, data, pos, len)
Fcb *fcb;
int unixfd;
char *data;
long pos;
int len;
{
int offset; /* Offset within a page */
Blkno blkno;
Bufhdr *bufhdr;
int nbytes;
/*
* Data may span multiple blocks.
*/
while (len > 0) {
blkno = _getblkno(pos);
offset = _getoffset(pos);
nbytes = (len < ISPAGESIZE - offset) ? len : ISPAGESIZE - offset;
bufhdr = _isdisk_fix(fcb, unixfd, blkno, ISFIXREAD);
memcpy( data,bufhdr->isb_buffer + offset, nbytes);
_isdisk_unfix(bufhdr);
pos += nbytes;
data += nbytes;
len -= nbytes;
}
}
/*
* extend_file(fcb, unixfd, oldsize)
*
* Extend UNIX file by one block.
*/
Blkno
_extend_file(fcb, unixfd, oldsize)
Fcb *fcb;
int unixfd;
Blkno oldsize;
{
Bufhdr *bufhdr;
char buf[ISPAGESIZE];
/*
* We must write something to the buffer, or we will get
* segmentation fault when using mapped I/O.
*/
_isseekpg(unixfd, oldsize);
_iswritepg(unixfd, buf);
bufhdr = _isdisk_fix(fcb, unixfd, oldsize, ISFIXNOREAD);
_isdisk_unfix(bufhdr);
return (oldsize + 1);
}
/*
* off = _getoffset(pos)
*
* Calculate offset relative to the beginning of page
*/
Static int
_getoffset(pos)
long pos;
{
return ((int)(pos % ISPAGESIZE));
}
/*
* blkno = _getblkno(pos)
*
* Calculate block number of the block containing position pos.
*/
Static Blkno
_getblkno(pos)
long pos;
{
return ((int)(pos / ISPAGESIZE));
}

View File

@@ -0,0 +1,397 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isfixrec.c /main/3 1995/10/23 11:39:42 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isfixrec.c 1.5 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfixrec.c
*
* Description:
* Fixed length record access (FLRA) module.
*/
#include "isam_impl.h"
/* Local functions */
long _fl_getpos(); /* Get offset in .rec file */
int _fl_deleted(); /* 0/1 returns 1 if record is deleted */
static void remove_from_chain(); /* used by _flrec_wrrec() */
/*
* _flrec_write(fcb, record, recnum, reclen)
*
* Write a record.
*
* Input params:
* FCB File Control Block
* record record buffer
* reclen record length (NOT USED)
*
* Output params:
* recnum record number of the new record
*
* Returns 0 if record was written succesfully, or -1 if any error.
*/
/*ARGSUSED*/
int
_flrec_write(fcb, record, recnum, reclen)
register Fcb *fcb;
char *record;
Recno *recnum;
int reclen;
{
Recno recnum2;
long rec_position;
char delflag = FL_RECEXISTS;
char recnobuf [RECNOSIZE];
/*
* Reuse a deleted record if one exits.
* Otherwise, extend .rec file by a record.
*/
if (fcb->freerecno != NULL_RECNO) {
recnum2 = fcb->freerecno;
/*
* Remove record from the chain of deleted records.
*/
rec_position = _fl_getpos(fcb, recnum2); /* Offset in .rec file */
_cp_fromfile(fcb, fcb->datfd, recnobuf, rec_position + 1, RECNOSIZE);
fcb->freerecno = ldrecno(recnobuf);
}
else {
recnum2 = ++(fcb->lastrecno);
/*
* Extend .rec file size if necessary.
*/
while (_fl_getpos(fcb, recnum2 + 1) > fcb->datsize * ISPAGESIZE) {
fcb->datsize = _extend_file(fcb, fcb->datfd, fcb->datsize);
}
rec_position = _fl_getpos(fcb, recnum2); /* Offset in .rec file */
}
/*
* Copy record to the .at file. Mark record as undeleted.
*/
_cp_tofile(fcb, fcb->datfd, &delflag, rec_position, 1);
_cp_tofile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen);
*recnum = recnum2;
return (ISOK);
}
/*
* _flrec_read(fcb, record, recnum, reclen)
*
* Read a record.
*
* Input params:
* FCB File Control Block
* recnum record number of the record
* reclen filled with the record size for compatibilty with
* variable length records
*
* Output params:
* record record buffer is filled with data
*
* Returns 0 if record was read succesfully, or error code if any error.
*/
int
_flrec_read(fcb, record, recnum, reclen)
register Fcb *fcb;
char *record;
Recno recnum;
int *reclen;
{
long rec_position;
char delflag;
/*
* Check that recnum is within the range of existing record numbers.
*/
if (recnum < 1 || recnum > fcb->lastrecno)
return (EENDFILE);
rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
/*
* Check that the record is not marked as deleted.
*/
_cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1);
if (delflag == FL_RECDELETED) {
return (ENOREC);
}
/*
* Copy record from the .at file.
*/
_cp_fromfile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen);
*reclen = fcb->minreclen;
return (ISOK);
}
/*
* pos = _fl_getpos(fcb, recnum)
*
* Calculate the position of record in .rec file.
*/
long
_fl_getpos(fcb, recnum)
Fcb *fcb;
Recno recnum;
{
return ((long)(ISCNTLSIZE + (fcb->minreclen + 1) * (recnum -1)));
}
/*
* _flrec_rewrite(fcb, record, recnum, reclen)
*
* Rewrite a record.
*
* Input params:
* FCB File Control Block
* recnum record number of the record
* record new record
* int reclen (NOT USED)
*
* Returns 0 if record was rewritten succesfully, or error code if any error.
*/
/*ARGSUSED*/
int
_flrec_rewrite(fcb, record, recnum, reclen)
register Fcb *fcb;
char *record;
Recno recnum;
int reclen;
{
long rec_position;
char delflag;
/*
* Check that recnum is within the range of existing record numbers.
*/
if (recnum < 1 || recnum > fcb->lastrecno)
return (EENDFILE);
rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
/*
* Check that the record is not marked as deleted.
*/
_cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1);
if (delflag == FL_RECDELETED) {
return (ENOREC);
}
/*
* Copy new record to the .rec file.
*/
_cp_tofile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen);
return (ISOK);
}
/*
* _flrec_delete(fcb, recnum)
*
* Rewrite a record.
*
* Input params:
* FCB File Control Block
* recnum record number of the record
*
* Returns 0 if record was rewritten succesfully, or error code if any error.
*/
int
_flrec_delete(fcb, recnum)
register Fcb *fcb;
Recno recnum;
{
long rec_position;
char delflag;
char recnobuf [RECNOSIZE];
/*
* Check that recnum is within the range of existing record numbers.
*/
if (recnum < 1 || recnum > fcb->lastrecno)
return (EENDFILE);
rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
/*
* Check that the record is not marked as deleted.
*/
_cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1);
if (delflag == FL_RECDELETED) {
return (ENOREC);
}
/*
* Set the delete flag to FL_RECDELETED.
*/
delflag = FL_RECDELETED;
_cp_tofile(fcb, fcb->datfd, &delflag, rec_position, 1);
/*
* Insert record into chain of deleted records.
*/
strecno(fcb->freerecno, recnobuf);
_cp_tofile(fcb, fcb->datfd, recnobuf, rec_position + 1, RECNOSIZE);
fcb->freerecno = recnum;
return (ISOK);
}
/*
* _flrec_wrrec(fcb, record, recnum, reclen)
*
* Write a record by record number.
*
* Input params:
* FCB File Control Block
* recnum record number of the record
* record record buffer
* int reclen (NOT USED)
*
* Returns 0 if record was written succesfully, or error code if any error.
*
* Note that _flrec_wrrec() commits updates and syncs the FCB to avoid
* buffer pool overflow.
*/
/*ARGSUSED*/
int
_flrec_wrrec(fcb, record, recnum, reclen)
register Fcb *fcb;
char *record;
Recno recnum;
int reclen;
{
long rec_position;
char delflag;
Recno recnum2;
char recnumbuf [RECNOSIZE];
/*
* Check that recnum is not negative.
*/
if (recnum < 1)
return (EBADARG);
rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
if (recnum > fcb->lastrecno) {
/*
* If the recnum is bigger than the highest record number in the .rec
* file, extend the .rec file.
*/
while (_fl_getpos(fcb, recnum + 1) > fcb->datsize * ISPAGESIZE) {
fcb->datsize = _extend_file(fcb, fcb->datfd, fcb->datsize);
/* Sync the updates to avoid buffer pool overflow. */
_isdisk_commit();
_isdisk_sync();
(void)_isfcb_cntlpg_w2(fcb);
}
/*
* Mark all records in the range <fcb->lastrecno+1, recnum> as
* deleted.
*/
delflag = FL_RECDELETED;
for (recnum2 = fcb->lastrecno + 1; recnum2 <= recnum; recnum2++) {
_cp_tofile(fcb, fcb->datfd, &delflag, _fl_getpos(fcb, recnum2), 1);
strecno(fcb->freerecno, recnumbuf);
_cp_tofile(fcb, fcb->datfd, recnumbuf,
_fl_getpos(fcb, recnum2) + 1, RECNOSIZE);
fcb->freerecno = recnum2;
/* Sync the updates to avoid buffer pool overflow. */
_isdisk_commit();
_isdisk_sync();
fcb->lastrecno = recnum;
(void)_isfcb_cntlpg_w2(fcb);
}
/*
* Note that the disk structures are in a consistent state now,
* the .rec was extended by a few records marked as 'deleted'.
* This is important for subsequent rollbacks.
*/
}
/*
* If recnum specifies a record that has existed, check whether it
* has been deleted. _flrec_wrrec() does not override existing record.
*/
_cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1);
if (delflag == FL_RECEXISTS) {
return (EDUPL);
}
/*
* Remove the record from the chain of deleted records.
*/
remove_from_chain(fcb, recnum);
/*
* Copy new record to the .rec file.
*/
delflag = FL_RECEXISTS;
_cp_tofile(fcb, fcb->datfd, &delflag, rec_position, 1);
_cp_tofile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen);
return (ISOK);
}
/*
* remvoe_from_chain(fcb, recnum)
*
* Remove record from the chain of deleted records.
*/
static void
remove_from_chain(fcb, recnum)
Fcb *fcb;
Recno recnum;
{
char recnobuf1 [RECNOSIZE] , recnobuf2 [RECNOSIZE];
long pos1, pos2;
Recno recnum2;
pos1 = _fl_getpos(fcb, recnum);
_cp_fromfile(fcb, fcb->datfd, recnobuf1, pos1 + 1, RECNOSIZE);
if (fcb->freerecno == recnum) {
fcb->freerecno = ldrecno(recnobuf1);
}
else {
recnum2 = fcb->freerecno;
do {
pos2 = _fl_getpos(fcb, recnum2);
_cp_fromfile(fcb, fcb->datfd, recnobuf2, pos2 + 1, RECNOSIZE);
recnum2 = ldrecno(recnobuf2);
} while (recnum2 != recnum && recnum2 != NULL_RECNO);
_cp_tofile(fcb, fcb->datfd, recnobuf1, pos2 + 1, RECNOSIZE);
}
}

View File

@@ -0,0 +1,108 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isfname.c /main/3 1995/10/23 11:40:04 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isfname.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfname.c
*
* Description:
* Functions to translate ISAM file name to .rec, .ind, and .var file
* names. Also, several auxiliary functions that deal with path names.
*
*/
#include "isam_impl.h"
void _removelast();
char *_lastelement();
/*
* _makedat_isfname(isfname)
*
* Return path to .rec file corresponding to the ISAM file isfname.
* Conversion is done in place.
*/
void
_makedat_isfname(isfname)
char *isfname;
{
/* Append .rec */
(void) strcat(isfname, DAT_SUFFIX);
}
/*
* _makeind_isfname(isfname)
*
* Return path to .ind file corresponding to the ISAM file isfname.
* Conversion is done in place.
*/
void
_makeind_isfname(isfname)
char *isfname;
{
/* Append .ind */
(void) strcat(isfname, IND_SUFFIX);
}
/*
* _makevar_isfname(isfname)
*
* Return path to .var file corresponding to the ISAM file isfname.
* Conversion is done in place.
*/
void
_makevar_isfname(isfname)
char *isfname;
{
/* Append .var */
(void) strcat(isfname, VAR_SUFFIX);
}
/*
* _removelast(path)
*
* Remove last element of path. E.g. /usr/db/part yields /usr/db.
*/
void
_removelast(path)
char *path;
{
register char *p;
for (p = path + strlen(path); *--p != '/' && p >= path; )
*p = '\0';
}
/*
* _lastelement(path)
*
* Return pointer to the last element in the path.
* E.g.: _lastelement("/usr/temp") returns "temp".
*/
char *
_lastelement(path)
char *path;
{
register char *p;
p = path + strlen(path);
while (*--p != '/' && p > path)
{ ; }
return ((*p == '/') ? (p + 1) : p);
}

View File

@@ -0,0 +1,105 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: isgarbage.c /main/5 1998/04/10 08:04:25 mgreess $ */
#include "isam_impl.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
int
isgarbage(char * isfname)
{
char isfname2[MAXPATHLEN];
int isfd = -1, isfd2 = -1;
char buffer[ISMAXRECLEN];
char *recbuf;
struct dictinfo info;
struct keydesc keybuf;
struct stat statbuf;
int count = 0,i;
(void)strcpy(isfname2, isfname);
(void)strcat(isfname2, "~");
if ((isfd = isopen(isfname, ISEXCLLOCK + ISINPUT)) == ISERROR) {
goto ERROR;
}
if (isindexinfo(isfd, (struct keydesc *)&info, 0) == ISERROR) {
goto ERROR;
}
if (strlen(isfname) + 5 >= ISMAXRECLEN)
recbuf = (char*) malloc(strlen(isfname) + 5);
else
recbuf = buffer;
sprintf(recbuf, "%s.rec", isfname);
if (stat(recbuf, &statbuf) < 0) {
goto ERROR;
}
iserase(isfname2); /* Delete any old backup (~) files. */
if ((isfd2 = isbuild(isfname2, info.di_recsize, nokey,
(DICTVARLENBIT&info.di_nkeys?ISVARLEN: ISFIXLEN)
+ ISEXCLLOCK + ISINOUT)) == ISERROR) {
goto ERROR;
}
/* Copy all records */
while (isread(isfd, recbuf, ISNEXT) == ISOK) {
iswrite(isfd2, recbuf);
count++;
}
if (count != info.di_nrecords) {
goto ERROR;
}
/* Build all indexes from index info */
for (i = 1; i <= (info.di_nkeys & DICTNKEYSMASK); i++) {
if (isindexinfo(isfd, &keybuf, i) == ISERROR) {
goto ERROR;
}
if (i == 1 && keybuf.k_nparts != 0) {
/* Add primary index */
if (isaddprimary(isfd2, &keybuf) == ISERROR) {
goto ERROR;
}
}
else if (i > 1) {
/* Add secondary index */
if (isaddindex(isfd2, &keybuf) == ISERROR) {
goto ERROR;
}
}
}
(void)isclose(isfd);
(void)isclose(isfd2);
iserase(isfname); /* cannot abort at this point ! */
if (isrename(isfname2, isfname) == ISERROR) {
return (ISERROR);
}
return (ISOK);
ERROR:
if (isfd != -1)
(void)isclose(isfd);
if (isfd2 != -1) {
(void)isclose(isfd2);
(void)iserase(isfname2);
}
if (recbuf != buffer) free(recbuf);
return (ISERROR);
}

View File

@@ -0,0 +1,101 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isindexconv.c /main/3 1995/10/23 11:40:48 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isindexconv.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isindexconv.c
*
* Description:
* Encode/decode key descriptor
*/
#include "isam_impl.h"
void
stkey(pkeydesc2, p)
Keydesc2 *pkeydesc2;
char *p;
{
int i;
register struct keypart2 *ppart;
register char *pp;
int nparts;
stshort(pkeydesc2->k2_flags, p + K2_FLAGS_OFF);
stshort(pkeydesc2->k2_nparts, p + K2_NPARTS_OFF);
stshort(pkeydesc2->k2_len, p + K2_LEN_OFF);
stblkno(pkeydesc2->k2_rootnode, p + K2_ROOT_OFF);
stlong((long)pkeydesc2->k2_keyid, p + K2_KEYID_OFF);
ppart = pkeydesc2->k2_part;
pp = p + K2_KEYPART_OFF;
nparts = pkeydesc2->k2_nparts + 1; /* +1 for recno part */
if (ALLOWS_DUPS2(pkeydesc2)) /* +1 for dups serial number*/
nparts++;
for (i = 0; i < nparts;i++) {
stshort(ppart->kp2_start, pp);
pp += SHORTSIZE;
stshort(ppart->kp2_leng, pp);
pp += SHORTSIZE;
stshort(ppart->kp2_type, pp);
pp += SHORTSIZE;
stshort(ppart->kp2_offset, pp);
pp += SHORTSIZE;
ppart++;
}
}
void
ldkey(pkeydesc2,p)
register struct keydesc2 *pkeydesc2;
register char *p;
{
int i;
register struct keypart2 *ppart;
register char *pp;
int nparts;
memset ((char *) pkeydesc2, 0, sizeof (*pkeydesc2));
pkeydesc2->k2_flags = ldshort(p + K2_FLAGS_OFF);
pkeydesc2->k2_nparts = ldshort(p + K2_NPARTS_OFF);
pkeydesc2->k2_len = ldshort(p + K2_LEN_OFF);
pkeydesc2->k2_rootnode = ldblkno(p + K2_ROOT_OFF);
pkeydesc2->k2_keyid = ldlong(p + K2_KEYID_OFF);
ppart = pkeydesc2->k2_part;
pp = p + K2_KEYPART_OFF;
nparts = pkeydesc2->k2_nparts + 1; /* +1 for recno part */
if (ALLOWS_DUPS2(pkeydesc2)) /* +1 for dups serial number*/
nparts++;
for (i = 0; i < nparts;i++) {
ppart->kp2_start = ldunshort(pp);
pp += SHORTSIZE;
ppart->kp2_leng = ldshort(pp);
pp += SHORTSIZE;
ppart->kp2_type = ldshort(pp);
pp += SHORTSIZE;
ppart->kp2_offset = ldunshort(pp);
pp += SHORTSIZE;
ppart++;
}
}

View File

@@ -0,0 +1,154 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isindexinfo.c /main/3 1995/10/23 11:40:56 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isindexinfo.c 1.2 91/05/16 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isindexinfo.c
*
* Description:
* Access file status information
*/
#include "isam_impl.h"
#include <sys/time.h>
#define ZERO 0
/*
* err = isindexinfo(isfd, buffer, number)
*
* Return information about index.
* Return information about the data file (if number == 0).
*
* (this function is overloaded).
*
* Errors:
* EBADARG number is out of range
* ENOTOPEN isfd is not ISAM file descriptor of open ISAM file
*/
#define dibuf ((struct dictinfo *)buffer)
int
isindexinfo(isfd, buffer, number)
int isfd;
struct keydesc *buffer;
int number;
{
register Fab *fab;
int ret;
Fcb *fcb = NULL;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Call the Access Method or RPC client function, depending whether
* the file is local or remote.
*/
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(&fab->isfhandle, &fab->errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r(fcb);
/*
* Validate number argument.
*/
if (number < 0 || number > fcb->nkeys) {
_amseterrcode(&fab->errcode, EBADARG);
goto ERROR;
}
if (number == 0) {
/*
* Return dictinfo structure.
*/
dibuf->di_nkeys = fcb->nkeys;
dibuf->di_recsize = fcb->maxreclen;
dibuf->di_idxsize = fcb->keys[0].k2_len;
dibuf->di_nrecords = fcb->nrecords;
/* Set msb of di_nkeys for variable length records. */
if (fcb->varflag == TRUE)
dibuf->di_nkeys |= DICTVARLENBIT;
}
else {
/*
* Return index information.
*/
_iskey_itox(fcb->keys + number - 1, buffer);
}
_amseterrcode(&fab->errcode, ISOK);
/* XXX This fixes a core dump that occurs when isindexinfo is
* called on brand new tables
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
*/
_isam_exithook();
ret = ISOK;
goto CLEANUP;
ERROR:
/*
* Restore FCB from CNTL page.
*/
_isdisk_rollback();
_isdisk_inval();
_isam_exithook();
ret = ISERROR;
CLEANUP:
if (ret == ISOK)
isreclen = fab->minreclen; /* for variable length */
_seterr_errcode(&fab->errcode);
/*
* This is a patch to conform with the VSX 3.0 test that checks
* that k_leng == 2 and k_type == 1 for index 1 if the ISAM file
* has no primary key. I suspect that these numbers are returned by
* C-ISAM and the author of VSX tests diligently checks them even
* though they have no meaning.
*/
if (ret == ISOK && number == 1 && buffer->k_nparts == 0) {
buffer->k_leng = 2;
buffer->k_type = INTTYPE;
}
return (ret);
}

View File

@@ -0,0 +1,112 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isindfreel.c /main/3 1995/10/23 11:41:03 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isindfreel.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfreelist.c
*
* Description:
* Free list maintenance functions
*/
#include "isam_impl.h"
extern Bufhdr *_isdisk_fix();
/*
* blkno = _isfreel_alloc()
*
* Allocate a new index page.
*/
Blkno
_isindfreel_alloc(fcb)
Fcb *fcb;
{
Bufhdr *pbhdr;
char *p;
int npointers;
Blkno blkno;
if (fcb->indfreelist == FREELIST_NOPAGE) {
/*
* We must write something to the buffer, or we will get
* segmentation fault when using mapped I/O.
*/
fcb->indsize = _extend_file(fcb, fcb->indfd, fcb->indsize);
return (fcb->indsize - 1);
}
pbhdr = _isdisk_fix(fcb, fcb->indfd, fcb->indfreelist, ISFIXWRITE);
p = pbhdr->isb_buffer;
npointers = ldshort(p + FL_NPOINTERS_OFF);
if (npointers > 0) {
blkno = ldblkno(p + FL_POINTERS_OFF + npointers * BLKNOSIZE);
npointers--;
stshort((short)npointers, p + FL_NPOINTERS_OFF);
return (ldblkno(p + FL_POINTERS_OFF + npointers * BLKNOSIZE));
}
else {
blkno = fcb->indfreelist;
fcb->indfreelist = ldblkno(p + FL_NEXT_OFF);
return (blkno);
}
}
/*
* _isfreel_free()
*
* Free an index page.
*/
void
_isindfreel_free(fcb, blkno)
Fcb *fcb;
Blkno blkno;
{
Bufhdr *pbhdr;
char *p;
int npointers;
if (fcb->indfreelist != FREELIST_NOPAGE) {
pbhdr = _isdisk_fix(fcb, fcb->indfd, fcb->indfreelist, ISFIXWRITE);
p = pbhdr->isb_buffer;
npointers = ldshort(p + FL_NPOINTERS_OFF);
if (npointers < FL_MAXNPOINTERS) {
stblkno(blkno, p + FL_POINTERS_OFF + npointers * BLKNOSIZE);
npointers++;
stshort((short)npointers, p + FL_NPOINTERS_OFF);
return;
}
}
pbhdr = _isdisk_fix(fcb, fcb->indfd, blkno, ISFIXWRITE);
p = pbhdr->isb_buffer;
/* Mark page to indicate that it is in the free list. */
stshort((short)PT_FREELIST, p + FL_TYPE_OFF);
stshort((short)0, p + FL_NPOINTERS_OFF);
stblkno(fcb->indfreelist, p + FL_NEXT_OFF);
fcb->indfreelist = blkno;
}

View File

@@ -0,0 +1,98 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iskeyaux.c /main/3 1995/10/23 11:41:11 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iskeyaux.c 1.7 89/07/27 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iskeyaux.c
*
* Description:
* Auxiliary key related functions
*/
#include "isam_impl.h"
Blkno _isgetfreekpage();
/*
* _isindex_extract()
*
* Extract key parts from record buffer
*/
void
_iskey_extract (pkeydesc2, recp, keyp)
Keydesc2 * pkeydesc2;
char *recp;
char *keyp;
{
register int i;
register struct keypart2 *ppart;
int nparts;
nparts = pkeydesc2->k2_nparts;
ppart = pkeydesc2->k2_part;
/*
* XXX - This is a kludge to fix a problem with keys of an odd (ODD as
* not even) length that are extended to the nearest multiple of 2.
*
* It would be better to use bzero() here and not to call it in
* add1key etc. But this change was done just during the FCS process
* and may be robust even though it's not the cleanest thing under
* the sun.
*/
keyp[pkeydesc2->k2_len - 1] = '\0';
for (i = 0; i < nparts; i++) {
memcpy( keyp + ppart->kp2_offset,recp + ppart->kp2_start,
ppart->kp2_leng);
ppart++;
}
}
/*
* _allockpage()
*
* Allocate an initialize new key page.
*/
Bufhdr *
_allockpage(fcb, capac, level, blkno)
Fcb *fcb;
int capac;
int level;
Blkno *blkno; /* Output parameter */
{
Bufhdr *pbufhdr;
char *p;
*blkno = _isindfreel_alloc(fcb);
/* Fix the block in cache */
pbufhdr = _isdisk_fix(fcb, fcb->indfd, *blkno, ISFIXNOREAD);
p = pbufhdr->isb_buffer;
memset(p, 0, ISPAGESIZE);
/* Mark page as B-tree page. */
stshort((short)PT_INDEX, p + BT_TYPE_OFF);
/* Store page capacity. */
stshort((short)capac, p + BT_CAPAC_OFF);
/* Store B-tree level. */
stshort((short)level, p + BT_LEVEL_OFF);
return (pbufhdr);
}

View File

@@ -0,0 +1,54 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iskeycalc.c /main/3 1995/10/23 11:41:29 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iskeycalc.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iskeycalc.c
*
* Description:
* Key related calculation functions
*/
#include "isam_impl.h"
/* getkeysperleaf() - Calculate number of keys per leaf node */
int
getkeysperleaf (keylen)
int keylen;
{
int n;
n = ((ISPAGESIZE - BT_KEYS_OFF) / keylen);
return (le_odd (n)); /* n or n-1 */
}
/* getkeyspernode() - Calculate number of keys per non-leaf node */
int
getkeyspernode (keylen)
int keylen;
{
int n;
n = ((ISPAGESIZE - BT_KEYS_OFF) / (keylen + BLKNOSIZE));
return (le_odd (n)); /* n or n-1 */
}
/* le_odd(n) - Get next lower or equal odd number */
int
le_odd(n)
int n;
{
return ((n - 1) | 1);
}

View File

@@ -0,0 +1,162 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iskeycmp.c /main/3 1995/10/23 11:41:41 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iskeycmp.c 1.5 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iskeycmp.c
*
* Description:
* ISAM index comparison functions
*/
#include "isam_impl.h"
static struct keypart2 *_curtab; /* Current comparison */
/* descriptor table */
static int _ncurtab; /* Number of entries */
/*
* _iskeycmp_set()
*
* Set key decriptor and number of parts for subsequent key comparison.s
*/
void
_iskeycmp_set (pkeydesc2, nparts)
Keydesc2 *pkeydesc2;
int nparts; /* Use only so many parts */
{
_ncurtab = nparts;
_curtab = pkeydesc2->k2_part;
assert(_ncurtab <= pkeydesc2->k2_nparts + 1); /* + 1 for recno */
}
/*
* Return number that is > 0 if l > r,
* = 0 if l = r,
* < 0 if l < r.
*/
int
_iskeycmp(lkey, rkey)
char *lkey, *rkey;
{
int i, ret;
register struct keypart2 *p;
register char *l, *r;
register long llong, rlong;
double ldouble, rdouble;
ret = 0;
for (i = 0, p = _curtab; ret == 0 && i < _ncurtab;i++, p++) {
l = lkey + p->kp2_offset;
r = rkey + p->kp2_offset;
switch (p->kp2_type) {
case CHARTYPE:
case BINTYPE:
ret = memcmp(l, r, p->kp2_leng);
break;
case LONGTYPE:
llong = ldlong(l);
rlong = ldlong(r);
if (llong > rlong)
ret = 1;
else if (llong < rlong)
ret = -1;
break;
case SHORTTYPE:
llong = (long)ldshort(l);
rlong = (long)ldshort(r);
if (llong > rlong)
ret = 1;
else if (llong < rlong)
ret = -1;
break;
case DOUBLETYPE:
ldouble = lddbl(l);
rdouble = lddbl(r);
if (ldouble > rdouble)
ret = 1;
else if (ldouble < rdouble)
ret = -1;
break;
case FLOATTYPE:
ldouble = (double)ldfloat(l);
rdouble = (double)ldfloat(r);
if (ldouble > rdouble)
ret = 1;
else if (ldouble < rdouble)
ret = -1;
break;
case CHARTYPE + ISDESC:
case BINTYPE + ISDESC:
ret = memcmp(r, l, p->kp2_leng);
break;
case LONGTYPE + ISDESC:
llong = ldlong(l);
rlong = ldlong(r);
if (llong > rlong)
ret = -1;
else if (llong < rlong)
ret = 1;
break;
case SHORTTYPE + ISDESC:
llong = (long)ldshort(l);
rlong = (long)ldshort(r);
if (llong > rlong)
ret = -1;
else if (llong < rlong)
ret = 1;
break;
case DOUBLETYPE + ISDESC:
ldouble = lddbl(l);
rdouble = lddbl(r);
if (ldouble > rdouble)
ret = -1;
else if (ldouble < rdouble)
ret = 1;
break;
case FLOATTYPE + ISDESC:
ldouble = (double)ldfloat(l);
rdouble = (double)ldfloat(r);
if (ldouble > rdouble)
ret = -1;
else if (ldouble < rdouble)
ret = 1;
break;
default:
_isfatal_error("Bad data conversion descriptor");
break;
}
}
return (ret);
}

View File

@@ -0,0 +1,110 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iskeyconv.c /main/3 1995/10/23 11:41:54 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iskeyconv.c 1.4 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iskeyconv.c
*
* Description:
* Conversion functions between internal and external key descriptor
*
*/
#include "isam_impl.h"
/*
* _iskey_itox(pikdesc,pxkdesc)
*
* Convert internal key desc. to X/OPEN key descriptor.
*/
_iskey_itox(pikdesc,pxkdesc)
register struct keydesc2 *pikdesc; /* NetISAM internal format */
register struct keydesc *pxkdesc; /* X/OPEN format */
{
int nparts;
register int i;
memset ((char *)pxkdesc, 0, sizeof (*pxkdesc));
pxkdesc->k_flags = pikdesc->k2_flags;
nparts = pxkdesc->k_nparts = pikdesc->k2_nparts;
for (i = 0; i < nparts;i++) {
pxkdesc->k_part[i].kp_start = pikdesc->k2_part[i].kp2_start;
pxkdesc->k_part[i].kp_leng = pikdesc->k2_part[i].kp2_leng;
pxkdesc->k_part[i].kp_type = pikdesc->k2_part[i].kp2_type;
}
}
/*
* _iskey_xtoi()
*
* Convert X/OPEN key descriptor to internal key descriptor.
*
*/
_iskey_xtoi(pikdesc,pxkdesc)
register struct keydesc2 *pikdesc; /* NetISAM internal format */
register struct keydesc *pxkdesc; /* X/OPEN format */
{
int nparts;
register int i;
int offset; /* Keep track of offset in key */
memset ((char *)pikdesc, 0, sizeof (*pikdesc));
pikdesc->k2_flags = pxkdesc->k_flags;
nparts = pikdesc->k2_nparts = pxkdesc->k_nparts;
offset = 0;
/*
* Every key entry starts with record number.
*/
offset += RECNOSIZE;
/*
* If index allows duplicates, the key is augmented with duplicate
* serial number.
*/
if ((pxkdesc->k_flags & DUPSMASK) == ISDUPS)
offset += DUPIDSIZE;
for (i = 0; i < nparts; i++) {
pikdesc->k2_part[i].kp2_start = pxkdesc->k_part[i].kp_start;
pikdesc->k2_part[i].kp2_leng = pxkdesc->k_part[i].kp_leng;
pikdesc->k2_part[i].kp2_type = pxkdesc->k_part[i].kp_type;
pikdesc->k2_part[i].kp2_offset = offset;
offset += pxkdesc->k_part[i].kp_leng;
}
/* Append recno to key descriptors. */
pikdesc->k2_part[i].kp2_start = 0; /* not used */
pikdesc->k2_part[i].kp2_leng = RECNOSIZE;
pikdesc->k2_part[i].kp2_type = RECNOTYPE;
pikdesc->k2_part[i].kp2_offset = KEY_RECNO_OFF; /* at the beginning of key */
if ((pxkdesc->k_flags & DUPSMASK) == ISDUPS) {
/* Append duplicate serial number to key descriptors. */
pikdesc->k2_part[i].kp2_start = 0; /* not used */
pikdesc->k2_part[i].kp2_leng = DUPIDSIZE;
pikdesc->k2_part[i].kp2_type = DUPIDTYPE;
pikdesc->k2_part[i].kp2_offset = KEY_DUPS_OFF; /* after recno field */
}
/* Round up to next multiple of 2. */
offset = (offset+1) & ~1;
pikdesc->k2_len = offset; /* Length of the entire key */
}

View File

@@ -0,0 +1,101 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iskeyvalid.c /main/3 1995/10/23 11:42:06 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iskeyvalid.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iskeydesc.c
*
* Description:
* Functions dealing with the keydesc structure.
*
*
*/
#include "isam_impl.h"
static int _check_typelen();
/*
* _validate_keydesc(keydesc, minreclen)
*
* Validate key descriptor. minreclen is needed to make suree that all
* the key parts have a meaningful offset.
*
*/
int
_validate_keydesc(keydesc, minreclen)
register struct keydesc *keydesc;
int minreclen;
{
int nparts;
register int i;
int type, start, length;
int keylen = 0;
nparts = keydesc->k_nparts;
if (nparts <= 0 || nparts > NPARTS)
return (ISERROR);
for (i = 0; i < nparts;i++) {
type = keydesc->k_part[i].kp_type & ~ISDESC;
start = keydesc->k_part[i].kp_start;
length = keydesc->k_part[i].kp_leng;
if(_check_typelen(type, length) == ISERROR)
return (ISERROR);
if (type < MINTYPE || type >= MAXTYPE)
return (ISERROR);
if (start < 0 || start + length > minreclen)
return (ISERROR);
keylen += length;
}
if(keylen > MAXKEYSIZE)
return (ISERROR);
return (ISOK);
}
/*
* _check_typelen()
*
* Check length against the length of the corresponding type.
*/
static int
_check_typelen(type, length)
int type;
int length;
{
switch (type) {
case INTTYPE:
return ((length == INTSIZE) ? ISOK : ISERROR);
case LONGTYPE:
return ((length == LONGSIZE) ? ISOK : ISERROR);
case FLOATTYPE:
return ((length == FLOATSIZE) ? ISOK : ISERROR);
case DOUBLETYPE:
return ((length == DOUBLESIZE) ? ISOK : ISERROR);
case CHARTYPE:
case BINTYPE:
return ((length > 0) ? ISOK : ISERROR);
default:
return (ISERROR);
}
}

View File

@@ -0,0 +1,183 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isminmax.c /main/3 1995/10/23 11:42:16 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isminmax.c 1.4 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isminmax.c
*
* Description:
* NetISAM minimum and maximum values functions
*/
#include "isam_impl.h"
static unsigned char ismaxlongarr[LONGSIZE] = ISMAXLONG;
static unsigned char isminlongarr[LONGSIZE] = ISMINLONG;
static unsigned char ismaxshortarr[SHORTSIZE] = ISMAXSHORT;
static unsigned char isminshortarr[SHORTSIZE] = ISMINSHORT;
static unsigned char ismaxdoublearr[DOUBLESIZE] = ISMAXDOUBLE;
static unsigned char ismindoublearr[DOUBLESIZE] = ISMINDOUBLE;
static unsigned char ismaxfloatarr[FLOATSIZE] = ISMAXFLOAT;
static unsigned char isminfloatarr[FLOATSIZE] = ISMINFLOAT;
/* These two are used globally. */
long *ismaxlong = (long *)ismaxlongarr;
long *isminlong = (long *)isminlongarr;
static short *ismaxshort = (short *)ismaxshortarr;
static short *isminshort = (short *)isminshortarr;
static double *ismaxdouble = (double *)ismaxdoublearr;
static double *ismindouble = (double *)ismindoublearr;
static float *ismaxfloat = (float *)ismaxfloatarr;
static float *isminfloat = (float *)isminfloatarr;
/*
* _iskey_fillmax()
*
* Fill key buffer with maximum values
*/
void
_iskey_fillmax(pkeydesc2, keybuf)
struct keydesc2 *pkeydesc2;
register char *keybuf;
{
register int i;
register struct keypart2 *ppart;
int nparts;
nparts = pkeydesc2->k2_nparts;
ppart = pkeydesc2->k2_part;
for (i = 0; i < nparts + 1;i++) { /* +1 is for recnum part */
switch (ppart->kp2_type) {
case CHARTYPE:
(void) memset (keybuf + ppart->kp2_offset, ISMAXCHAR,
ppart->kp2_leng);
break;
case BINTYPE:
(void) memset (keybuf + ppart->kp2_offset, ISMAXBIN,
ppart->kp2_leng);
break;
case LONGTYPE:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismaxlong, LONGSIZE);
break;
case SHORTTYPE:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismaxshort, SHORTSIZE);
break;
case FLOATTYPE:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismaxfloat, FLOATSIZE);
break;
case DOUBLETYPE:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismaxdouble, DOUBLESIZE);
break;
case CHARTYPE + ISDESC:
(void) memset (keybuf + ppart->kp2_offset, ISMINCHAR,
ppart->kp2_leng);
break;
case BINTYPE + ISDESC:
(void) memset (keybuf + ppart->kp2_offset, ISMINBIN,
ppart->kp2_leng);
break;
case LONGTYPE + ISDESC:
memcpy ( keybuf + ppart->kp2_offset,(char *)isminlong, LONGSIZE);
break;
case SHORTTYPE + ISDESC:
memcpy ( keybuf + ppart->kp2_offset,(char *)isminshort, SHORTSIZE);
break;
case FLOATTYPE + ISDESC:
memcpy ( keybuf + ppart->kp2_offset,(char *)isminfloat, FLOATSIZE);
break;
case DOUBLETYPE + ISDESC:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismindouble, DOUBLESIZE);
break;
default:
_isfatal_error("_iskey_fillmax");
}
ppart++;
}
}
/*
* _iskey_fillmin()
*
* Fill key buffer with minimum values
*/
void
_iskey_fillmin(pkeydesc2, keybuf)
struct keydesc2 *pkeydesc2;
register char *keybuf;
{
register int i;
register struct keypart2 *ppart;
int nparts;
nparts = pkeydesc2->k2_nparts;
ppart = pkeydesc2->k2_part;
for (i = 0; i < nparts + 1;i++) { /* +1 is for recnum part */
switch (ppart->kp2_type) {
case CHARTYPE:
(void) memset (keybuf + ppart->kp2_offset, ISMINCHAR,
ppart->kp2_leng);
break;
case BINTYPE:
(void) memset (keybuf + ppart->kp2_offset, ISMINBIN,
ppart->kp2_leng);
break;
case LONGTYPE:
memcpy ( keybuf + ppart->kp2_offset,(char *)isminlong, LONGSIZE);
break;
case SHORTTYPE:
memcpy ( keybuf + ppart->kp2_offset,(char *)isminshort, SHORTSIZE);
break;
case FLOATTYPE:
memcpy ( keybuf + ppart->kp2_offset,(char *)isminfloat, FLOATSIZE);
break;
case DOUBLETYPE:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismindouble, DOUBLESIZE);
break;
case CHARTYPE + ISDESC:
(void) memset (keybuf + ppart->kp2_offset, ISMAXCHAR,
ppart->kp2_leng);
break;
case BINTYPE + ISDESC:
(void) memset (keybuf + ppart->kp2_offset, ISMAXBIN,
ppart->kp2_leng);
break;
case LONGTYPE + ISDESC:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismaxlong, LONGSIZE);
break;
case SHORTTYPE + ISDESC:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismaxshort, SHORTSIZE);
break;
case FLOATTYPE + ISDESC:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismaxfloat, FLOATSIZE);
break;
case DOUBLETYPE + ISDESC:
memcpy ( keybuf + ppart->kp2_offset,(char *)ismaxdouble, DOUBLESIZE);
break;
default:
_isfatal_error("_iskey_fillmin");
}
ppart++;
}
}

View File

@@ -0,0 +1,214 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: ismngfcb.c /main/3 1995/10/23 11:42:28 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)ismngfcb.c 1.4 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* ismngfcb.c
*
* Description:
* Manager of open FCB blocks.
*
* This module keeps track of usage of the FCB blocks and finds a victim
* on LRU basis.
* It also provides associative access to the FCB by their isfhandles.
*
*/
#include "isam_impl.h"
#define FCBHASHSIZE 101 /* Should be a prime for best hash */
#if (MAXFCB_UNIXFD > FCBHASHSIZE)
/*
* Cause a syntax error. FCBHASHSIZE must be increased to be > MAXFCB_UNIXFD.
* A good estimate is a prime approximately equal (2 * MAXFCB_UNIXFD).
*/
MUST INCREASE FCBHASHSIZE
#endif
struct hashtable {
Bytearray isfhandle;
Fcb *fcb;
long mrused;
} hashtable [FCBHASHSIZE];
#define unused(entry) ((entry).fcb == NULL)
static int _hashisfhandle();
static mrused_last = 0; /* stamp generator */
/*
* _mngfcb_insert(fcb, isfhandle)
*
* Insert new FCB entry.
*/
void
_mngfcb_insert(fcb, isfhandle)
Fcb *fcb;
Bytearray *isfhandle;
{
int hashval = _hashisfhandle(isfhandle);
register int ind;
int ntries;
/* Try to find an unused entry in the hash table. */
ind = hashval;
for (ntries = 0; ntries < FCBHASHSIZE; ntries++) {
if (unused(hashtable[ind]))
break;
if (++ind == FCBHASHSIZE)
ind = 0; /* Wrap the table */
}
if (ntries == FCBHASHSIZE) {
_isfatal_error("FCB hash table overflow");
}
/*
* Create an entry at the index ind.
* Duplicate the file handle and mark the entry with the current stamp.
*/
hashtable[ind].isfhandle = _bytearr_dup(isfhandle);
hashtable[ind].fcb = fcb;
hashtable[ind].mrused = mrused_last++;
}
/*
* fcb = _mngfcb_find(isfhandle)
*
* Return a pointer to the FCB, or NULL if the FCB is not found.
* If the FCB is found, it is "touched" for the LRU algorithm purpose.
*/
Fcb *
_mngfcb_find(isfhandle)
Bytearray *isfhandle;
{
int hashval = _hashisfhandle(isfhandle);
register int ind;
int ntries;
/* Find the entry. */
ind = hashval;
for (ntries = 0; ntries < FCBHASHSIZE; ntries++) {
if (_bytearr_cmp(&hashtable[ind].isfhandle, isfhandle) == 0)
break;
if (++ind == FCBHASHSIZE)
ind = 0; /* Wrap the table */
}
if (ntries == FCBHASHSIZE) {
return (NULL); /* Not found */
}
else {
/*
* Mark the entry with the current stamp.
*/
hashtable[ind].mrused = mrused_last++;
return hashtable[ind].fcb;
}
}
/*
* _mngfcb_delete(isfname)
*
* Delete an entry.
*/
void
_mngfcb_delete(isfhandle)
Bytearray *isfhandle;
{
int hashval = _hashisfhandle(isfhandle);
register int ind;
int ntries;
/* Find the entry */
ind = hashval;
for (ntries = 0; ntries < FCBHASHSIZE; ntries++) {
if (_bytearr_cmp(&hashtable[ind].isfhandle, isfhandle) == 0)
break;
if (++ind == FCBHASHSIZE)
ind = 0; /* Wrap the table */
}
if (ntries == FCBHASHSIZE) {
_isfatal_error("_mngfcb_delete cannot find entry");
}
else {
/*
* Clear the entry.
*/
_bytearr_free(&hashtable[ind].isfhandle);
memset ((char *) &hashtable[ind], 0, sizeof(hashtable[ind]));
}
}
/*
* isfhandle = _mngfcb_victim()
*
* Find LRU used FCB.
*/
Bytearray *
_mngfcb_victim()
{
int victim_ind = -1;
long victim_time = 0; /* Assign to shut up lint */
register int i;
for (i = 0; i < FCBHASHSIZE; i++) {
if (unused(hashtable[i])) /* Skip empty slots in table */
continue;
if (victim_ind == -1 || victim_time > hashtable[i].mrused) {
victim_ind = i;
victim_time = hashtable[i].mrused;
}
}
return ((victim_ind == -1) ? NULL : &hashtable[victim_ind].isfhandle);
}
/*
* _hashisfhandle(isfhandle)
*
* Hash isfhandle into an integer.
*/
Static int
_hashisfhandle(isfhandle)
Bytearray *isfhandle;
{
register char *p;
register unsigned h, g;
register int len;
len = isfhandle->length;
p = isfhandle->data;
h = 0;
while (len-- > 0) {
h = (h << 4) + (*p++);
if (g = h&0xf0000000) {
h = h ^ (g >> 24);
h = h ^ g;
}
}
return (h % FCBHASHSIZE);
}

View File

@@ -0,0 +1,106 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isopen.c /main/3 1995/10/23 11:42:40 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isopen.c 1.12 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isopen.c
*
* Description:
* Open an ISAM file.
*/
#include "isam_impl.h"
#include <netdb.h>
#include <sys/file.h>
#include <sys/time.h>
extern char _isam_version[];
static char *_version_ = _isam_version;
static int _am_open();
/*
* isfd = isopen(isfname, mode)
*
* Isopen() determines on which machine the ISAM file resides,
* checks if the file exists, creates a File access block,
* and initilizes it. It also checks permissions. Returns an ISAM file
* descriptor (isfd), or a value of -1 if the open failed.
*
* Errors:
* EBADARG Improper mode parameter
* EBADFILE ISAM file is corrupted or it is not an NetISAM file
* EFLOCKED The file is exclusively locked by other process.
* EFNAME Invalid ISAM file name
* EFNAME ISAM file does not exist
* ETOOMANY Too many ISAM file descriptors are in use (128 is the limit)
*
* The following error code is "borrowed" from UNIX:
* EACCES UNIX file system protection denies access to the file:
* - mode is INOUT or OUTPUT and ISAM file is on
* a Read-Only mounted file system
* - UNIX file permissions don't allow access to the file
*/
int
isopen(isfname, mode)
char *isfname;
int mode;
{
Fab *fab;
Isfd isfd;
enum openmode openmode;
/*
* Check if the user is allowed to access the ISAM file.
* Use UNIX and NFS permissions.
*/
/* Get file open mode part of the mode parameter. */
if ((openmode = _getopenmode(mode)) == OM_BADMODE) {
_setiserrno2(EBADARG, '9', '0');
return (NOISFD);
}
/* Create a Fab object. */
fab = _fab_new(isfname,
openmode,
(Bool)((mode & ISLENMODE) == ISVARLEN),
0,
0);
if (fab == NULL) {
return (NOISFD); /* iserrno is set by fab_new */
}
/* Get an ISAM file descriptor for this fab */
if ((isfd = _isfd_insert(fab)) == NOISFD) {
/* Table of ISAM file descriptors would overflow. */
_fab_destroy(fab);
_setiserrno2(ETOOMANY, '9', '0');
return (NOISFD);
}
FAB_ISFDSET(fab, isfd);
if (_am_open(fab)) {
_seterr_errcode(&fab->errcode);
_fab_destroy(fab);
return (NOISFD);
}
isreclen = fab->maxreclen;
return ((int)isfd); /* Successful isopen() */
}
Static int _am_open(fab)
register Fab *fab;
{
return (_amopen(fab->isfname, fab->openmode, &fab->varlength,
&fab->minreclen, &fab->maxreclen, &fab->isfhandle,
&fab->curpos, &fab->errcode));
}

View File

@@ -0,0 +1,69 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: ispageio.c /main/3 1995/10/23 11:42:51 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)ispageio.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* ispageio.c
*
* Description:
* I/O functions for file pages.
*
*
*/
#include "isam_impl.h"
/*
* _isseekpg(fd, pgno)
*
* Set current file pointer to the page pgno.
*/
void
_isseekpg(fd, pgno)
int fd;
Blkno pgno;
{
long offset = pgno * ISPAGESIZE;
if (lseek(fd, offset, 0) != offset)
_isfatal_error("lseek failed");
}
/*
* _isreadpg(fd, buf)
*
* Read eon block from UNIX file into a buffer.
*/
void
_isreadpg(fd, buf)
int fd;
char *buf;
{
if (read(fd, buf, ISPAGESIZE) != ISPAGESIZE)
_isfatal_error("read failed");
}
/*
* _iswritepg(fd, buf)
*
* Write one block to UNIX file.
*/
void
_iswritepg(fd, buf)
int fd;
char *buf;
{
if (write(fd, buf, ISPAGESIZE) != ISPAGESIZE)
_isfatal_error("write failed");
}

View File

@@ -0,0 +1,79 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isperm.c /main/3 1995/10/23 11:43:03 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isperm.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isperm.c
*
* Description:
* Extract permissions from mode functions.
*/
#include "isam_impl.h"
/*
* _getopenmode(mode)
*
* Extract open mode (ISINPUT, ISOUTPUT, ISINOUT) from mode.
*/
enum openmode
_getopenmode(mode)
int mode;
{
switch (mode & ISOPENMODE) {
case ISINPUT:
return (OM_INPUT);
case ISOUTPUT:
return (OM_OUTPUT);
case ISINOUT:
return (OM_INOUT);
default:
return (OM_BADMODE);
}
}
/*
* _getreadmode(mode)
*
* Extract read mode from mode.
*/
enum readmode
_getreadmode(mode)
int mode;
{
switch (mode & ISREADMODE) {
case ISFIRST:
return (RM_FIRST);
case ISLAST:
return (RM_LAST);
case ISNEXT:
return (RM_NEXT);
case ISPREV:
return (RM_PREV);
case ISCURR:
return (RM_CURR);
case ISEQUAL:
return (RM_EQUAL);
case ISGREAT:
return (RM_GREAT);
case ISGTEQ:
return (RM_GTEQ);
case ISLESS:
return (RM_LESS);
case ISLTEQ:
return (RM_LTEQ);
default:
return (RM_BADMODE);
}
}

View File

@@ -0,0 +1,796 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isread.c /main/3 1995/10/23 11:43:35 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isread.c 1.9 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isread.c
*
* Description:
* Read a record from ISAM file.
*/
#include "isam_impl.h"
#include <sys/time.h>
static int _amread();
/*
* err = isread(isfd, record, mode)
*
* Isread() reads a new record from an ISAM file.
*
* Current record position is set.
* isrecnum is set to indicate the read record.
*
* If the ISAM file is for variable length records, the isreclen variable
* is set to indicate the actual length of the record.
*
* Returns 0 if successful, or -1 of any error.
*
* Errors:
* ELOCKED The record or the entire file is locked by another process.
* ENOTOPEN isfd does not correspond to an open ISAM file, or the
* ISAM file was opened with ISOUTPUT mode.
* EBADARG Bad mode parameter.
* ENOCURR Mode is ISCURR and the current record position is not set.
* ENOREC Specified record cannot be found (random access read)
* EENDFILE The end file of is reached (sequential read).
* EBADKEY Index was deleted by other process (can happen only
* when lock file is purged).
*/
int
isread(isfd, record, mode)
int isfd;
char *record;
int mode;
{
register Fab *fab;
int reclen;
Recno recnum;
int ret;
enum readmode readmode;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISINPUT, or ISINOUT.
*/
if (fab->openmode != OM_INPUT && fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Extract read mode.
*/
if ((readmode = _getreadmode(mode)) == RM_BADMODE) {
_setiserrno2(EBADARG, '9', '0');
return (ISERROR);
}
/*
* All keys must be in the minimum record length.
* So send just the minimum length part of the record.
*/
reclen = fab->minreclen;
/*
* Call the Access Method
*/
recnum = isrecnum;
if ((ret = _amread(&fab->isfhandle, record, &reclen,
readmode, &fab->curpos, &recnum,
&fab->errcode)) == ISOK) {
isrecnum = recnum; /* Set isrecnum */
}
isreclen = reclen;
_seterr_errcode(&fab->errcode);
return (ret); /* Successful read */
}
/*
* _amread(isfhandle, record, reclen, readmode, curpos, recnum, errcode)
*
* _amread() reads a record from ISAM file
*
* Input params:
* isfhandle Handle of ISAM file
* readmode Specifies access mode (random or sequential)
* curpos current record position
* recnum copy if isrecnum
*
* Output params:
* curpos new current position
* recnum record number
* errcode error status of the operation
* reclen actual length of the record
* record filled with data
*
*/
static int
_amread(isfhandle, record, reclen, readmode, curpos, recnum, errcode)
Bytearray *isfhandle;
enum readmode readmode;
char *record;
int *reclen;
Bytearray *curpos;
Recno *recnum;
struct errcode *errcode;
{
Fcb *fcb = NULL;
Recno recnum2;
int err;
Crp *crp;
Btree *btree = NULL;
Keydesc2 *pkeydesc2;
char keybuf1[MAXKEYSIZE], keybuf2[MAXKEYSIZE];
char *pkey, *pkeynext;
int skipbytes;
int ret;
Bytearray oldcurpos;
int (*rec_read)();
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r2(fcb);
/*
* Save the old record position.
*/
oldcurpos = _bytearr_dup(curpos);
/*
* Get info from current record position structure.
*/
crp = (Crp *) curpos->data;
if (crp->keyid == PHYS_ORDER) {
/*
* Physical order in use.
*/
switch (readmode) {
case RM_EQUAL:
recnum2 = *recnum; /* passed from isrecnum */
if ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
break;
case RM_GREAT:
recnum2 = *recnum + 1;
if (recnum2 < 1) recnum2 = 1;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
err == ENOREC)
recnum2++;
if (err != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
break;
case RM_GTEQ:
recnum2 = *recnum;
if (recnum2 < 1) recnum2 = 1;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
err == ENOREC)
recnum2++;
if (err != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
break;
case RM_LESS:
recnum2 = *recnum - 1;
if (recnum2 > fcb->lastrecno) recnum2 = fcb->lastrecno;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
err == ENOREC)
recnum2--;
if (err != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
break;
case RM_LTEQ:
recnum2 = *recnum;
if (recnum2 > fcb->lastrecno) recnum2 = fcb->lastrecno;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
err == ENOREC)
recnum2--;
if (err != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
break;
case RM_FIRST:
recnum2 = 1;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
err == ENOREC)
recnum2++;
if (err != ISOK) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
break;
case RM_CURR:
switch (crp->flag) {
case CRP_ON:
case CRP_BEFORE:
case CRP_AFTER:
recnum2 = crp->recno;
break;
case CRP_BEFOREANY:
recnum2 = 1;
break;
default:
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
if( rec_read(fcb, record, recnum2, reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
break;
case RM_NEXT:
switch (crp->flag) {
case CRP_ON:
case CRP_AFTER:
recnum2 = crp->recno + 1;
break;
case CRP_BEFOREANY:
recnum2 = 1;
break;
case CRP_BEFORE:
recnum2 = crp->recno;
break;
case CRP_AFTERANY:
_amseterrcode(errcode, EENDFILE);
goto ERROR;
default:
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
err == ENOREC)
recnum2++;
if (err != ISOK) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
break;
case RM_PREV:
switch (crp->flag) {
case CRP_ON:
case CRP_BEFORE:
recnum2 = crp->recno - 1;
break;
case CRP_AFTER:
recnum2 = crp->recno;
break;
case CRP_BEFOREANY:
_amseterrcode(errcode, EENDFILE);
goto ERROR;
default:
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
err == ENOREC)
recnum2--;
if (err != ISOK) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
break;
case RM_LAST:
recnum2 = fcb->lastrecno;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
err == ENOREC)
recnum2--;
if (err != ISOK) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
break;
default:
_isfatal_error("Invalid readmode");
}
*recnum = recnum2;
/*
* Set new current record position.
*/
crp->recno = recnum2;
crp->flag = CRP_ON;
} /* physical order */
else {
/*
* Find key descriptor in FCB
*/
if ((pkeydesc2 = _isfcb_indfindkey(fcb, crp->keyid)) == NULL) {
_amseterrcode(errcode, EBADKEY);
goto ERROR;
}
/*
* skipkeybytes is set to the number of bytes in the beginning
* of the key:
* RECNOSIZE for ISNODUPS keys to skip recno part
* RECNOSIZE + DUPIDSIZE to skip recno and duplicate serial number
*/
skipbytes = RECNOSIZE;
if (ALLOWS_DUPS2(pkeydesc2))
skipbytes += DUPIDSIZE;
/*
* Create B tree object.
*/
btree = _isbtree_create(fcb, pkeydesc2);
switch (readmode) {
case RM_EQUAL:
case RM_GTEQ:
/*
* Make sure that you will read the first duplicate.
*/
_iskey_fillmin(pkeydesc2, keybuf1);
/*
* Extract key fields from record.
*/
_iskey_extract(pkeydesc2, record, keybuf2);
memcpy((void *)(keybuf1 + skipbytes),
(const void *)(keybuf2 + skipbytes), crp->matchkeylen);
/*
* Position pointer in the B-tree in before the searched value.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_next(btree)) == NULL) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
if (readmode == RM_EQUAL &&
memcmp(keybuf1 + skipbytes, pkey + skipbytes,
crp->matchkeylen) != 0) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
recnum2 = crp->recno;
break;
case RM_GREAT:
/*
* Make sure that you will read past all matching records.
*/
_iskey_fillmax(pkeydesc2, keybuf1);
/*
* Extract key fields from record.
*/
_iskey_extract(pkeydesc2, record, keybuf2);
memcpy((void *)(keybuf1 + skipbytes),
(const void *)(keybuf2 + skipbytes), crp->matchkeylen);
/*
* Position pointer in the B-tree in before the searched value.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_next(btree)) == NULL) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
recnum2 = crp->recno;
break;
case RM_LESS:
/*
* Make sure that you will read before all matching records.
*/
_iskey_fillmin(pkeydesc2, keybuf1);
/*
* Extract key fields from record.
*/
_iskey_extract(pkeydesc2, record, keybuf2);
memcpy((void *)(keybuf1 + skipbytes),
(const void *)(keybuf2 + skipbytes), crp->matchkeylen);
/*
* Position pointer in the B-tree in before the searched value.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_current(btree)) == NULL) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
recnum2 = crp->recno;
break;
case RM_LTEQ:
/*
* Make sure that you will read the last duplicate.
*/
_iskey_fillmax(pkeydesc2, keybuf1);
/*
* Extract key fields from record.
*/
_iskey_extract(pkeydesc2, record, keybuf2);
memcpy((void *)(keybuf1 + skipbytes),
(const void *)(keybuf2 + skipbytes), crp->matchkeylen);
/*
* Position pointer in the B-tree in before the searched value.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_current(btree)) == NULL) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
recnum2 = crp->recno;
break;
case RM_CURR:
switch (crp->flag) {
case CRP_ON:
case CRP_BEFORE:
case CRP_AFTER:
/*
* We have check if the record has not been deleted
* since the current record position was set up.
*/
_isbtree_search(btree, crp->key);
pkey = _isbtree_current(btree);
if (pkey == NULL ||
ldrecno(pkey + KEY_RECNO_OFF) != crp->recno) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
break;
case CRP_BEFOREANY:
_isbtree_search(btree, crp->key);
pkey = _isbtree_next(btree);
if (pkey == NULL) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
break;
default:
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
recnum2 = crp->recno;
break;
case RM_NEXT:
/*
* Validate that current position has been set.
*/
switch (crp->flag) {
case CRP_ON:
case CRP_BEFORE:
case CRP_BEFOREANY:
break;
case CRP_AFTERANY:
_amseterrcode(errcode, EENDFILE);
goto ERROR;
default:
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
/*
* Position pointer to current position.
*/
_isbtree_search(btree, crp->key);
if (crp->flag == CRP_BEFORE)
pkey = _isbtree_current(btree);
else
/* crp->flag == CRP_ON || crp->flag == CRP_BEFOREANY */
pkey = _isbtree_next(btree);
if (pkey == NULL) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
recnum2 = crp->recno;
break;
case RM_PREV:
/*
* Validate that current position has been set.
*/
switch (crp->flag) {
case CRP_ON:
case CRP_BEFORE:
/*
* To get to the previous record, we must decrement
* the TID part for unique keys, or duplicate serial number
* for non-unique keys.
*/
memcpy((void *)keybuf1,
(const void *)crp->key, pkeydesc2->k2_len);
if (ALLOWS_DUPS2(pkeydesc2)) {
stlong(ldlong(keybuf1 + KEY_DUPS_OFF) - 1,
keybuf1 + KEY_DUPS_OFF);
}
else {
strecno(ldrecno(keybuf1 + KEY_RECNO_OFF) - 1,
keybuf1 + KEY_RECNO_OFF);
}
break;
case CRP_AFTER:
memcpy((void *)keybuf1, (const void *)crp->key, pkeydesc2->k2_len);
break;
case CRP_BEFOREANY:
_amseterrcode(errcode, EENDFILE);
goto ERROR;
default:
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
/*
* Position pointer to current position.
*/
_isbtree_search(btree, keybuf1);
pkey = _isbtree_current(btree);
if (pkey == NULL) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
recnum2 = crp->recno;
break;
case RM_FIRST:
/*
* Fill key buffer with -infinity.
*/
_iskey_fillmin(pkeydesc2, keybuf1);
/*
* Position pointer in the B-tree before any key entry.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_next(btree)) == NULL) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
recnum2 = crp->recno;
break;
case RM_LAST:
/*
* Fill key buffer with +infinity.
*/
_iskey_fillmax(pkeydesc2, keybuf1);
/*
* Position pointer in the B-tree before any key entry.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_current(btree)) == NULL) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, EENDFILE);
goto ERROR;
}
recnum2 = crp->recno;
break;
default:
_isfatal_error("Invalid readmode");
}
*recnum = recnum2;
crp->flag = CRP_ON;
/*
* Set up isdupl to handle isstat2 value for keys that allow
* duplicate values.
*/
if (ALLOWS_DUPS2(pkeydesc2) && (pkeynext = _isbtree_next(btree)) &&
memcmp(pkey + skipbytes, pkeynext + skipbytes,
crp->matchkeylen) == 0) {
isdupl = 1;
}
_isbtree_destroy(btree);
}
_amseterrcode(errcode, ISOK);
ret = ISOK;
/* Clean-up work. */
_isdisk_commit(); /* This will only check
* that we unfixed all fixed
* buffers */
_isdisk_inval();
_bytearr_free(&oldcurpos);
_isam_exithook();
return (ret);
ERROR:
*reclen = 0;
_isdisk_inval();
_bytearr_free(&oldcurpos);
/*
* If error is ENOREC, set the current record position undefined.
*/
if (errcode->iserrno == ENOREC || errcode->iserrno == EENDFILE) {
((Crp *)curpos->data)->flag = CRP_UNDEF;
}
if (btree != NULL)
_isbtree_destroy(btree);
_isam_exithook();
return (ISERROR);
}

View File

@@ -0,0 +1,265 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isrename.c /main/3 1995/10/23 11:43:48 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isrename.c 1.10 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isrename.c
*
* Description:
* Rename an ISAM file.
*/
#include "isam_impl.h"
#include <sys/time.h>
void _removelast();
static void _removelast2();
char *_lastelement();
static void _rename_datfile(), _rename_indfile(), _rename_varfile();
static int _amrename();
/*
* isfd = isrename(oldname, newname)
*
*
* Errors:
* EBADFILE ISAM file is corrupted or it is not an NetISAM file
* EFLOCKED The file is exclusively locked by other process.
* EFNAME Invalid ISAM file name
* EFNAME ISAM file does not exist
* ETOOMANY Too many ISAM file descriptors are in use (128 is the limit)
*
* The following error code is "borrowed" from UNIX:
* EACCES UNIX file system protection denies access to the file:
* - mode is INOUT or OUTPUT and ISAM file is on
* a Read-Only mounted file system
* - UNIX file permissions don't allow access to the file
*/
int
isrename(oldname, newname)
char *oldname, *newname;
{
Isfd isfd, isfd2;
Fab *fab;
char olddir [MAXPATHLEN];
char newdir [MAXPATHLEN];
char datfname[MAXPATHLEN];
/*
* Check that the odl and new filename are in the same directory.
*/
(void)strcpy(olddir, oldname);
_removelast2(olddir);
(void)strcpy(newdir, newname);
_removelast2(newdir);
if (strcmp(newdir, olddir) != 0) {
_setiserrno2(EFNAME, 9, 0);
return (ISERROR);
}
/*
* Open the file
*/
if ((isfd = isopen(oldname, ISINOUT)) == -1)
return (ISERROR); /* iserrno is set */
/*
* Reject rename if 'newfile' exists.
*/
if ((isfd2 = isopen(newname, ISINOUT)) != -1 || iserrno != ENOENT) {
_setiserrno2(EEXIST, 9, 0);
if (isfd2 >= 0) (void)isclose(isfd2);
return (ISERROR); /* iserrno is set */
}
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_isfatal_error("isrename() cannot find FAB");
_setiserrno2(EFATAL,'9','0');
return (ISERROR);
}
if (_amrename(&fab->isfhandle, _lastelement(newname), &fab->errcode)) {
_seterr_errcode(&fab->errcode);
(void)isclose(isfd);
return (ISERROR);
}
_fab_destroy(fab); /* Deallocate Fab object */
_isfd_delete(isfd);
/*
* We must unlink() the .rec file, or isbuild() with the same
* following immediatly would fail because for NFS files the client
* still thinks that the file exists for a few seconds.
*/
(void)strcpy(datfname, oldname);
_makedat_isfname(datfname);
(void)unlink(datfname);
return (ISOK); /* Successful isrename() */
}
/*
* _removelast2(path)
*
* Remove last element of path. E.g. /usr/db/part yields /usr/db.
* Unlike _removelast() that path does not have to start with '/'.
*/
Static void
_removelast2(path)
char *path;
{
register char *p;
for (p = path + strlen(path); *--p != '/' && p >= path; )
*p = '\0';
}
/*
* _amrename(isfhandle, newname)
*
* _amrename() renames ISAM file
*
* Input params:
* isfhandle Handle of ISAM file
*
* Output params:
* errcode Error code
*
*/
static int
_amrename(isfhandle, newname, errcode)
Bytearray *isfhandle;
char *newname;
struct errcode *errcode;
{
Fcb *fcb;
char *isfname = _getisfname(isfhandle);
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
goto ERROR;
}
/*
* Delete FCB and remove it from FCB cache.
*/
(void) _watchfd_decr(_isfcb_nfds(fcb));
_isfcb_close(fcb);
_mngfcb_delete(isfhandle);
/*
* Rename all UNIX files.
*/
_rename_datfile(isfname, newname);
_rename_indfile(isfname, newname);
_rename_varfile(isfname, newname);
_isam_exithook();
return (ISOK);
ERROR:
_isam_exithook();
return (ISERROR);
}
Static void
_rename_datfile(isfname, newname)
char *isfname;
char *newname; /* with no prefix */
{
char namebuf[MAXPATHLEN];
char newbuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
(void) strcpy(newbuf, isfname);
/*
* Replace the last element of the old path with newname.
*/
_removelast(newbuf);
if (strcmp(newbuf, "/") != 0)
(void) strcat(newbuf, "/");
(void)strcat(newbuf, newname);
_makedat_isfname(namebuf);
_makedat_isfname(newbuf);
(void)rename(namebuf, newbuf);
}
Static void
_rename_indfile(isfname, newname)
char *isfname;
char *newname; /* with no prefix */
{
char namebuf[MAXPATHLEN];
char newbuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
(void) strcpy(newbuf, isfname);
/*
* Replace the last element of the old path with newname.
*/
_removelast(newbuf);
if (strcmp(newbuf, "/") != 0)
(void) strcat(newbuf, "/");
(void)strcat(newbuf, newname);
_makeind_isfname(namebuf);
_makeind_isfname(newbuf);
(void)rename(namebuf, newbuf);
}
Static void
_rename_varfile(isfname, newname)
char *isfname;
char *newname; /* with no prefix */
{
char namebuf[MAXPATHLEN];
char newbuf[MAXPATHLEN];
(void) strcpy(namebuf, isfname);
(void) strcpy(newbuf, isfname);
/*
* Replace the last element of the old path with newname.
*/
_removelast(newbuf);
if (strcmp(newbuf, "/") != 0)
(void) strcat(newbuf, "/");
(void)strcat(newbuf, newname);
_makevar_isfname(namebuf);
_makevar_isfname(newbuf);
(void)rename(namebuf, newbuf);
}

View File

@@ -0,0 +1,441 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: isrepair.c /main/5 1998/04/10 08:04:42 mgreess $ */
/* @(#)isrepair.c 1.7 93/07/30
* Copyright (c) 1988, 1993 by Sun Microsystems, Inc.
*/
/*
* isrepair.c
*
* Description:
* Repair an ISAM file.
*/
#include "isam_impl.h"
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
/*
* err = isrepair(isfname, verbose)
*
* isrepair repairs an ISAM file.
*
* The algorithm used is as the following:
* 1. Read the control page of the possibly damaged file. We assume
* that the control page is not damaged.
* 2. Open a new ISAM file with ~ suffix.
* 3. Scan .rec file (and .var file if variable length records file)
* retrieve all records not marked as deleted, and write them
* to the ~ ISAM file.
* 4. Delete the old ISAM file.
* 5. Rename ~ file to the original file name.
* 6. Build all indexes.
*
* verbose option (if set to nonzero) will print messages to stdout.
*/
Static char *rp_readrecord_v(), *rp_readrecord_f();
Static printkey();
Static cmd_error();
Static int typeletter();
Static rp_readcntlpg();
static int isnoprintf(const char *, ...);
isrepair(isfname, verbose)
char *isfname;
int verbose;
{
extern char *rp_readrecord_v(), *rp_readrecord_f();
char cntlpg[ISCNTLSIZE];
int datfd, indfd, varfd;
int minreclen, maxreclen;
int nrecords_fromcntl;
int varflag;
char nameBuf [MAXPATHLEN];
char *namebuf;
int isfd = -1;
struct keydesc2 keydesc2;
int i;
long offset, recfile_end;
char *prec;
long recnum;
int nrecords_found, diff;
long lastrecno;
struct keydesc keydesc;
int (*print)(const char *, ...);
sigset_t oldmask;
sigset_t allsignals;
char Buffer[BUFSIZ];
char *buffer;
print = verbose ? printf : isnoprintf;
datfd = indfd = varfd = -1;
/*
* Open UNIX files.
*/
if (strlen(isfname) + 10 >= MAXPATHLEN)
namebuf = (char*) malloc(strlen(isfname) + 10);
else
namebuf = nameBuf;
(void)strcpy(namebuf, isfname);
_makedat_isfname(namebuf);
datfd = open(namebuf, O_RDONLY);
if (datfd > -1) {
fcntl(datfd, F_SETFD, 1);
}
(void)strcpy(namebuf, isfname);
_makeind_isfname(namebuf);
indfd = open(namebuf, O_RDONLY);
if (indfd > -1) {
fcntl(indfd, F_SETFD, 1);
}
(void)strcpy(namebuf, isfname);
_makevar_isfname(namebuf);
varfd = open(namebuf, O_RDONLY);
if (varfd > -1) {
fcntl(varfd, F_SETFD, 1);
}
(void)print("Reading control page from %s.rec file...\n",
isfname);
if (rp_readcntlpg(datfd, cntlpg) == ISERROR) {
(void)print("Cannot read the control page\n");
goto ERROR;
}
/*
* Check magic. Repair only ISAM files!!!
*/
if (strncmp(cntlpg + CP_MAGIC_OFF, ISMAGIC, strlen(ISMAGIC)) != 0) {
(void)print("Bad magic in %s.rec\n", isfname);
goto ERROR;
}
varflag = ldint(cntlpg + CP_VARFLAG_OFF);
minreclen = ldint(cntlpg + CP_MINRECLEN_OFF);
maxreclen = ldint(cntlpg + CP_MAXRECLEN_OFF);
/*
* Check for maxreclen field value of -1. This could have occured due to
* ISMAXRECLEN being incorrectly set to 65535 in an earlier version. If
* this field is -1 and it's a variable length record, reset to the new
* value of MAXRECLEN. This means that this field will be repaired when
* the control block is written back to disk.
*/
if (maxreclen == -1 && varflag) {
maxreclen = ISMAXRECLEN;
}
lastrecno = ldlong(cntlpg + CP_LASTRECNO_OFF);
nrecords_fromcntl = ldlong(cntlpg + CP_NRECORDS_OFF);
/*
* Open output file. Use ~ as suffix.
*/
(void)sprintf(namebuf, "%s~", isfname);
(void)print("Opening temporary ISAM file '%s'...\n",
namebuf);
isreclen = minreclen;
if ((isfd = isbuild(namebuf, maxreclen, nokey, ISINOUT + ISEXCLLOCK +
(varflag?ISVARLEN:0))) == ISERROR) {
(void)print("Cannot open temporary ISAM file %s\n",
namebuf);
if (iserrno == EEXIST)
(void)print("File %s already exists\n", namebuf);
goto ERROR;
}
/*
* Scan .rec file and read all undeleted records.
*/
(void)print("Salvaging records from %s.rec%s file...\n",
isfname, varflag?" (and .var file)" : "");
offset = ISCNTLSIZE;
recfile_end = lseek(datfd, 0L, 2);
recnum = 1;
nrecords_found = 0;
while (recnum <= lastrecno && offset < recfile_end - minreclen) {
if (varflag) {
prec = rp_readrecord_v(datfd, varfd, offset, minreclen, maxreclen);
offset += minreclen + LONGSIZE;
}
else {
prec = rp_readrecord_f(datfd, offset, minreclen);
offset += minreclen + 1;
}
if (prec != NULL) {
if (iswrrec(isfd, recnum, prec) == ISERROR) {
cmd_error("iswrrec", print);
goto ERROR;
}
nrecords_found++;
}
recnum++;
}
diff = nrecords_found - nrecords_fromcntl;
if (diff == 0)
(void)print("All records found - total %d records\n",
nrecords_found);
else
(void)print("%d records found - %d records %s than in header\n",
nrecords_found, diff, diff > 0 ?
"more" : "less");
/*
* Close all file descriptors.
*/
(void)close(datfd);
(void)close(indfd);
(void)close(varfd);
(void)isclose(isfd);
(void) sigfillset(&allsignals);
(void) sigprocmask(SIG_SETMASK, &allsignals, &oldmask);
(void)print("Erasing ISAM file '%s'...\n", isfname);
/* if (iserase(isfname) != ISOK) {
cmd_error("iserase", print);
goto ERROR;
}
*/
if (strlen(isfname) + 5 >= MAXPATHLEN)
buffer = (char*) malloc(strlen(isfname) + 5);
else
buffer = Buffer;
(void)sprintf(buffer,"%s.rec", isfname);
(void)unlink(buffer);
(void)sprintf(buffer,"%s.ind", isfname);
(void)unlink(buffer);
(void)sprintf(buffer,"%s.var", isfname);
(void)unlink(buffer);
(void)sprintf(namebuf, "%s~", isfname);
(void)print("Renaming ISAM file '%s' to '%s'...\n",
namebuf, isfname);
if (isrename(namebuf, isfname) != ISOK) {
cmd_error("isrename", print);
goto ERROR;
}
/*
* Re-open the file and add keys.
*/
if (ldshort(cntlpg + CP_NKEYS_OFF) > 0) {
(void)print("Adding keys...\n");
if ((isfd = isopen(isfname, ISEXCLLOCK + ISINOUT +
(varflag?ISVARLEN:0))) == ISERROR) {
cmd_error("isopen", print);
goto ERROR;
}
for (i = 0; i < ldshort(cntlpg + CP_NKEYS_OFF); i++) {
ldkey(&keydesc2, cntlpg + CP_KEYS_OFF + i * K2_LEN);
_iskey_itox(&keydesc2, &keydesc);
if (keydesc.k_nparts == 0) /* special case for no primary */
continue;
printkey (i+1, &keydesc, print);
if (i == 0) {
if (isaddprimary(isfd, &keydesc) == ISERROR) {
cmd_error("isaddprimary", print);
(void)isclose(isfd);
goto ERROR;
}
}
else {
if (isaddindex(isfd, &keydesc) == ISERROR) {
cmd_error("isaddindex", print);
(void)isclose(isfd);
goto ERROR;
}
}
}
}
(void)isclose(isfd);
(void)sigprocmask(SIG_SETMASK, &oldmask, NULL);
print("...File repaired\n");
return (ISOK);
ERROR:
(void)print("\007Didn't repair ISAM file '%s'\n", isfname);
(void)close(datfd);
(void)close(indfd);
(void)close(varfd);
(void)isclose(isfd);
if (namebuf != nameBuf) free(namebuf);
if (buffer != Buffer) free(buffer);
return (ISERROR);
}
/******* low level data access used by the 'repair' utility ******************/
static char recordbuffer[ISMAXRECLEN + LONGSIZE];
/* rp_readcntlpg() - Read the control page */
Static
rp_readcntlpg(datfd, cntlpg)
int datfd;
char *cntlpg;
{
if (read (datfd, cntlpg, ISCNTLSIZE) != ISCNTLSIZE)
return (ISERROR);
return (ISOK);
}
/* rp_readrecord_f() - Read a record from .rec file */
Static char *
rp_readrecord_f(datfd, offset, reclen)
int datfd;
long offset;
int reclen;
{
if (lseek(datfd, offset, 0) != offset)
return ((char *) NULL);
if (read(datfd, recordbuffer, reclen + 1) != (reclen + 1))
return ((char *) NULL);
if (recordbuffer[0] == FL_RECDELETED)
return ((char *) NULL);
return (recordbuffer + 1);
}
/* rp_readrecord_v() - Read a record from .rec file */
Static char *
rp_readrecord_v(datfd, varfd, offset, minreclen, maxreclen)
int datfd, varfd;
long offset;
int minreclen, maxreclen;
{
long tailoff;
char frameheadbuf [2 * SHORTSIZE];
int taillen;
if (lseek(datfd, offset, 0) != offset)
return ((char *) NULL);
if (read(datfd, recordbuffer, minreclen + LONGSIZE) != (minreclen + LONGSIZE))
return ((char *) NULL);
if ((tailoff = ldlong(recordbuffer)) == VL_RECDELETED)
return ((char *) NULL);
isreclen = minreclen;
/* Recover tail of the record */
if (tailoff != VL_RECNOTAIL) {
if (lseek(varfd, tailoff, 0) != tailoff)
goto OKEXIT;
if (read(varfd, frameheadbuf, 2 * SHORTSIZE) != 2 * SHORTSIZE)
goto OKEXIT;
taillen = (int) ldshort(frameheadbuf + VR_TAILLEN_OFF);
if (taillen <= 0 || taillen + minreclen > maxreclen)
goto OKEXIT;
if (read(varfd, recordbuffer + LONGSIZE + isreclen, taillen) != taillen)
goto OKEXIT;
isreclen += taillen;
}
OKEXIT:
return (recordbuffer + LONGSIZE);
}
static int
isnoprintf(const char *s, ...)
{
return(0);
}
static
printkey(n, pkdesc, print)
int n;
struct keydesc *pkdesc;
int (*print)();
{
int i;
struct keypart *pk;
if (pkdesc->k_nparts == 0) {
print("%3d: --- NO PRIMARY KEY ---\n", n);
return;
}
if (n == 1)
print("P%3d: %s ", n, (pkdesc->k_flags&ISDUPS) ?
"DUPS " : "NODUPS");
else
print(" %3d: %s ", n, (pkdesc->k_flags&ISDUPS) ?
"DUPS " : "NODUPS");
for (i = 0; i < pkdesc->k_nparts; i++) {
pk = pkdesc->k_part + i;
print(" %d%c%d%s", pk->kp_start,
typeletter(pk->kp_type & ~ISDESC), pk->kp_leng,
(pk->kp_type & ISDESC)?"D":" ");
}
print("\n");
}
static
cmd_error(str,print)
char *str;
int (*print)();
{
(void)print("%s: ISAM error %d\n", str, iserrno);
}
static int
typeletter(type)
int type;
{
switch (type) {
case INTTYPE:
return 'I';
case LONGTYPE:
return 'L';
case FLOATTYPE:
return 'F';
case DOUBLETYPE:
return 'D';
case CHARTYPE:
return 'C';
case BINTYPE:
return 'B';
default:
assert(0);
}
/* NOTREACHED */
}

View File

@@ -0,0 +1,247 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isrewcurr.c /main/3 1995/10/23 11:44:15 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isrewcurr.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isrewcurr.c
*
* Description:
* Rewrite current record in ISAM file.
*/
#include "isam_impl.h"
#include <sys/time.h>
static int _amrewcurr(), _changekeys2();
/*
* err = isrewcurr(isfd, record)
*
* Isrewcurr() modifies the current record in ISAM file.
* All indexes of the ISAM file are updated.
*
* Current record position is changed in relation to the new key value.
* isrecnum is set to the changed record.
*
* If the ISAM file is for variable length records, the isreclen variable
* must be set to indicate the actual length of the record, which must
* be between the minimum and maximum length, as specified in isbuild().
*
* Returns 0 if successful, or -1 of any error.
*
* Errors:
* EDUPL The write woul result in a duplicate on a key that
* does not allow duplicates.
* ELOCKED The file has been locked by another process.
* ENOTOPEN isfd does not correspond to an open ISAM file, or the
* ISAM file was not opened with ISINOUT mode.
* ENOCURR Record with record number recnum does not exist, or it
* was deleted by another process.
*/
int
isrewcurr(isfd, record)
int isfd;
char *record;
{
register Fab *fab;
int reclen;
int ret;
int recnum;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISINOUT.
*/
if (fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Determine record length. Check it against min and max record length.
*/
reclen = (fab->varlength == TRUE) ? isreclen : fab->minreclen;
if (reclen < fab->minreclen || reclen > fab->maxreclen) {
_setiserrno2(EBADARG, '9', '0');
return (ISERROR);
}
if ((ret = _amrewcurr(&fab->isfhandle, record, reclen, &fab->curpos,
&recnum, &fab->errcode)) == ISOK) {
isrecnum = recnum; /* Set isrecnum */
}
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}
/*
* _amrewcurr(isfhandle, record, reclen, curpos, recnum, errcode)
*
* _amrewcurr() rewrites the current record in ISAM file.
*
* Input params:
* isfhandle Handle of ISAM file
* record record
* reclen length of the record
* curpos curent record position
*
* Output params:
* errcode error status of the operation
* curpos new current position
* recnum record number fo current record
*
*/
static int
_amrewcurr(isfhandle, record, reclen, curpos, recnum, errcode)
Bytearray *isfhandle;
char *record;
int reclen;
Recno *recnum;
Bytearray *curpos;
struct errcode *errcode;
{
Fcb *fcb;
Crp *crp;
Bytearray newcurpos;
int err;
char oldrecord[ISMAXRECLEN];
int reclen2;
int (*rec_read)();
int (*rec_rewrite)();
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
rec_rewrite = (fcb->varflag?_vlrec_rewrite:_flrec_rewrite);
/*
* Get info from current record position structure.
*/
crp = (Crp *) curpos->data;
if (crp->flag != CRP_ON) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r2(fcb);
/*
* We must read the record first to be able to delete keys.
*/
if (rec_read(fcb, oldrecord, crp->recno, &reclen2) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
if (rec_rewrite(fcb, record, crp->recno, reclen) != ISOK) {
_amseterrcode(errcode, ENOCURR);
goto ERROR;
}
/*
* Update keys, set new key position.
*/
newcurpos = _bytearr_dup(curpos);
if ((err = _changekeys2 (fcb, record, oldrecord, crp->recno, &newcurpos))
!= ISOK) {
_bytearr_free(&newcurpos);
_amseterrcode(errcode, err);
goto ERROR;
}
_bytearr_free(curpos);
*curpos = newcurpos;
/*
* This takes care of new record position if the physical order is in use.
*/
*recnum = crp->recno;
_amseterrcode(errcode, ISOK);
_issignals_mask();
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
/*
* Update control page.
*/
(void)_isfcb_cntlpg_w2(fcb);
_issignals_unmask();
_isam_exithook();
return (ISOK);
ERROR:
_isdisk_rollback();
_isdisk_inval();
/*
* Restore FCB from CNTL page.
*/
(void)_isfcb_cntlpg_r2(fcb);
_isam_exithook();
return (ISERROR);
}
Static int
_changekeys2(fcb, record, oldrecord, recnum, curpos)
Fcb *fcb;
char *record;
char *oldrecord;
Recno recnum;
Bytearray *curpos;
{
int nkeys = fcb->nkeys;
register int i;
int err;
Crp *crp;
int keyid;
Keydesc2 *keydesc2;
crp = (Crp *)curpos->data;
keyid = crp->keyid;
for (i = 0; i < nkeys; i++) {
keydesc2 = fcb->keys + i;
if ((err =_change1key(fcb, keydesc2, record, oldrecord, recnum,
(keydesc2->k2_keyid == keyid) ?
crp->key : (char *) NULL)) != ISOK)
return (err);
}
return (ISOK);
}

View File

@@ -0,0 +1,213 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isrewrec.c /main/3 1995/10/23 11:44:28 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isrewrec.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isrewrec.c
*
* Description:
* Rewrite a record in ISAM file.
*/
#include "isam_impl.h"
#include <sys/time.h>
static int _amrewrec(), _changekeys();
/*
* err = isrewrec(isfd, recnum, record)
*
* Isrewrec() modifies a record in ISAM file. The record is identified
* by its record number. All indexes of the ISAM file are updated.
*
* Current record position is not changed.
* isrecnum is set to recnum.
*
* If the ISAM file is for variable length records, the isreclen variable
* must be set to indicate the actual length of the record, which must
* be between the minimum and maximum length, as specified in isbuild().
*
* Returns 0 if successful, or -1 of any error.
*
* Errors:
* EDUPL The write woul result in a duplicate on a key that
* does not allow duplicates.
* ELOCKED The file has been locked by another process.
* ENOTOPEN isfd does not correspond to an open ISAM file, or the
* ISAM file was not opened with ISINOUT mode.
* ENOREC Record with record number recnum does not exist.
*/
int
isrewrec(isfd, recnum, record)
int isfd;
long recnum;
char *record;
{
register Fab *fab;
int reclen;
int ret;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISINOUT.
*/
if (fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Determine record length. Check it against min and max record length.
*/
reclen = (fab->varlength == TRUE) ? isreclen : fab->minreclen;
if (reclen < fab->minreclen || reclen > fab->maxreclen) {
_setiserrno2(EBADARG, '9', '0');
return (ISERROR);
}
if ((ret = _amrewrec(&fab->isfhandle, record,
reclen, recnum, &fab->errcode)) == ISOK) {
isrecnum = recnum; /* Set isrecnum */
}
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}
/*
* _amrewrec(isfhandle, record, reclen, recnum, errcode)
*
* _amrewrec() rewrites a record in ISAM file.
*
* Input params:
* isfhandle Handle of ISAM file
* record record
* reclen length of the record
* recnum record number of record to be deleted
*
* Output params:
* errcode error status of the operation
*
*/
static int
_amrewrec(isfhandle, record, reclen, recnum, errcode)
Bytearray *isfhandle;
char *record;
int reclen;
Recno recnum;
struct errcode *errcode;
{
Fcb *fcb;
char oldrecbuf[ISMAXRECLEN];
int err;
int reclen2;
int (*rec_read)();
int (*rec_rewrite)();
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
rec_rewrite = (fcb->varflag?_vlrec_rewrite:_flrec_rewrite);
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r2(fcb);
/*
* We must read the record first to be able to delete keys.
*/
if (rec_read(fcb, oldrecbuf, recnum, &reclen2) != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
if (rec_rewrite(fcb, record, recnum, reclen) != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
/*
* Update all keys.
*/
if ((err = _changekeys(fcb, record, oldrecbuf, recnum)) != ISOK) {
_amseterrcode(errcode, err);
goto ERROR;
}
_amseterrcode(errcode, ISOK);
_issignals_mask();
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
/*
* Update control page.
*/
(void)_isfcb_cntlpg_w2(fcb);
_issignals_unmask();
_isam_exithook();
return (ISOK);
ERROR:
_isdisk_rollback();
_isdisk_inval();
/*
* Restore FCB from CNTL page.
*/
(void)_isfcb_cntlpg_r2(fcb);
_isam_exithook();
return (ISERROR);
}
static int
_changekeys (fcb, record, oldrecord, recnum)
Fcb *fcb;
char *record;
char *oldrecord;
Recno recnum;
{
int nkeys = fcb->nkeys;
register int i;
int err;
for (i = 0; i < nkeys; i++) {
if ((err =_change1key(fcb, fcb->keys + i, record, oldrecord, recnum,
(char *)NULL))
!= ISOK)
return (err);
}
return (ISOK);
}

View File

@@ -0,0 +1,76 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: issignals.c /main/3 1995/10/23 11:44:41 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)issignals.c 1.7 89/08/30 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* issignals.c
*
* Description:
* Signal masking functions
*/
#include "isam_impl.h"
#include <signal.h>
/*
* _issignal_mask() is called at the beginning of each ISAM update operation
* to mask signals for the duration of the operation. _issignals_unmask()
* is called at the end of the operation to restore the original signal
* mask.
*
* _issignals_cntl() enables/disables this signal masking facility.
* (the default is "mask the signals").
*
* The variable already_masked is used to provide more robustness: it
* will prevent permanent signal masking due to bugs in the ISAM package.
* The permanent masking of signals would happen if _issignals_mask()
* were called twice in a row.
*/
static int do_mask = 1; /* default value */
static int already_masked;
static sigset_t oldmask;
static sigset_t allsignals;
_issignals_cntl(opt)
int opt; /* 1 will enable masking */
/* 0 will disable masking */
{
int oldmask = do_mask;
do_mask = opt ? 1 : 0;
return (oldmask);
}
_issignals_mask()
{
if (do_mask && !already_masked) {
(void) sigfillset(&allsignals);
(void) sigdelset(&allsignals, SIGTRAP);
(void) sigdelset(&allsignals, SIGSEGV);
(void) sigdelset(&allsignals, SIGILL);
(void) sigdelset(&allsignals, SIGBUS);
(void) sigprocmask(SIG_SETMASK, &allsignals, &oldmask);
already_masked = 1;
}
}
_issignals_unmask()
{
if (do_mask) {
(void)sigprocmask(SIG_SETMASK, &oldmask, NULL);
already_masked = 0;
}
}

View File

@@ -0,0 +1,132 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: issort.c /main/3 1995/10/23 11:44:55 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)issort.c 1.3 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* issort.c
*
* Description:
* ISAM sort package (sort in memory)
*/
#include "isam_impl.h"
extern char *_isunix_malloc();
/*
* _issort_create()
*
* Create a sorter
*/
Issort *
_issort_create(reclen,nrecs,compfunc)
int reclen;
int nrecs;
int (*compfunc)();
{
Issort *p;
p = (Issort *)_ismalloc(sizeof(*p)); /* Allocate new sorter */
memset((char *)p, 0,sizeof(*p));
p->ist_reclength = reclen; /* Record length in bytes */
p->ist_allocrecs = nrecs; /* Maximum number of records */
/* that can inserted */
p->ist_nrecs = 0; /* Current number of records */
p->ist_currec; /* Current position */
p->ist_compf = compfunc; /* Comparison function */
p->ist_array = _ismalloc((unsigned)(reclen * nrecs)); /* Allocate array */
/* for storing records */
return(p);
}
/*
* _issort_destroy()
*
* Destroy a sorter
*/
void
_issort_destroy(srt)
Issort *srt;
{
assert(srt->ist_array != (char *) 0);
(void) free(srt->ist_array);
(void) free((char *)srt);
}
/*
* _issort_insert()
*
* Insert record to sorter
*/
void
_issort_insert(srt,record)
register Issort *srt;
char *record;
{
assert(srt->ist_nrecs < srt->ist_allocrecs);
memcpy(srt->ist_array + srt->ist_nrecs * srt->ist_reclength,record,
srt->ist_reclength);
srt->ist_currec = srt->ist_nrecs++;
}
/*
* _issort_sort()
*
* Sort records
*/
void
_issort_sort(srt)
Issort *srt;
{
if (srt->ist_nrecs > 1)
qsort(srt->ist_array,srt->ist_nrecs,srt->ist_reclength,srt->ist_compf);
_issort_rewind(srt); /* Rewind for subsequent reads */
}
/*
* _issort_rewind()
*
* Rewind sorter
*/
void
_issort_rewind(srt)
Issort *srt;
{
srt->ist_currec = 0;
}
/*
* _issort_read()
*
* Read record from sorter
*/
char *
_issort_read(srt)
register Issort *srt;
{
return((srt->ist_currec < srt->ist_nrecs) ?
(srt->ist_array + srt->ist_currec++ * srt->ist_reclength) :
(char *) 0);
}

View File

@@ -0,0 +1,612 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isstart.c /main/3 1995/10/23 11:45:08 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isstart.c 1.9 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isstart.c
*
* Description:
* Select index and set record position.
*/
#include "isam_impl.h"
#include <sys/time.h>
static int _amstart();
/*
* err = isstart(isfd, keydesc, length, record, mode)
*
* Isstart() selects index for subsequent read operations and set new
* current record position.
*
* isrecnum is set to indicate the start record.
*
*
* Returns 0 if successful, or -1 of any error.
*
* Errors:
* ENOTOPEN isfd does not correspond to an open ISAM file, or the
* ISAM file was opened with ISOUTPUT mode.
* EBADARG Bad mode parameter.
* EBADARG keylen is out of range.
* ENOREC Specified record cannot be found (random access read).
* EBADKEY Error in the key descriptor.
*/
int
isstart(isfd, keydesc, length, record, mode)
int isfd;
struct keydesc *keydesc;
int length;
char *record;
int mode;
{
register Fab *fab;
int reclen;
Recno recnum;
int ret;
enum readmode readmode;
char dummy_record [1]; /* used for ISFIRST and ISLAST */
char *precord;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISINPUT, or ISINOUT.
*/
if (fab->openmode != OM_INPUT && fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Extract read mode.
*/
if ((readmode = _getreadmode(mode)) == RM_BADMODE) {
_setiserrno2(EBADARG, '9', '0');
return (ISERROR);
}
/*
* Some arguments are used only when a particular mode is specified.
*/
if (readmode == RM_FIRST || readmode == RM_LAST || USE_PHYS_ORDER(keydesc)) {
precord = dummy_record;
reclen = 0;
}
else {
precord = record;
reclen = fab->minreclen;
}
reclen = fab->minreclen;
recnum = isrecnum;
if ((ret = _amstart(&fab->isfhandle, precord, reclen,
readmode, keydesc, length, &fab->curpos,
&recnum, &fab->errcode)) == ISOK) {
isrecnum = recnum; /* Set isrecnum */
}
_seterr_errcode(&fab->errcode);
return (ret); /* Successful start */
}
/*
* _amstart(isfhandle, record, reclen, readmode,
* keydesc, keylen, curpos, recnum, errcode)
*
* _amstart() reads a record from ISAM file
*
* Input params:
* isfhandle Handle of ISAM file
* readmode Specifies access mode (random or sequential)
* curpos old record position
* recnum copy of isrecnum
* keydesc key descriptor
* keylen # of bytes of key to match
* record extract key from this record buffer
*
* Output params:
* curpos new current position
* recnum record number
* errcode error status of the operation
* reclen actual length of the record
*
* Note:
* Successfull isstart() returns the new curpos and frees the old curpos.
*/
/* ARGSUSED */
static int
_amstart(isfhandle, record, reclen, readmode,
keydesc, keylen, curpos, recnum, errcode)
Bytearray *isfhandle;
enum readmode readmode;
char *record;
int *reclen;
Bytearray *curpos;
Recno *recnum;
struct errcode *errcode;
struct keydesc *keydesc;
int keylen;
{
Fcb *fcb;
Recno recnum2;
int err;
Crp *newcrp = NULL;
char recbuf [ISMAXRECLEN];
Keydesc2 keydesc2;
Keydesc2 *pkeydesc2;
int newcrpsize = 0;
char keybuf1 [MAXKEYSIZE], keybuf2 [MAXKEYSIZE];
int matchkeylen;
int skipbytes;
char *pkey;
Btree *btree = NULL;
int reclen2;
int (*rec_read)();
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r2(fcb);
if (USE_PHYS_ORDER(keydesc)) {
/*
* Physical order in use.
*/
/*
* Allocate new current position structure.
*/
newcrpsize = sizeof(*newcrp);
newcrp = (Crp *) _ismalloc(sizeof(*newcrp));
memset ((char *)newcrp, 0, sizeof(*newcrp));
newcrp->keyid = PHYS_ORDER;
switch (readmode) {
case RM_EQUAL:
recnum2 = *recnum; /* passed from isrecnum */
if ((err = rec_read(fcb, recbuf, recnum2, &reclen2)) != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
newcrp->flag = CRP_BEFORE;
newcrp->recno = recnum2;
break;
case RM_GREAT:
recnum2 = *recnum + 1;
if (recnum2 < 1) recnum2 = 1;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, recbuf, recnum2, &reclen2)) != ISOK &&
err == ENOREC)
recnum2++;
if (err != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
newcrp->flag = CRP_BEFORE;
newcrp->recno = recnum2;
break;
case RM_GTEQ:
recnum2 = *recnum;
if (recnum2 < 1) recnum2 = 1;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, recbuf, recnum2, &reclen2)) != ISOK &&
err == ENOREC)
recnum2++;
if (err != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
newcrp->flag = CRP_BEFORE;
newcrp->recno = recnum2;
break;
case RM_LESS:
recnum2 = *recnum - 1;
if (recnum2 > fcb->lastrecno) recnum2 = fcb->lastrecno;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, recbuf, recnum2, &reclen2)) != ISOK &&
err == ENOREC)
recnum2--;
if (err != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
newcrp->flag = CRP_AFTER;
newcrp->recno = recnum2;
break;
case RM_LTEQ:
recnum2 = *recnum;
if (recnum2 > fcb->lastrecno) recnum2 = fcb->lastrecno;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, recbuf, recnum2, &reclen2)) != ISOK &&
err == ENOREC)
recnum2--;
if (err != ISOK) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
newcrp->flag = CRP_AFTER;
newcrp->recno = recnum2;
break;
case RM_FIRST:
recnum2 = 1;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, recbuf, recnum2, &reclen2)) != ISOK &&
err == ENOREC)
recnum2++;
if (err == ISOK) {
newcrp->flag = CRP_BEFORE;
newcrp->recno = recnum2;
}
else {
newcrp->flag = CRP_AFTERANY;
}
break;
case RM_LAST:
recnum2 = fcb->lastrecno;
/*
* Skip deleted records.
*/
while ((err = rec_read(fcb, recbuf, recnum2, &reclen2)) != ISOK &&
err == ENOREC)
recnum2--;
if (err == ISOK) {
newcrp->flag = CRP_AFTER;
newcrp->recno = recnum2;
}
else {
newcrp->flag = CRP_BEFOREANY;
}
break;
default:
_isfatal_error("Invalid readmode");
}
*recnum = recnum2;
/*
* Build new curpos, deallocate old curpos.
*/
_bytearr_free(curpos);
*curpos = _bytearr_new(sizeof(*newcrp), (char *)newcrp);
} /* physical order */
else {
/*
* Use order defined by some key.
*/
/*
* Check key descriptor for validity.
*/
if (_validate_keydesc(keydesc, fcb->minreclen) != ISOK) {
_amseterrcode(errcode, EBADKEY);
goto ERROR;
}
/*
* Convert key descriptor to internal form.
*/
_iskey_xtoi (&keydesc2, keydesc);
/* Find key decriptor in the FCB. */
if ((pkeydesc2 = _isfcb_findkey(fcb ,&keydesc2)) == NULL) {
_amseterrcode(errcode, EBADKEY);
goto ERROR;
}
/*
* skipkeybytes is set to the number of bytes in the beginning
* of the key:
* RECNOSIZE for ISNODUPS keys to skip recno part
* RECNOSIZE + DUPIDSIZE to skip recno and duplicate serial number
*/
skipbytes = RECNOSIZE;
if (ALLOWS_DUPS2(pkeydesc2))
skipbytes += DUPIDSIZE;
/*
* Validate keylen.
*/
if (keylen < 0 || keylen > pkeydesc2->k2_len - skipbytes) {
_amseterrcode(errcode, EBADARG);
goto ERROR;
}
/*
* Special case if keylen == 0: use the entire key.
*/
if (keylen == 0)
matchkeylen = pkeydesc2->k2_len - skipbytes;
else
matchkeylen = keylen;
/*
* Allocate new current record position.
*/
newcrpsize = sizeof(Crp) + pkeydesc2->k2_len;
newcrp = (Crp *) _ismalloc((unsigned)newcrpsize);
memset((char *)newcrp, 0, newcrpsize);
newcrp->keyid = pkeydesc2->k2_keyid; /* Key identifier in FCB */
newcrp->matchkeylen = matchkeylen; /* number of bytes to match */
/*
* Create B tree object.
*/
btree = _isbtree_create(fcb, pkeydesc2);
switch (readmode) {
case RM_EQUAL:
case RM_GTEQ:
/*
* Make sure that you will read the first duplicate.
*/
_iskey_fillmin(pkeydesc2, keybuf1);
/*
* Extract key fields from record.
*/
_iskey_extract(pkeydesc2, record, keybuf2);
memcpy( keybuf1 + skipbytes,keybuf2 + skipbytes, matchkeylen);
/*
* Position pointer in the B-tree in before the searched value.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_next(btree)) == NULL) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
if (readmode == RM_EQUAL &&
memcmp(keybuf1 + skipbytes, pkey + skipbytes,
matchkeylen) != 0) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
newcrp->flag = CRP_BEFORE;
newcrp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy( newcrp->key,pkey, pkeydesc2->k2_len);
break;
case RM_GREAT:
/*
* Make sure that you will read past all matching records.
*/
_iskey_fillmax(pkeydesc2, keybuf1);
/*
* Extract key fields from record.
*/
_iskey_extract(pkeydesc2, record, keybuf2);
memcpy( keybuf1 + skipbytes,keybuf2 + skipbytes, matchkeylen);
/*
* Position pointer in the B-tree after the searched value.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_next(btree)) == NULL) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
newcrp->flag = CRP_BEFORE;
newcrp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy( newcrp->key,pkey, pkeydesc2->k2_len);
break;
case RM_LESS:
/*
* Make sure that you will read before all matching records.
*/
_iskey_fillmin(pkeydesc2, keybuf1);
/*
* Extract key fields from record.
*/
_iskey_extract(pkeydesc2, record, keybuf2);
memcpy( keybuf1 + skipbytes,keybuf2 + skipbytes, matchkeylen);
/*
* Position pointer in the B-tree after the searched value.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_current(btree)) == NULL) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
newcrp->flag = CRP_AFTER;
newcrp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy( newcrp->key,pkey, pkeydesc2->k2_len);
break;
case RM_LTEQ:
/*
* Make sure that you will the last duplicate.
*/
_iskey_fillmax(pkeydesc2, keybuf1);
/*
* Extract key fields from record.
*/
_iskey_extract(pkeydesc2, record, keybuf2);
memcpy( keybuf1 + skipbytes,keybuf2 + skipbytes, matchkeylen);
/*
* Position pointer in the B-tree in before the searched value.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_current(btree)) == NULL) {
_amseterrcode(errcode, ENOREC);
goto ERROR;
}
newcrp->flag = CRP_AFTER;
newcrp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy( newcrp->key,pkey, pkeydesc2->k2_len);
break;
case RM_FIRST:
/*
* Fill key buffer with -infinity.
*/
_iskey_fillmin(pkeydesc2, keybuf1);
/*
* Position pointer in the B-tree before any key entry.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_next(btree)) == NULL) {
newcrp->flag = CRP_AFTERANY;
}
else {
newcrp->flag = CRP_BEFORE;
newcrp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy( newcrp->key,pkey, pkeydesc2->k2_len);
}
break;
case RM_LAST:
/*
* Fill key buffer with +infinity.
*/
_iskey_fillmax(pkeydesc2, keybuf1);
/*
* Position pointer in the B-tree after all entries.
*/
_isbtree_search(btree, keybuf1);
if ((pkey = _isbtree_current(btree)) == NULL) {
newcrp->flag = CRP_BEFOREANY;
}
else {
newcrp->flag = CRP_AFTER;
newcrp->recno = ldrecno(pkey + KEY_RECNO_OFF);
memcpy( newcrp->key,pkey, pkeydesc2->k2_len);
}
break;
default:
_isfatal_error("Invalid readmode");
}
*recnum = newcrp->recno;
/*
* Build new curpos, deallocate old curpos data.
*/
_bytearr_free(curpos);
*curpos = _bytearr_new((u_short)newcrpsize, (char *)newcrp);
_isbtree_destroy(btree);
}
_amseterrcode(errcode, ISOK);
/* Clean-up work. */
if (newcrp != NULL)
free((char *)newcrp);
_isdisk_commit(); /* This will only check
* that we unfixed all fixed
* buffers */
_isdisk_inval();
_isam_exithook();
return (ISOK);
ERROR:
if (btree != NULL)
_isbtree_destroy(btree);
/*
* If error is EBADKEY, make the current position undefined.
*/
if (errcode->iserrno == EBADKEY) {
((Crp *)curpos->data)->flag = CRP_UNDEF;
}
/*
* If error is ENOREC, switch to the new key, but set the current
* record position undefined.
*/
if (errcode->iserrno == ENOREC && newcrp != NULL) {
_bytearr_free(curpos);
*curpos = _bytearr_new((u_short)newcrpsize, (char *)newcrp);
((Crp *)curpos->data)->flag = CRP_UNDEF;
}
if (newcrp != NULL)
free((char *)newcrp);
_isdisk_inval();
_isam_exithook();
return (ISERROR);
}

View File

@@ -0,0 +1,112 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: issync.c /main/3 1995/10/23 11:45:20 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)issync.c 1.7 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* issync.c
*
* Description:
* Sync all kernel buffers to the disk.
*
* Note: issync() flushes changed kernel buffers that are local to
* the application that issued the call.
*
* See sync(2) UNIX manual for what actually happens if sync() is called.
*/
#include "isam_impl.h"
#include <sys/file.h>
#include <sys/time.h>
/*
* int issync()
*/
int
issync()
{
return iscntl(ALLISFD, ISCNTL_FSYNC);
}
/*
* int isfsync(fd)
*/
int
isfsync(isfd)
int isfd;
{
return iscntl(isfd, ISCNTL_FSYNC);
}
_issync()
{
int i;
for (i = 0; i < MAXISFD; i++)
(void)_isfsync(i);
return (ISOK);
}
_isfsync(isfd)
int isfd;
{
register Fab *fab;
Fcb *fcb;
int ret;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISINPUT, or ISINOUT.
*/
if (fab->openmode != OM_INPUT && fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(&fab->isfhandle, &fab->errcode)) == NULL) {
_isam_exithook();
ret = ISERROR;
}
else {
if (fcb->datfd != -1)
(void)fsync(fcb->datfd);
if (fcb->indfd != -1)
(void)fsync(fcb->indfd);
if (fcb->varfd != -1)
(void)fsync(fcb->varfd);
_amseterrcode(&fab->errcode, ISOK);
_isam_exithook();
ret = ISOK;
}
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}

View File

@@ -0,0 +1,581 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isvarrec.c /main/3 1995/10/23 11:45:36 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isvarrec.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isvarrec.c
*
* Description:
* Fixed length record access (VLRA) module.
*/
#include "isam_impl.h"
/* Local functions */
long _vl_getpos(); /* Get offset in .rec file */
int _vl_deleted(); /* 0/1 returns 1 if record is deleted */
static void remove_from_chain2(); /* used by _vlrec_wrrec() */
long _istail_insert();
static void _istail_delete();
static _istail_read();
/*
* _vlrec_write(fcb, record, recnum, reclen)
*
* Write a record.
*
* Input params:
* FCB File Control Block
* record record buffer
* reclen record length (NOT USED)
*
* Output params:
* recnum record number of the new record
*
* Returns 0 if record was written succesfully, or -1 if any error.
*/
/*ARGSUSED*/
int
_vlrec_write(fcb, record, recnum, reclen)
register Fcb *fcb;
char *record;
Recno *recnum;
int reclen;
{
Recno recnum2;
long rec_position;
long tailoff = VL_RECNOTAIL;
char recnobuf [RECNOSIZE];
char tailoffbuf[LONGSIZE];
/*
* Reuse a deleted record if one exits.
* Otherwise, extend .rec file by a record.
*/
if (fcb->freerecno != NULL_RECNO) {
recnum2 = fcb->freerecno;
/*
* Remove record from the chain of deleted records.
*/
rec_position = _vl_getpos(fcb, recnum2); /* Offset in .rec file */
_cp_fromfile(fcb, fcb->datfd, recnobuf, rec_position + LONGSIZE, RECNOSIZE);
fcb->freerecno = ldrecno(recnobuf);
}
else {
recnum2 = ++(fcb->lastrecno);
/*
* Extend .rec file size if necessary.
*/
while (_vl_getpos(fcb, recnum2 + 1) > fcb->datsize * ISPAGESIZE) {
fcb->datsize = _extend_file(fcb, fcb->datfd, fcb->datsize);
}
rec_position = _vl_getpos(fcb, recnum2); /* Offset in .rec file */
}
/*
* Store variable part of record (the 'tail') in .var file.
*/
tailoff = _istail_insert(fcb, record + fcb->minreclen,
reclen - fcb->minreclen);
/*
* Copy record to the .rec file. Mark record as undeleted.
*/
stlong(tailoff, tailoffbuf);
_cp_tofile(fcb, fcb->datfd, tailoffbuf, rec_position, LONGSIZE);
_cp_tofile(fcb, fcb->datfd, record, rec_position + LONGSIZE, fcb->minreclen);
*recnum = recnum2;
return (ISOK);
}
/*
* _vlrec_read(fcb, record, recnum, reclen)
*
* Read a record.
*
* Input params:
* FCB File Control Block
* recnum record number of the record
* reclen filled with the record size for compatibilty with
* variable length records
*
* Output params:
* record record buffer is filled with data
*
* Returns 0 if record was read succesfully, or error code if any error.
*/
int
_vlrec_read(fcb, record, recnum, reclen)
register Fcb *fcb;
char *record;
Recno recnum;
int *reclen;
{
long rec_position;
long tailoff;
char tailoffbuf[LONGSIZE];
/*
* Check that recnum is within the range of existing record numbers.
*/
if (recnum < 1 || recnum > fcb->lastrecno)
return (EENDFILE);
rec_position = _vl_getpos(fcb, recnum); /* Offset in .rec file */
/*
* Check that the record is not marked as deleted.
*/
_cp_fromfile(fcb, fcb->datfd, tailoffbuf, rec_position, LONGSIZE);
tailoff = ldlong(tailoffbuf);
if (tailoff == VL_RECDELETED) {
return (ENOREC);
}
/*
* Copy record from the .at file.
*/
_cp_fromfile(fcb, fcb->datfd, record, rec_position + LONGSIZE, fcb->minreclen);
*reclen = fcb->minreclen;
/*
* Get the 'tail' of the record if any.
*/
*reclen += _istail_read(fcb, tailoff, record + fcb->minreclen);
if (*reclen > fcb->maxreclen)
_isfatal_error("Corrupted file: too long variable length record");
return (ISOK);
}
/*
* pos = _vl_getpos(fcb, recnum)
*
* Calculate the position of record in .rec file.
*/
long
_vl_getpos(fcb, recnum)
Fcb *fcb;
Recno recnum;
{
return ((long)(ISCNTLSIZE + (fcb->minreclen + LONGSIZE) * (recnum -1)));
}
/*
* _vlrec_rewrite(fcb, record, recnum, reclen)
*
* Rewrite a record.
*
* Input params:
* FCB File Control Block
* recnum record number of the record
* record new record
* int reclen (NOT USED)
*
* Returns 0 if record was rewritten succesfully, or error code if any error.
*/
/*ARGSUSED*/
int
_vlrec_rewrite(fcb, record, recnum, reclen)
register Fcb *fcb;
char *record;
Recno recnum;
int reclen;
{
long rec_position;
long tailoff;
char tailoffbuf[LONGSIZE];
/*
* Check that recnum is within the range of existing record numbers.
*/
if (recnum < 1 || recnum > fcb->lastrecno)
return (EENDFILE);
rec_position = _vl_getpos(fcb, recnum); /* Offset in .rec file */
/*
* Check that the record is not marked as deleted.
*/
_cp_fromfile(fcb, fcb->datfd, tailoffbuf, rec_position, LONGSIZE);
tailoff = ldlong(tailoffbuf);
if (tailoff == VL_RECDELETED) {
return (ENOREC);
}
/*
* Store variable part of record (the 'tail') in .var file.
*/
tailoff = _istail_modify(fcb, tailoff, record + fcb->minreclen,
reclen - fcb->minreclen);
/*
* Copy new record to the .rec file.
*/
stlong(tailoff, tailoffbuf);
_cp_tofile(fcb, fcb->datfd, tailoffbuf, rec_position, LONGSIZE);
_cp_tofile(fcb, fcb->datfd, record, rec_position + LONGSIZE, fcb->minreclen);
return (ISOK);
}
/*
* _vlrec_delete;(fcb, recnum)
*
* Rewrite a record.
*
* Input params:
* FCB File Control Block
* recnum record number of the record
*
* Returns 0 if record was rewritten succesfully, or error code if any error.
*/
int
_vlrec_delete(fcb, recnum)
register Fcb *fcb;
Recno recnum;
{
long rec_position;
long tailoff;
char tailoffbuf[LONGSIZE];
char recnobuf [RECNOSIZE];
/*
* Check that recnum is within the range of existing record numbers.
*/
if (recnum < 1 || recnum > fcb->lastrecno)
return (EENDFILE);
rec_position = _vl_getpos(fcb, recnum); /* Offset in .rec file */
/*
* Check that the record is not marked as deleted.
*/
_cp_fromfile(fcb, fcb->datfd, tailoffbuf, rec_position, LONGSIZE);
tailoff = ldlong(tailoffbuf);
if (tailoff == VL_RECDELETED) {
return (ENOREC);
}
/*
* Set the delete flag to VL_RECDELETED.
*/
tailoff = VL_RECDELETED;
stlong(tailoff, tailoffbuf);
_cp_tofile(fcb, fcb->datfd, tailoffbuf, rec_position, LONGSIZE);
/*
* Insert record into chain of deleted records.
*/
strecno(fcb->freerecno, recnobuf);
_cp_tofile(fcb, fcb->datfd, recnobuf, rec_position + LONGSIZE, RECNOSIZE);
fcb->freerecno = recnum;
/*
* Delete tail from .var file.
*/
return (ISOK);
}
/*
* _vlrec_wrrec(fcb, record, recnum, reclen)
*
* Write a record by record number.
*
* Input params:
* FCB File Control Block
* recnum record number of the record
* record record buffer
* int reclen (NOT USED)
*
* Returns 0 if record was written succesfully, or error code if any error.
*
* Note that _vlrec_wrrec() commits updates and syncs the FCB to avoid
* buffer pool overflow.
*/
/*ARGSUSED*/
int
_vlrec_wrrec(fcb, record, recnum, reclen)
register Fcb *fcb;
char *record;
Recno recnum;
int reclen;
{
long rec_position;
long tailoff;
char tailoffbuf[LONGSIZE];
Recno recnum2;
char recnumbuf [RECNOSIZE];
/*
* Check that recnum is not negative.
*/
if (recnum < 1)
return (EBADARG);
rec_position = _vl_getpos(fcb, recnum); /* Offset in .rec file */
if (recnum > fcb->lastrecno) {
/*
* If the recnum is bigger than the highest record number in the .rec
* file, extend the .rec file.
*/
while (_vl_getpos(fcb, recnum + 1) > fcb->datsize * ISPAGESIZE) {
fcb->datsize = _extend_file(fcb, fcb->datfd, fcb->datsize);
/* Sync the updates to avoid buffer pool overflow. */
_isdisk_commit();
_isdisk_sync();
(void)_isfcb_cntlpg_w2(fcb);
}
/*
* Mark all records in the range <fcb->lastrecno+1, recnum> as
* deleted.
*/
tailoff = VL_RECDELETED;
stlong(tailoff, tailoffbuf);
for (recnum2 = fcb->lastrecno + 1; recnum2 <= recnum; recnum2++) {
_cp_tofile(fcb, fcb->datfd, tailoffbuf, _vl_getpos(fcb, recnum2), LONGSIZE);
strecno(fcb->freerecno, recnumbuf);
_cp_tofile(fcb, fcb->datfd, recnumbuf,
_vl_getpos(fcb, recnum2) + LONGSIZE, RECNOSIZE);
fcb->freerecno = recnum2;
/* Sync the updates to avoid buffer pool overflow. */
_isdisk_commit();
_isdisk_sync();
fcb->lastrecno = recnum;
(void)_isfcb_cntlpg_w2(fcb);
}
/*
* Note that the disk structures are in a consistent state now,
* the .rec was extended by a few records marked as 'deleted'.
* This is important for subsequent rollbacks.
*/
}
/*
* If recnum specifies a record that has existed, check whether it
* has been deleted. _vlrec_wrrec() does not override existing record.
*/
_cp_fromfile(fcb, fcb->datfd, tailoffbuf, rec_position, LONGSIZE);
tailoff = ldlong(tailoffbuf);
if (tailoff != VL_RECDELETED) {
return (EDUPL);
}
/*
* Remove the record from the chain of deleted records.
*/
remove_from_chain2(fcb, recnum);
/*
* Store variable part of record (the 'tail') in .var file.
*/
tailoff = _istail_insert(fcb, record + fcb->minreclen, reclen - fcb->minreclen);
/*
* Copy new record to the .rec file.
*/
stlong(tailoff, tailoffbuf);
_cp_tofile(fcb, fcb->datfd, tailoffbuf, rec_position, LONGSIZE);
_cp_tofile(fcb, fcb->datfd, record, rec_position + LONGSIZE, fcb->minreclen);
return (ISOK);
}
/*
* remove_from_chain(fcb, recnum)
*
* Remove record from the chain of deleted records.
*/
static void
remove_from_chain2(fcb, recnum)
Fcb *fcb;
Recno recnum;
{
char recnobuf1 [RECNOSIZE] , recnobuf2 [RECNOSIZE];
long pos1, pos2;
Recno recnum2;
pos1 = _vl_getpos(fcb, recnum);
_cp_fromfile(fcb, fcb->datfd, recnobuf1, pos1 + LONGSIZE, RECNOSIZE);
if (fcb->freerecno == recnum) {
fcb->freerecno = ldrecno(recnobuf1);
}
else {
recnum2 = fcb->freerecno;
do {
pos2 = _vl_getpos(fcb, recnum2);
_cp_fromfile(fcb, fcb->datfd, recnobuf2, pos2 + LONGSIZE, RECNOSIZE);
recnum2 = ldrecno(recnobuf2);
} while (recnum2 != recnum && recnum2 != NULL_RECNO);
_cp_tofile(fcb, fcb->datfd, recnobuf1, pos2 + LONGSIZE, RECNOSIZE);
}
}
/*
* The following are functions that manipulate the 'tails' of variable
* records. The tail is the actual record with the fixed part removed
* (fixed part starts at offset zero and its length is minimum record
* length. The tails are stored in the .var file.
*/
/* Insert tail into .var file. Return offset in .var file */
long _istail_insert(fcb, tailp, taillen)
Fcb *fcb;
char *tailp;
int taillen;
{
char frameheadbuf [2 * SHORTSIZE];
int framelen;
long offset;
/* printf ("_insert called, taillen %d\n", taillen); */
if (taillen == 0)
return (VL_RECNOTAIL);
framelen = taillen + 2 * SHORTSIZE;
/*
* Set up frame header.
*/
stshort((short)taillen, frameheadbuf + VR_FRAMELEN_OFF);
stshort((short)taillen, frameheadbuf + VR_TAILLEN_OFF);
offset = fcb->varend;
/*
* Extend .var file if that is necesary.
*/
while (offset + framelen > fcb->varsize * ISPAGESIZE)
fcb->varsize = _extend_file(fcb, fcb->varfd, fcb->varsize);
/*
* Copy frame head and tail to .var file.
*/
_cp_tofile(fcb, fcb->varfd, frameheadbuf, offset, 2 * SHORTSIZE);
_cp_tofile(fcb, fcb->varfd, tailp, offset + 2 * SHORTSIZE, taillen);
fcb->varend += taillen + 2 * SHORTSIZE;
return (offset);
}
/* Remove tail from .var file */
/* ARGSUSED */
Static void _istail_delete(fcb, offset)
Fcb *fcb;
long offset;
{
/*
* Don't do anything in NetISAM 1.0. The tails are lost, the space
* will be re-used after next restructuring: "copy -c file" command
*/
return;
}
/* Read tail from .var file */
Static _istail_read(fcb, offset, buffer)
Fcb *fcb;
long offset;
char *buffer;
{
char frameheadbuf [2 * SHORTSIZE];
int taillen;
/* printf ("_read called, offset %d\n", offset); */
if (offset == VL_RECNOTAIL)
return (0);
/*
* Read frame header.
*/
_cp_fromfile(fcb, fcb->varfd, frameheadbuf, offset, 2 * SHORTSIZE);
taillen = ldshort(frameheadbuf + VR_TAILLEN_OFF);
_cp_fromfile(fcb, fcb->varfd, buffer, offset + 2 * SHORTSIZE, taillen);
return (taillen);
}
/* Rewrite tail. Returns -1 if the new tail is longer than the original frame */
int _istail_modify(fcb, offset, tailp, taillen)
Fcb *fcb;
long offset;
int taillen;
char *tailp;
{
char frameheadbuf [2 * SHORTSIZE];
int framelen;
/*
* Trivial case: no old frame, no new tail.
*/
if (offset == VL_RECNOTAIL && taillen == 0)
return (offset);
if (offset != VL_RECNOTAIL) {
/*
* Read frame header.
*/
_cp_fromfile(fcb, fcb->varfd, frameheadbuf, offset, 2 * SHORTSIZE);
framelen = ldshort(frameheadbuf + VR_FRAMELEN_OFF);
}
else
framelen = 0;
if (taillen > framelen) {
/*
* Delete the old frame if the new tail does not fit.
* Insert the new tail at the end of .var file.
*/
_istail_delete(fcb, offset);
return (_istail_insert(fcb, tailp, taillen));
}
else {
/*
* The new tail fits in the existing frame.
*/
stshort((short)taillen, frameheadbuf + VR_TAILLEN_OFF);
_cp_tofile(fcb, fcb->varfd, frameheadbuf, offset, 2 * SHORTSIZE);
_cp_tofile(fcb, fcb->varfd, tailp, offset + 2 * SHORTSIZE, taillen);
return (offset);
}
}

View File

@@ -0,0 +1,38 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isvars.c /main/3 1995/10/23 11:45:48 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isvars.c 1.7 90/08/15 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isvars.c
*
* Description:
* NetISAM gloabl variables
*
*/
#include "isam_impl.h"
int iserrno;
int isreclen;
long isrecnum;
char isstat1, isstat2, isstat3, isstat4;
static struct keydesc _nokey;
struct keydesc *nokey = &_nokey;
/*
* isdupl is used internally to indicate that some index contains
* a duplicate value. Used only to set up isstat2 Cobol variable.
*/
int isdupl; /* 1 if duplicate found */

View File

@@ -0,0 +1,23 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isversion.c /main/3 1995/10/23 11:46:03 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)isversion.c 1.5 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988, 1992 by Sun Microsystems, Inc.
*/
/*
* isversion.c
*
* Description:
* Keep version for Customer Support benefit
* Since this version is considered part of ToolTalk, use the
* ToolTalk version number.
*
*/
char _isam_version[] = TT_VERSION_STRING;

View File

@@ -0,0 +1,113 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iswrite.c /main/3 1995/10/23 11:46:15 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iswrite.c 1.8 89/07/17 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iswrite.c
*
* Description:
* Write a record to ISAM file.
*/
#include "isam_impl.h"
#include <sys/file.h>
#include <sys/time.h>
static int _am_write();
/*
* err = iswrite(isfd, record)
*
* Iswrite() adds a new record to an ISAM file. All indexes of the ISAM
* file are updated.
*
* Current record position is not changed.
* isrecnum is set to indicate the new record.
*
* If the ISAM file is for variable length records, the isreclen variable
* must be set to indicate the actual length of the record, which must
* be between the minimum and maximum length, as specified in isbuild().
*
* Returns 0 if successful, or -1 of any error.
*
* Errors:
* EDUPL The write woul result in a duplicate on a key that
* does not allow duplicates.
* ELOCKED The file has been locked by another process.
* ENOTOPEN isfd does not correspond to an open ISAM file, or the
* ISAM file was opened with ISINPUT mode.
* EBADARG Unacceptable value of isreclen for variable length record.
*/
int
iswrite(isfd, record)
int isfd;
char *record;
{
int _am_write();
register Fab *fab;
int reclen;
Recno recnum;
Bytearray curpos;
int ret;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISOUTPUT, or ISINOUT.
*/
if (fab->openmode != OM_OUTPUT && fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Determine record length. Check it against min and max record length.
*/
reclen = (fab->varlength == TRUE) ? isreclen : fab->minreclen;
if (reclen < fab->minreclen || reclen > fab->maxreclen) {
_setiserrno2(EBADARG, '9', '0');
return (ISERROR);
}
/*
* Call the Access Method
*/
curpos = _bytearr_dup(&fab->curpos);
if ((ret = _am_write(fab, record, reclen, &curpos, &recnum)) == ISOK) {
isrecnum = recnum; /* Set isrecnum */
}
_bytearr_free(&curpos);
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}
Static int _am_write(fab, record, reclen, curpos, recnum)
register Fab *fab;
char *record;
int reclen;
Bytearray *curpos;
Recno *recnum;
{
return (_amwrite(&fab->isfhandle, record, reclen,
curpos, recnum, &fab->errcode));
}

View File

@@ -0,0 +1,184 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: iswrrec.c /main/3 1995/10/23 11:46:30 rswiston $ */
#ifndef lint
static char sccsid[] = "@(#)iswrrec.c 1.7 89/06/07 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* iswrrec.c
*
* Description:
* Write a record to ISAM file.
*/
#include "isam_impl.h"
#include <sys/time.h>
static int _amwrrec();
/*
* isfd = iswrrec(isfd, recnum, record)
*
* Iswrrec() writes a record to ISAM file at specified recno position.
* All indexes of the ISAM file are updated.
*
* Current record position is not changed.
* isrecnum is set to recnum.
*
* If the ISAM file is for variable length records, the isreclen variable
* must be set to indicate the actual length of the record, which must
* be between the minimum and maximum length, as specified in isbuild().
*
* Returns 0 if successful, or -1 of any error.
*
* Errors:
* EDUPL The write would result in a duplicate on a key that
* does not allow duplicates.
* ELOCKED The file has been locked by another process.
* ENOTOPEN isfd does not correspond to an open ISAM file, or the
* ISAM file was not opened with ISINOUT mode.
* EKEXISTS Record with recnum already exists.
* EBADARG recnum is negative.
*/
int
iswrrec(isfd, recnum, record)
int isfd;
long recnum;
char *record;
{
register Fab *fab;
int reclen;
int ret;
/*
* Get File Access Block.
*/
if ((fab = _isfd_find(isfd)) == NULL) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Check that the open mode was ISINOUT.
*/
if (fab->openmode != OM_INOUT) {
_setiserrno2(ENOTOPEN, '9', '0');
return (ISERROR);
}
/*
* Determine record length. Check it against min and max record length.
*/
reclen = (fab->varlength == TRUE) ? isreclen : fab->minreclen;
if (reclen < fab->minreclen || reclen > fab->maxreclen) {
_setiserrno2(EBADARG, '9' ,'0');
return (ISERROR);
}
if ((ret = _amwrrec(&fab->isfhandle, record, reclen,
recnum, &fab->errcode)) == ISOK) {
isrecnum = recnum; /* Set isrecnum */
}
_seterr_errcode(&fab->errcode);
return (ret); /* Successful write */
}
/*
* _amwrrec(isfhandle, record, reclen, recnum, errcode)
*
* _amwrrec() rewrites a record in ISAM file.
*
* Input params:
* isfhandle Handle of ISAM file
* record record
* reclen length of the record
* recnum record number of record to be deleted
*
* Output params:
* errcode error status of the operation
*
*/
static int
_amwrrec(isfhandle, record, reclen, recnum, errcode)
Bytearray *isfhandle;
char *record;
int reclen;
Recno recnum;
struct errcode *errcode;
{
Fcb *fcb = NULL;
int err;
int (*rec_wrrec)();
_isam_entryhook();
/*
* Get FCB corresponding to the isfhandle handle.
*/
if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
_isam_exithook();
return (ISERROR);
}
rec_wrrec = (fcb->varflag?_vlrec_wrrec:_flrec_wrrec);
/*
* Update information in FCB from CNTL page on the disk
*/
(void)_isfcb_cntlpg_r2(fcb);
if ((err = rec_wrrec(fcb, record, recnum, reclen)) != ISOK) {
_amseterrcode(errcode, err);
goto ERROR;
}
/*
* Update all keys.
*/
if ((err = _addkeys(fcb, record, recnum)) != ISOK) {
_amseterrcode(errcode, err);
goto ERROR;
}
fcb->nrecords++;
_amseterrcode(errcode, ISOK);
_issignals_mask();
_isdisk_commit();
_isdisk_sync();
_isdisk_inval();
/*
* Update CNTL Page from the FCB.
*/
(void)_isfcb_cntlpg_w2(fcb);
_issignals_unmask();
_isam_exithook();
return (ISOK);
ERROR:
_isdisk_rollback();
_isdisk_inval();
/*
* Restore FCB from CNTL page.
*/
if (fcb) (void)_isfcb_cntlpg_r2(fcb);
_isam_exithook();
return (ISERROR);
}

View File

@@ -0,0 +1,19 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: strdup.ultrix.c /main/3 1995/10/23 11:46:57 rswiston $ */
/* strdup - make duplicate of string s */
#include <string.h>
#include <malloc.h>
char *
strdup(char *s)
{
char *p;
p = (char *)malloc(strlen(s) + 1); /* + 1 for '\0' character */
if (p != NULL)
strcpy(p,s);
return p;
}