home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-12-12 | 35.0 KB | 1,422 lines |
- Newsgroups: comp.sources.misc
- subject: v09i063: umdb - UUCP Map Database - part 01/02
- from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Reply-To: wht%n4hgf@gatech.edu (Warren Tucker)
-
- Posting-number: Volume 9, Issue 63
- Submitted-by: wht%n4hgf@gatech.edu (Warren Tucker)
- Archive-name: umdb/part01
-
- This gaggle of programs uses a btree database to play around with masses
- of UUCP maps. The stuff is not so much a finished product as a toolbox
- for development of map-grokking tools. They are not efficient, but
- might be useful. For more details, see the README
-
- UMDBUILD builds the database.
-
- UMDBDUP prints duplicate system names.
-
- UMDBPATH prints expanded path information. IT CURRENTLY WORKS ONLY IF
- YOU HAVE SMAIL (by 'smail -A').
-
- ---- Cut Here and unpack ----
- #!/bin/sh
- # This is umdb, a shell archive (shar 3.04)
- # made 12/11/1989 01:41 UTC by gatech!kd4nc!n4hgf!wht (wht%n4hgf@gatech.edu)
- # Source directory /u4/src/umdb
- #
- # existing files WILL be overwritten
- #
- # This is part 1 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- #
- # This shar contains:
- # README
- # Makefile
- # btree.h
- # funcdefs.h
- # umdb.h
- # btree.c
- # diagnose.c
- # umdbdup.c
- # umdbpath.c
- # umdbuild.c
- # umdbutil.c
- #
- touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$
- if [ -s /tmp/s3_touch$$ ]
- then
- TOUCH=can
- else
- TOUCH=cannot
- fi
- rm -f /tmp/s3_touch$$
- if test -r s3_seq_.tmp
- then echo "Must unpack archives in sequence!"
- next=`cat s3_seq_.tmp`; echo "Please unpack part $next next"
- exit 1; fi
- echo "x - extracting README (Text)"
- sed 's/^X//' << 'SHAR_EOF' > README &&
- XUMDB Release x1.00 - Sun Dec 10 20:37:46 EST 1989
- X
- XThis gaggle of programs uses a btree database to play around with masses
- Xof UUCP maps. The stuff is not so much a finished product as a toolbox
- Xfor development of map-grokking tools. They are not efficient, but
- Xmight be useful.
- X
- XTO MAKE:
- X---------------------------------------------------------------------
- XEdit the Makefile if you are not running on SCO UNIX or XENIX 386 or
- Xa Pyramid in the BSD universe. Note that I have only tested the
- Xprograms on SCO UNIX/XENIX and a Pyramid. It hasn't been tested, but
- Xsome #defines are in the code for Sun.
- X
- XAdd to CFLAGS:
- X-DBSD4 for a BSD or Sun system.
- X-M2l for a XENIX 286 system. M_SYS5 provided by the compiler will do
- Xthe rest.
- XPyramid from the att universe, 'ucb make' :-).
- X
- XUMDBUILD
- X---------------------------------------------------------------------
- XUMDBUILD builds the database. To do it:
- Xsu root
- Xcd /.../.../map_directory
- Xumdbbuild /.../.../map_directory/[du].*
- XThis places the output database into /usr/lib/uucp/umdb.
- XA name index is placed in /usr/lib/uucp/umdb.in.
- XCode is present in the program to build a location index in
- X/usr/lib/uucp/umdb.il, but since no programs use it, production
- Xis turned off (to turn on, use -DBUILD_LOC_INDEX).
- X
- XUMDBDUP
- X---------------------------------------------------------------------
- XUMDBDUP prints duplicate system names. Example output:
- Xpei (pei) in /u3/lib/pathalias/u.usa.ca.5
- Xpei (pei) in /u3/lib/pathalias/u.usa.ca.8
- Xpepper (pepper) in /u3/lib/pathalias/u.fin.1
- Xpepper (pepper) in /u3/lib/pathalias/u.usa.co.1
- Xpporta (pporta) in /u3/lib/pathalias/u.usa.az.1
- Xpporta (pporta) in /u3/lib/pathalias/u.usa.ok.1
- Xsoft (softcon) in /u3/lib/pathalias/u.deu.2
- Xsoft (intra) in /u3/lib/pathalias/u.grc.1
- Xsssphx (sssphx) in /u3/lib/pathalias/u.usa.az.1
- Xsssphx (sssphx) in /u3/lib/pathalias/u.usa.ca.5
- X
- XUMDBPATH
- X---------------------------------------------------------------------
- XUMDBPATH prints expanded path information. IT CURRENTLY WORKS ONLY IF
- XYOU HAVE SMAIL (by 'smail -A'). I would love to receive patches
- Xfrom folks who get it working with other path generators.
- XExample output (from n4hgf perspective):
- X
- X% umdbpath sco
- Xpath: kd4nc!gatech!ames!sun!sco
- Xkd4nc 33.7500 N 82.3833 W city (u.usa.ga.1)
- X.gatech.edu 33.7753 N 84.3947 W (u.usa.ga.1)
- Xames 37.4172 N 122.0575 W (u.usa.ca.2)
- Xsun 37.4289 N 122.0969 W (u.usa.ca.8)
- Xsco 36.9667 N 122.0500 W city (u.usa.ca.8)
- X
- X% umdbpath proxima
- Xpath: kd4nc!gatech!ames!lll-winken!ddsw1!olsa99!tabbs!proxima
- Xkd4nc 33.7500 N 82.3833 W city (u.usa.ga.1)
- X.gatech.edu 33.7753 N 84.3947 W (u.usa.ga.1)
- Xames 37.4172 N 122.0575 W (u.usa.ca.2)
- Xlll-winken 37.6839 N 121.7106 W (u.usa.ca.6)
- Xddsw1 42.2833 N 87.9667 W city (u.usa.il.1)
- Xolsa99 26.0000 S 27.0000 E (u.zaf.1)
- Xtabbs 26.0000 S 27.0000 E (u.zaf.1)
- Xproxima 0.0000 N 0.0000 W ?? (u.zaf.1)
- X
- X% umdbpath oz
- Xpath: kd4nc!gatech!mailrus!uunet!munnari
- Xkd4nc 33.7500 N 82.3833 W city (u.usa.ga.1)
- X.gatech.edu 33.7753 N 84.3947 W (u.usa.ga.1)
- Xmailrus 42.2889 N 83.7144 W (u.usa.mi.2)
- X.uu.net 38.8833 N 77.0667 W (u.usa.va.2)
- Xmunnari not found: munnari.oz.au seems to match
- Xmunnari.oz.au 37.8086 S 144.9617 E (u.aus.vic.1)
- X
- X^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
- X1st name on #N line latitude, latitude basename of map
- X
- X-N SWITCH
- X---------------------------------------------------------------------
- XAll of the above programs accept an optional -n <umdb> to specify
- Xa database other than /u3/lib/uucp/umdb.
- X
- Xumdbbuild -n foo u.*
- X
- Xbuilds the databse in ./foo and the index in ./foo.in.
- X
- XDIAGNOSE
- X---------------------------------------------------------------------
- XDIAGNOSE is not made by default, but is included for those who want
- Xto hack on or debug the btree. Thanks for the btree source to Marcus
- XJ. Ranum, William Welch Medical Library (mjr@jhuigf.BITNET). Much
- Xhacking was done on btree.c and btree.h to improve efficiency and to
- Xtune it for this "large" an application. It also seemed not to work
- Xreal great when I first got it, and I'm still not sure it won't
- Xbreak, but it works fine on an SCO UNIX or XENIX 386 box and on a
- XPyramid.
- X
- X---------------------------------------------------------------------
- XWarren Tucker, Mountain Park, Georgia ...!gatech!kd4nc!n4hgf!wht
- SHAR_EOF
- chmod 0644 README || echo "restore of README fails"
- if [ $TOUCH = can ]
- then
- touch -m 1210204189 README
- fi
- echo "x - extracting Makefile (Text)"
- sed 's/^X//' << 'SHAR_EOF' > Makefile &&
- X#------------------------------------------------------------------
- X# Makefile for umdb - UUCP Map Database programs
- X# ...!gatech!emory!tridom!wht
- X#------------------------------------------------------------------
- X#+:EDITS:
- X#:12-09-1989-20:30-wht-creation
- X
- XSHELL = /bin/sh
- XCFLAGS = -Ox -DLINT_ARGS
- XLIB=
- X
- XSRC = \
- X btree.c \
- X umdbuild.c \
- X umdbdup.c \
- X umdbutil.c
- X
- XUMDBUILD_OBJ = \
- X btree.o \
- X umdbuild.o \
- X umdbutil.o
- X
- XUMDBDUP_OBJ = \
- X btree.o \
- X umdbdup.o \
- X umdbutil.o
- X
- XUMDBPATH_OBJ = \
- X btree.o \
- X umdbpath.o \
- X umdbutil.o
- X
- XDIAGNOSE_OBJ = \
- X btree.o \
- X diagnose.o
- X
- Xall: umdbuild umdbdup umdbpath
- X
- Xumdbuild: $(UMDBUILD_OBJ)
- X cc -o $@ $(UMDBUILD_OBJ) $(LIB)
- X
- Xumdbdup: $(UMDBDUP_OBJ)
- X cc -o $@ $(UMDBDUP_OBJ) $(LIB)
- X
- Xumdbpath: $(UMDBPATH_OBJ)
- X cc -o $@ $(UMDBPATH_OBJ) $(LIB)
- X
- Xdiagnose: $(DIAGNOSE_OBJ)
- X cc -o $@ $(DIAGNOSE_OBJ) $(LIB)
- X
- X# using this method, can only build with MSC compiler
- Xlint:
- X ls $(SRC) > src.fls
- X echo ' '> funcdefs.h
- X csh ./zgcc src.fls funcdefs.h
- X
- Xshar:
- X shar -c -numdb -o/tmp/umdb. -l36 README Makefile *.h *.c
- SHAR_EOF
- chmod 0644 Makefile || echo "restore of Makefile fails"
- if [ $TOUCH = can ]
- then
- touch -m 1210202889 Makefile
- fi
- echo "x - extracting btree.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > btree.h &&
- X/*+-------------------------------------------------------------------------
- X btree.h
- X hacked by ...!gatech!kd4nc!n4hgf!wht
- X
- XCopyright (C) 1988, Marcus J. Ranum, William Welch Medical Library
- X$Author: mjr $ $Log: btree.c,v $ Revision 1.1 88/06/01 21:35:07 mjr
- XInitial revision
- XThe original code was placed in the public domain. This is not, since I
- Xwish to retain some control over it. No restrictions are placed on
- Xmodification, or use of this code, as long as the copyrights are not
- Xremoved. There are some areas that really could use improving (like
- Xhandling free nodes better) and I hope that if someone makes
- Ximprovements they will keep me up to date on them (e-mail please, I am
- Xnot on usenet).
- XMarcus J. Ranum, William Welch Medical Library, 1988
- Xmjr@jhuigf.BITNET || uunet!mimsy!aplcen!osiris!welchvax!mjr
- X--------------------------------------------------------------------------*/
- X/*+:EDITS:*/
- X/*:12-10-1989-18:03-wht-make cache much larger */
- X/*:12-17-1988-19:52-wht-released 1.20 */
- X/*:12-16-1988-20:38-wht-variable max key length */
- X/*:12-16-1988-18:22-afterlint-creation */
- X
- X#ifndef _INCL_BTREE_H
- X#define _INCL_BTREE_H 1
- X
- X#define BT_NREC 1 /* no such record */
- X#define BT_EOF 2 /* end of the tree (either end) */
- X#define BT_ERR -1 /* something went wrong */
- X
- X#define BT_KSIZ 60 /* size of keys to store (or trunc) */
- X#define BT_CSIZ 4096 /* # of nodes to cache (power of two) */
- X
- X/* this indicates a node deleted */
- X#define BT_DELETED 1
- X#define BT_ACTIVE 0
- X
- X#define BT_MAGIC 0x0BB1
- X
- X/* btree stack */
- X#define STACK_LENGTH 30 /* length of history stacks */
- X
- Xstruct btstack {
- X short ele[STACK_LENGTH]; /* stack elements */
- X short lev[STACK_LENGTH]; /* stack levels */
- X short sptr; /* stack pointer */
- X};
- X
- X/* a disk resident btree super block */
- Xstruct btsuper {
- X short magic; /* magic number */
- X short keysize; /* maximum length of key */
- X short root; /* pointer to root node */
- X short free; /* pointer to next free (basically, EOF) */
- X short list; /* number of active records */
- X};
- X
- Xstruct btnode {
- X long recno; /* index to external file, or whatever */
- X short lptr; /* left-pointer */
- X short rptr; /* right-pointer */
- X char deleted; /* deleted flag */
- X char balance; /* balance flag */
- X};
- X#define BTNODE struct btnode
- X
- Xstruct btnode_m
- X{
- X struct btnode n; /* keep these two ... */
- X char key[BT_KSIZ]; /* ... fields FIRST !!! */
- X short node_num; /* disk node number */
- X short dirty; /* if true, cache item needs writing to disk */
- X};
- X
- X/* a memory resident btree super block */
- X/* including room to hold a disk super block */
- Xstruct btree
- X{
- X int fd; /* file descriptor */
- X struct btsuper sblk; /* copy of superblock */
- X struct btstack rstak; /* history stack */
- X struct btstack lstak; /* history stack */
- X struct btnode_m *cache[BT_CSIZ]; /* read-only cache */
- X short rdonly; /* true if file opened read-only */
- X short slev; /* history stack level */
- X};
- X#define BTREE struct btree
- X
- XBTREE *btopen();
- Xvoid btperror();
- X
- Xextern int bterrno; /* btree error number/flag */
- Xextern char *bterrs[]; /* error message list */
- X/* error codes - match bterrs */
- X#define BT_BAD_MAGIC 1 /* bad index file magic number */
- X#define BT_BAD_STACK 2 /* history stack overflow */
- X#define BT_BAD_ROOT 3 /* failed attempt to delete node 0 */
- X#define BT_BAD_KSIZ 4 /* keysize at open does not match index keysize */
- X#define BT_BAD_MEMORY 5 /* memory allocation failed */
- X#define BT_BAD_SBLK 6 /* bad superblock */
- X#define BT_BAD_WSUPER 7 /* error writing superblock */
- X#define BT_BAD_WNODE 8 /* error writing node */
- X#define BT_BAD_RNODE 9 /* error reading node */
- X#define BT_BAD_FLUSH 10 /* error flushing node */
- X
- X#endif /*_INCL_BTREE_H */
- X/* vi: set tabstop=4 shiftwidth=4: */
- X/* end of btree.h */
- SHAR_EOF
- chmod 0644 btree.h || echo "restore of btree.h fails"
- if [ $TOUCH = can ]
- then
- touch -m 1210180489 btree.h
- fi
- echo "x - extracting funcdefs.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > funcdefs.h &&
- X/*+-----------------------------------------------------------------------
- X funcdefs.h
- X------------------------------------------------------------------------*/
- X/*+:EDITS:*/
- X/*:12-10-1989-15:27-afterlint-creation */
- X
- X#ifndef BUILDING_LINT_ARGS
- X#ifdef LINT_ARGS
- X
- X/* btree.c */
- Xint _bthead(short *,struct btnode_m *,struct btree *);
- Xint _btnext(short *,struct btnode_m *,struct btree *);
- Xint _btprevious(short *,struct btnode_m *,struct btree *);
- Xint _bttail(short *,struct btnode_m *,struct btree *);
- Xint _flush_cache_node(struct btree *,struct btnode_m *);
- Xint _pushl(struct btree *,short );
- Xint _pushr(struct btree *,short );
- Xint _rnode(short ,struct btnode_m *,struct btree *);
- Xint _wnode(short ,struct btnode_m *,struct btree *);
- Xint _wsuper(struct btree *);
- Xint btclose(struct btree *);
- Xint btdelete(short ,struct btree *);
- Xint btfind(char *,short *,char **,long *,struct btree *);
- Xint btflush(struct btree *);
- Xint bthead(short *,char **,long *,struct btree *);
- Xint btinsert(char *,long ,struct btree *);
- Xint btnext(short *,char **,long *,struct btree *);
- Xint btprevious(short *,char **,long *,struct btree *);
- Xint btsetrec(short ,long ,struct btree *);
- Xint bttail(short *,char **,long *,struct btree *);
- Xshort _popl(struct btree *);
- Xshort _popr(struct btree *);
- Xstruct btree *btopen(char *,int ,int ,int );
- Xvoid _btlink(int ,struct btnode *,int ,struct btnode *);
- Xvoid _linknbr(int ,struct btnode *,short );
- Xvoid _nbrlink(short *,int ,struct btnode *);
- Xvoid _nodebal(int ,struct btnode *,struct btnode *,struct btnode *);
- Xvoid btperror(char *);
- X/* umdbdup.c */
- Xint main(int ,char **,char **);
- Xvoid print_dup_umdb_rec(long );
- X/* umdbuild.c */
- Xint main(int ,char **,char **);
- Xvoid mapfile_to_mapdb(char *);
- X/* umdbutil.c */
- Xchar *arg_token(char *,char *);
- Xchar *normalize_location(char *);
- Xchar *normalized_loc_to_str(char *);
- Xint array_to_angle(char **,int ,double *);
- Xvoid build_arg_array(char *,char **,int ,int *,char *);
- Xvoid build_dbfld_array(char *,char **,int ,int *);
- Xvoid build_normalized_locfld(char *,double ,double ,int );
- Xvoid build_sitename_array(char *,char **,int ,int *);
- X
- X#else /* compiler doesn't know about prototyping */
- X
- X/* btree.c */
- Xshort _popl();
- Xshort _popr();
- Xstruct btree *btopen();
- Xvoid _btlink();
- Xvoid _linknbr();
- Xvoid _nbrlink();
- Xvoid _nodebal();
- Xvoid btperror();
- X/* umdbdup.c */
- Xvoid print_dup_umdb_rec();
- X/* umdbuild.c */
- Xvoid mapfile_to_mapdb();
- X/* umdbutil.c */
- Xchar *arg_token();
- Xchar *normalize_location();
- Xchar *normalized_loc_to_str();
- Xvoid build_arg_array();
- Xvoid build_dbfld_array();
- Xvoid build_normalized_locfld();
- Xvoid build_sitename_array();
- X
- X#endif /* LINT_ARGS */
- X#endif /* BUILDING_LINT_ARGS */
- X
- X/* end of funcdefs.h */
- SHAR_EOF
- chmod 0644 funcdefs.h || echo "restore of funcdefs.h fails"
- if [ $TOUCH = can ]
- then
- touch -m 1210180489 funcdefs.h
- fi
- echo "x - extracting umdb.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > umdb.h &&
- X/*+-------------------------------------------------------------------------
- X umdb.h - uucp map database definitions
- X ...!gatech!emory!tridom!wht
- X--------------------------------------------------------------------------*/
- X/*+:EDITS:*/
- X/*:12-09-1989-18:18-wht-creation */
- X
- X#include "funcdefs.h"
- X
- X/* maximum length of system name (remember .dom.dom.ad.nauseam) */
- X#define SYSNAME_MAXLEN 40
- X
- X/* length of normailed location (latitude/logitude) field */
- X#define LOC_LEN 24 /* don't change w/o studying code */
- X
- X/* max sitenames per #N or other text line */
- X#define MAX_SITENAMES_PER_LINE 20 /* plenty! - avoid overflow tomorrow */
- X
- X/* max systems in a path */
- X#define MAX_SYSTEMS_PER_PATH 50 /* plenty! - avoid overflow tomorrow */
- X
- X/* count of fields in umdb main db record */
- X#define DBFLD_NLOC 0 /* normalized location */
- X#define DBFLD_SNAME 1 /* site name */
- X#define DBFLD_MNAME 2 /* map file name */
- X#define DBFLD_MPOS 3 /* map file position of #N line */
- X#define DBFLD_COUNT 4
- X
- X/* angle type definitions */
- X#define ANGLE_LATITUDE 1
- X#define ANGLE_LONGITUDE 2
- X#define ANGLE_BAD -1
- X
- X/* vi: set tabstop=4 shiftwidth=4: */
- X/* end of umdb.h */
- SHAR_EOF
- chmod 0644 umdb.h || echo "restore of umdb.h fails"
- if [ $TOUCH = can ]
- then
- touch -m 1210180489 umdb.h
- fi
- echo "x - extracting btree.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > btree.c &&
- X/*#define DEBUG*/
- X/*+-------------------------------------------------------------------------
- X btree.c
- X hacked by ...!gatech!kd4nc!n4hgf!wht
- X
- XCopyright (C) 1988, Marcus J. Ranum, William Welch Medical Library
- X$Author: mjr $ $Log: btree.c,v $ Revision 1.1 88/06/01 21:35:07 mjr
- XInitial revision
- XThe original code was placed in the public domain. This is not, since I
- Xwish to retain some control over it. No restrictions are placed on
- Xmodification, or use of this code, as long as the copyrights are not
- Xremoved. There are some areas that really could use improving (like
- Xhandling free nodes better) and I hope that if someone makes
- Ximprovements they will keep me up to date on them (e-mail please, I am
- Xnot on usenet).
- XMarcus J. Ranum, William Welch Medical Library, 1988
- Xmjr@jhuigf.BITNET || uunet!mimsy!aplcen!osiris!welchvax!mjr
- X
- X Defined functions:
- X _bthead(node_num,node,bt)
- X _btlink(alpha1,node1,alpha2,node2)
- X _btnext(node_num,node,bt)
- X _btprevious(node_num,node,bt)
- X _bttail(node_num,node,bt)
- X _flush_cache_node(bt,cache_node)
- X _linknbr(alpha,node1,node_num)
- X _nbrlink(node_num,alpha,node1)
- X _nodebal(alpha,node1,node2,node3)
- X _popl(bt)
- X _popr(bt)
- X _pushl(bt,node_num)
- X _pushr(bt,node_num)
- X _rnode(node_num,npt,bt)
- X _wnode(node_num,npt,bt)
- X _wsuper(bt)
- X btclose(bt)
- X btdelete(node_num,bt)
- X btfind(key,node_num,reckey,recno,bt)
- X btflush(bt)
- X bthead(node_num,key,recno,bt)
- X btinsert(argkey,recno,bt)
- X btnext(node_num,key,recno,bt)
- X btopen(path,flags,mode,keysize)
- X btperror(str)
- X btprevious(node_num,key,recno,bt)
- X btsetrec(node_num,newrec,bt)
- X bttail(node_num,key,recno,bt)
- X
- X--------------------------------------------------------------------------*/
- X/*+:EDITS:*/
- X/*:12-09-1989-17:29-wht-get working on SCO UNIX -- just #defines */
- X/*:12-17-1988-17:51-wht-write sblk only at close-writes were inefficient */
- X/*:12-17-1988-17:51-wht-cache now read-write... writes were inefficient */
- X/*:12-17-1988-12:09-wht-allow open of existing index to specify zero keysize */
- X/*:12-16-1988-20:38-wht-variable max key length */
- X/*:12-16-1988-17:15-wht-static procs no longer static, but with '_' prefix */
- X
- X
- X#include <stdio.h>
- X#include <errno.h>
- X#include "funcdefs.h"
- X
- X#define ff fprintf
- X#define se stderr
- X
- X#if defined(pyr) || defined(sun) || defined(BSD4)
- X#include <sys/file.h>
- X#endif
- X
- X#if defined(M_SYS5) || defined(SYS5)
- X#include <sys/fcntl.h>
- X#define bcopy(dest,src,len) memcpy(src,dest,len)
- X#define bzero(dest,len) memset(dest,0,len)
- X#endif
- X
- X#include "btree.h"
- X
- Xlong cache_hits = 0;
- Xlong cache_no_hits = 0;
- X
- X#define BT_NSIZ (sizeof(struct btnode) + bt->sblk.keysize)
- X#define BT_SSIZ (sizeof(struct btsuper))
- Xlong lseek();
- X
- X/* the errno for btree problems. we use negative # - */
- X/* so btperror can use the real UNIX errno */
- Xint bterrno = 0;
- Xchar *bterrs[] =
- X{
- X "No btree error",
- X "Bad index magic number (is this an index file?)",
- X "History stack overflow",
- X "Cannot delete node zero",
- X "Open keysize does not match index keysize",
- X "Memory allocation failure",
- X "Bad superblock (is this an index file?)",
- X "error writing superblock",
- X "error writing node",
- X "error reading node",
- X "error flushing node",
- X 0
- X};
- X
- X/* write the btree superblock to disk */
- Xint
- X_wsuper(bt)
- Xstruct btree *bt;
- X{
- Xregister int save_bterrno = bterrno;
- X
- X if(bt->rdonly)
- X return(0);
- X
- X#ifdef DEBUG
- X ff(se,"-------> write superblock fd=%d\n",bt->fd);
- X#endif
- X
- X bterrno = BT_BAD_WSUPER;
- X if(lseek(bt->fd,0L,0) < 0)
- X return(BT_ERR);
- X
- X if(write(bt->fd,(char *)&bt->sblk,BT_SSIZ) != BT_SSIZ)
- X return(BT_ERR);
- X
- X bterrno = save_bterrno;
- X return(0);
- X}
- X
- X
- X
- X/* dynamically allocate a control structure for an open btree */
- Xstruct btree *
- Xbtopen(path,flags,mode,keysize)
- Xchar *path;
- Xregister int flags;
- Xregister int mode;
- Xregister int keysize;
- X{
- X struct btree *bt;
- X register int r;
- X extern char *malloc();
- X
- X if(keysize)
- X {
- X keysize++; /* allow for null at end of record */
- X if(keysize & 1)
- X keysize++; /* keep even */
- X }
- X if(keysize > BT_KSIZ)
- X {
- X fprintf(stderr,"key size specified for %s (%d) exceeds max of %d\n",
- X path,keysize,BT_KSIZ);
- X exit(1);
- X }
- X
- X
- X /* lets be dynamic, shall we ? */
- X if((bt = (struct btree *) malloc(sizeof(struct btree))) == (BTREE *)0)
- X {
- X bterrno = BT_BAD_MEMORY;
- X return((BTREE *)0);
- X }
- X
- X if((bt->fd = open(path,flags,mode)) > -1)
- X {
- X#ifdef DEBUG
- X ff(se,"----------> open '%s' fd=%d\n",path,bt->fd);
- X#endif
- X r = read(bt->fd,(char *) &bt->sblk,BT_SSIZ);
- X
- X /* if read nothing, must be a new guy, right ? */
- X if(r == 0)
- X {
- X bt->sblk.magic = BT_MAGIC;
- X bt->sblk.free = 1;
- X bt->sblk.root = 0;
- X bt->sblk.list = 0;
- X if(keysize)
- X bt->sblk.keysize = keysize;
- X else
- X {
- X printf("cannot create new index with max keysize == 0\n");
- X exit(1);
- X }
- X
- X if(_wsuper(bt) == 0)
- X r = BT_SSIZ;
- X }
- X else if(r == BT_SSIZ)
- X {
- X bterrno = 0;
- X if(bt->sblk.magic != BT_MAGIC)
- X bterrno = BT_BAD_MAGIC;
- X else if(keysize && (keysize != bt->sblk.keysize))
- X bterrno = BT_BAD_KSIZ;
- X if(bterrno)
- X {
- X close(bt->fd);
- X free((char *) bt);
- X return((BTREE *)0);
- X }
- X }
- X
- X /* cleverly check ret value from either read or write */
- X if(r != BT_SSIZ)
- X {
- X bterrno = BT_BAD_SBLK;
- X close(bt->fd);
- X free((char *) bt);
- X return((BTREE *)0);
- X }
- X }
- X else
- X {
- X /* couldnt even open the bloody file */
- X free((char *) bt);
- X return((BTREE *)0);
- X }
- X
- X /* zero the cache -- will fail at 65535 records :-) */
- X for(r = 0; r < BT_CSIZ; r++)
- X {
- X if((bt->cache[r] = (struct btnode_m *)malloc(sizeof(struct btnode_m)))
- X == (struct btnode_m *)0)
- X {
- X ff(se,"no memory for cache\n");
- X exit(1);
- X }
- X bt->cache[r]->node_num = -1;
- X bt->cache[r]->dirty = 0;
- X }
- X bt->rdonly = ((flags & (O_WRONLY | O_RDWR)) == O_RDONLY);
- X
- X return(bt);
- X}
- X
- X/* close and deallocate the control structure */
- Xbtclose(bt)
- Xstruct btree *bt;
- X{
- X register int err = 0;
- X register int icache;
- X
- X if(!bt->rdonly)
- X {
- X if(err = btflush(bt))
- X printf("======== ERROR WRITING TO DISK ON CLOSE ==========\n");
- X }
- X close(bt->fd);
- X for(icache = 0; icache < BT_CSIZ; icache++)
- X free((char *)bt->cache[icache]);
- X free((char *) bt);
- X return(err);
- X}
- X
- Xint
- X_flush_cache_node(bt,cache_node)
- Xstruct btree *bt;
- Xregister struct btnode_m *cache_node;
- X{
- Xregister int save_bterrno = bterrno;
- X
- X if((cache_node->node_num == -1) || (!cache_node->dirty))
- X return(0);
- X bterrno = BT_BAD_FLUSH;
- X if(lseek(bt->fd,(((long)cache_node->node_num * BT_NSIZ) + BT_SSIZ),0) < 0)
- X return(BT_ERR);
- X if(write(bt->fd,(char *)&cache_node->n,BT_NSIZ) != BT_NSIZ)
- X return(BT_ERR);
- X cache_node->dirty = 0;
- X bterrno = save_bterrno;
- X return(0);
- X}
- X
- Xint
- Xbtflush(bt)
- Xstruct btree *bt;
- X{
- X register int icache;
- X register struct btnode_m *cache_node;
- X
- X for(icache = 0; icache < BT_CSIZ; icache++)
- X {
- X cache_node = bt->cache[icache];
- X if(_flush_cache_node(bt,cache_node))
- X return(BT_ERR);
- X }
- X if(_wsuper(bt))
- X return(BT_ERR);
- X return(0);
- X}
- X
- X/* write a node to cache */
- Xint
- X_wnode(node_num,npt,bt)
- Xregister short node_num;
- Xstruct btnode_m *npt;
- Xregister struct btree *bt;
- X{
- X unsigned int hash = (unsigned int)node_num & (BT_CSIZ - 1);
- X register struct btnode_m *cache_node = bt->cache[hash];
- X extern int errno;
- X
- X#ifdef DEBUG
- X ff(se,"_wnode(node_num=%d,fd=%d)\n",node_num,bt->fd);
- X ff(se," cache node_num=%d\n",cache_node->node_num);
- X#endif
- X
- X if(!node_num)
- X return(0);
- X
- X errno = 0;
- X if(bt->rdonly)
- X {
- X errno = EPERM; /* would be reported later */
- X return(BT_ERR);
- X }
- X bterrno = BT_BAD_WNODE;
- X if(cache_node->node_num != node_num)
- X {
- X if(_flush_cache_node(bt,cache_node))
- X return(BT_ERR);
- X }
- X
- X /* update cache - if the write succeeded */
- X (void)bcopy((char *)npt,(char *)cache_node,sizeof(struct btnode_m));
- X cache_node->node_num = node_num;
- X cache_node->dirty = 1;
- X bterrno = 0;
- X return(0);
- X}
- X
- X/* read a node from disk */
- Xint
- X_rnode(node_num,npt,bt)
- Xregister short node_num;
- Xregister struct btnode_m *npt;
- Xregister struct btree *bt;
- X{
- X register rdcount;
- X register long readpos;
- X unsigned int hash = (unsigned int)node_num & (BT_CSIZ - 1);
- X register struct btnode_m *cache_node = bt->cache[hash];
- X extern int errno;
- X
- X#ifdef DEBUG
- X ff(se,"_rnode(node_num=%d,fd=%d)\n",node_num,bt->fd);
- X ff(se," cache node_num=%d\n",cache_node->node_num);
- X#endif
- X
- X if(!node_num)
- X {
- X (void)bzero((char *)npt,sizeof(struct btnode_m));
- X return(0);
- X }
- X
- X errno = 0;
- X bterrno = BT_BAD_RNODE;
- X if(cache_node->node_num != node_num)
- X {
- X /* if no cache hit, load from disk */
- X cache_no_hits++;
- X if(!bt->rdonly)
- X {
- X if(_flush_cache_node(bt,cache_node))
- X return(BT_ERR);
- X }
- X if(lseek(bt->fd,(readpos = ((long)node_num * BT_NSIZ) + BT_SSIZ),0) < 0)
- X return(BT_ERR);
- X if((rdcount = read(bt->fd,(char *)&cache_node->n,BT_NSIZ)) != BT_NSIZ)
- X {
- X#ifdef DEBUG
- X if(rdcount >= 0)
- X ff(se,"rdcount for node %u was % (should be %d) @ %ld\n",
- X node_num,rdcount,BT_NSIZ,readpos);
- X#endif
- X return(BT_ERR);
- X }
- X cache_node->node_num = node_num;
- X cache_node->dirty = 0;
- X }
- X else
- X cache_hits++;
- X
- X (void)bcopy((char *)cache_node,(char *)npt,sizeof(struct btnode_m));
- X
- X bterrno = 0;
- X return(0);
- X}
- X
- Xint
- X_pushl(bt,node_num)
- Xstruct btree *bt;
- Xregister short node_num;
- X{
- X if(++ (bt->lstak.sptr) >= STACK_LENGTH)
- X {
- X bterrno = BT_BAD_STACK;
- X exit(0);
- X }
- X bt->lstak.ele[bt->lstak.sptr] = node_num;
- X bt->lstak.lev[bt->lstak.sptr] = ++bt->slev;
- X return;
- X}
- X
- X
- Xint
- X_pushr(bt,node_num)
- Xstruct btree *bt;
- Xregister short node_num;
- X{
- X if(++ (bt->rstak.sptr) >= STACK_LENGTH)
- X {
- X bterrno = BT_BAD_STACK;
- X exit(0);
- X }
- X bt->rstak.ele[bt->rstak.sptr] = node_num;
- X bt->rstak.lev[bt->rstak.sptr] = ++bt->slev;
- X return;
- X}
- X
- X
- X
- Xshort
- X_popr(bt)
- Xstruct btree *bt;
- X{
- X
- X bt->slev = bt->rstak.lev[bt->rstak.sptr];
- X
- X while(bt->lstak.lev[bt->lstak.sptr] > bt->slev)
- X (bt->lstak.sptr)--;
- X
- X if(bt->rstak.sptr == 0)
- X return(0);
- X
- X bt->slev--;
- X return(bt->rstak.ele[(bt->rstak.sptr)--]);
- X}
- X
- X
- X
- Xshort
- X_popl(bt)
- Xstruct btree *bt;
- X{
- X
- X bt->slev = bt->lstak.lev[bt->lstak.sptr];
- X
- X while(bt->rstak.lev[bt->rstak.sptr] > bt->slev)
- X (bt->rstak.sptr)--;
- X
- X if(bt->lstak.sptr == 0)
- X return(0);
- X
- X bt->slev--;
- X return(bt->lstak.ele[(bt->lstak.sptr)--]);
- X}
- X
- Xvoid
- X_btlink(alpha1,node1,alpha2,node2)
- Xregister int alpha1;
- Xregister int alpha2;
- Xstruct btnode *node1;
- Xstruct btnode *node2;
- X{
- X if(alpha1 == -1 && alpha2 == -1)
- X node1->lptr = node2->lptr;
- X else if(alpha1 == -1 && alpha2 == 1)
- X node1->lptr = node2->rptr;
- X else if(alpha1 == 1 && alpha2 == -1)
- X node1->rptr = node2->lptr;
- X else
- X node1->rptr = node2->rptr;
- X}
- X
- X
- X
- X/* number a link according to alpha */
- Xvoid
- X_nbrlink(node_num,alpha,node1)
- Xshort *node_num;
- Xregister int alpha;
- Xstruct btnode *node1;
- X{
- X *node_num = (alpha == 1) ? node1->rptr : node1->lptr;
- X}
- X
- X
- X
- X/* set a link according to alpha */
- Xvoid
- X_linknbr(alpha,node1,node_num)
- Xregister int alpha;
- Xstruct btnode *node1;
- Xregister short node_num;
- X{
- X
- X if(alpha == 1)
- X node1->rptr = node_num;
- X else
- X node1->lptr = node_num;
- X}
- X
- X
- X
- Xvoid
- X_nodebal(alpha,node1,node2,node3)
- Xregister int alpha;
- Xstruct btnode *node1;
- Xstruct btnode *node2;
- Xstruct btnode *node3;
- X{
- X
- X if(node1->balance == alpha)
- X {
- X node2->balance = -alpha;
- X node3->balance = 0;
- X }
- X else if(node1->balance == 0)
- X node2->balance = node3->balance = 0;
- X else
- X {
- X node2->balance = 0;
- X node3->balance = alpha;
- X }
- X}
- X
- X
- X
- X/* change the record number in a node */
- Xbtsetrec(node_num,newrec,bt)
- Xregister short node_num;
- Xlong newrec;
- Xstruct btree *bt;
- X{
- X struct btnode_m tnode;
- X
- X if(_rnode(node_num,&tnode,bt))
- X return(BT_ERR);
- X
- X tnode.n.recno = newrec;
- X
- X if(_wnode(node_num,&tnode,bt))
- X return(BT_ERR);
- X
- X return(0);
- X}
- X
- X/* insert the node into the tree */
- Xbtinsert(argkey,recno,bt)
- Xchar *argkey;
- Xlong recno;
- Xstruct btree *bt;
- X{
- X register int compare;
- X short trec1;
- X short trec2;
- X short trec3;
- X short trec4;
- X short top;
- X struct btnode_m tnode1;
- X struct btnode_m tnode2;
- X struct btnode_m tnode3;
- X struct btnode_m tnode4;
- X
- X
- X /* the very first node gets inserted specially */
- X if(bt->sblk.root == 0)
- X {
- X bt->sblk.root = 1;
- X tnode1.n.balance = tnode1.n.rptr = tnode1.n.lptr = 0;
- X tnode1.n.deleted = BT_ACTIVE;
- X tnode1.n.recno = recno;
- X
- X strncpy(tnode1.key,argkey,bt->sblk.keysize - 1);
- X tnode1.key[bt->sblk.keysize - 1] = '\0';
- X if(_wnode(1,&tnode1,bt) < 0)
- X return(BT_ERR);
- X
- X bt->sblk.free++;
- X bt->sblk.list++;
- X return(0);
- X }
- X top = -1;
- X trec1 = bt->sblk.root;
- X trec4 = bt->sblk.root;
- X while(1)
- X {
- X if(_rnode(trec1,&tnode1,bt))
- X {
- X#ifdef DEBUG
- X ff(se,"btinsert: trec1(1) read error\n");
- X#endif
- X return(BT_ERR);
- X }
- X if((compare = strcmp(argkey,tnode1.key)) < 0)
- X {
- X /* (move left) */
- X trec2 = tnode1.n.lptr;
- X
- X if(trec2 == 0)
- X {
- X /* insert here */
- X trec2 = bt->sblk.free++;
- X tnode1.n.lptr = trec2;
- X break; /* loop exit */
- X }
- X else
- X {
- X /* look again from this node */
- X if(_rnode(trec2,&tnode2,bt))
- X {
- X#ifdef DEBUG
- X ff(se,"btinsert: trec2(1) read error\n");
- X#endif
- X return(BT_ERR);
- X }
- X if(tnode2.n.balance != 0)
- X {
- X top = trec1;
- X trec4 = trec2;
- X }
- X }
- X trec1 = trec2;
- X }
- X else
- X {
- X /* (move right) */
- X trec2 = tnode1.n.rptr;
- X
- X if(trec2 == 0)
- X {
- X /* insert here */
- X trec2 = bt->sblk.free++;
- X tnode1.n.rptr = trec2;
- X break; /* loop exit */
- X }
- X else
- X {
- X /* look again from this node */
- X if(_rnode(trec2,&tnode2,bt))
- X {
- X#ifdef DEBUG
- X ff(se,"btinsert: trec2(2) read error\n");
- X#endif
- X return(BT_ERR);
- X }
- X if(tnode2.n.balance != 0)
- X {
- X top = trec1;
- X trec4 = trec2;
- X }
- X trec1 = trec2;
- X }
- X }
- X }
- X
- X /* Step 5 (insert key at tnode2) */
- X tnode2.n.lptr = tnode2.n.rptr = 0;
- X tnode2.n.balance = 0;
- X tnode2.n.deleted = BT_ACTIVE;
- X tnode2.n.recno = recno;
- X strncpy(tnode2.key,argkey,bt->sblk.keysize - 1);
- X tnode2.key[bt->sblk.keysize - 1] = '\0';
- X
- X if(_wnode(trec2,&tnode2,bt))
- X return(BT_ERR);
- X if(_wnode(trec1,&tnode1,bt))
- X return(BT_ERR);
- X if(_rnode(trec4,&tnode4,bt))
- X {
- X#ifdef DEBUG
- X ff(se,"btinsert: trec4(1) read error\n");
- X#endif
- X return(BT_ERR);
- X }
- X
- X /* (adjust balance factors) */
- X if(strcmp(argkey,tnode4.key) < 0)
- X trec3 = trec1 = tnode4.n.lptr;
- X else
- X trec3 = trec1 = tnode4.n.rptr;
- X
- X while(trec1 != trec2)
- X {
- X if(_rnode(trec1,&tnode1,bt))
- X {
- X#ifdef DEBUG
- X ff(se,"btinsert: trec1(2) read error\n");
- X#endif
- X return(BT_ERR);
- X }
- X if(strcmp(argkey,tnode1.key) < 0)
- X {
- X tnode1.n.balance = -1;
- X if(_wnode(trec1,&tnode1,bt) < 0)
- X return(BT_ERR);
- X trec1 = tnode1.n.lptr;
- X }
- X else
- X {
- X tnode1.n.balance = 1;
- X if(_wnode(trec1,&tnode1,bt) < 0)
- X return(BT_ERR);
- X trec1 = tnode1.n.rptr;
- X }
- X }
- X
- X compare = (strcmp(argkey,tnode4.key) < 0) ? -1 : 1;
- X if(tnode4.n.balance == 0)
- X {
- X bt->sblk.list++;
- X tnode4.n.balance = compare;
- X if(_wnode(trec4,&tnode4,bt) < 0)
- X return(BT_ERR);
- X return(0);
- X }
- X else if(tnode4.n.balance == -compare)
- X {
- X bt->sblk.list++;
- X tnode4.n.balance = 0;
- X if(_wnode(trec4,&tnode4,bt) < 0)
- X return(BT_ERR);
- X return(0);
- X }
- X else
- X {
- X /* (tree out of balance) */
- X bt->sblk.list++;
- X if(_rnode(trec4,&tnode4,bt))
- X {
- X#ifdef DEBUG
- X ff(se,"btinsert: trec4(2) read error\n");
- X#endif
- X return(BT_ERR);
- X }
- X if(_rnode(trec3,&tnode3,bt))
- X {
- X#ifdef DEBUG
- X ff(se,"btinsert: trec3(1) read error\n");
- X#endif
- X return(BT_ERR);
- X }
- X if(tnode3.n.balance == compare)
- X {
- X /* (single rotate) */
- X trec1 = trec3;
- X _btlink(compare,(BTNODE *) &tnode4,-compare,(BTNODE *) &tnode3);
- X _linknbr(-compare,(BTNODE *) &tnode3,trec4);
- X tnode4.n.balance = tnode3.n.balance = 0;
- X }
- X else
- X {
- X /* (double rotate) */
- X _nbrlink(&trec1,-compare,(BTNODE *) &tnode3);
- X if(_rnode(trec1,&tnode1,bt))
- X {
- X#ifdef DEBUG
- X ff(se,"btinsert: trec1(3) read error\n");
- X#endif
- X return(BT_ERR);
- X }
- X _btlink(-compare,(BTNODE *) &tnode3,compare,(BTNODE *) &tnode1);
- X _linknbr(compare,(BTNODE *) &tnode1,trec3);
- X _btlink(compare,(BTNODE *) &tnode4,-compare,(BTNODE *) &tnode1);
- X _linknbr(-compare,(BTNODE *) &tnode1,trec4);
- X _nodebal(compare,(BTNODE *) &tnode1,(BTNODE *) &tnode4,(BTNODE *) &tnode3);
- X tnode1.n.balance = 0;
- X if(_wnode(trec1,&tnode1,bt))
- X return(BT_ERR);
- X }
- X
- X if(top == -1)
- X bt->sblk.root = trec1;
- X else
- X {
- X /* balanced at top of a sub-tree */
- X if(_rnode(top,&tnode2,bt) < 0)
- X {
- X#ifdef DEBUG
- X ff(se,"btinsert: top(1) read error\n");
- X#endif
- X return(BT_ERR);
- X }
- X if(trec4 == tnode2.n.rptr)
- X tnode2.n.rptr = trec1;
- X else
- X tnode2.n.lptr = trec1;
- X if(_wnode(top,&tnode2,bt))
- X return(BT_ERR);
- X }
- X if(_wnode(trec4,&tnode4,bt))
- X return(BT_ERR);
- X if(_wnode(trec3,&tnode3,bt))
- X return(BT_ERR);
- X return(0);
- X }
- X}
- X
- X/* drop a node */
- Xbtdelete(node_num,bt)
- Xregister short node_num;
- Xstruct btree *bt;
- X{
- X struct btnode_m node;
- X
- X if(node_num == 0)
- X {
- X bterrno = BT_BAD_ROOT;
- X return(BT_ERR);
- X }
- X else
- X {
- X if(_rnode(node_num,&node,bt))
- X return(BT_ERR);
- X node.n.deleted = BT_DELETED;
- X if(_wnode(node_num,&node,bt))
- X return(BT_ERR);
- X else
- X bt->sblk.list--;
- X }
- X return(0);
- X}
- X
- X/* find the next node */
- Xbtnext(node_num,key,recno,bt)
- Xshort *node_num;
- Xchar **key;
- Xlong *recno;
- Xstruct btree *bt;
- X{
- X static struct btnode_m node;
- X register int retn;
- X if(_rnode(*node_num,&node,bt))
- X return(BT_ERR);
- X retn = _btnext(node_num,&node,bt);
- X *key = node.key;
- X *recno = node.n.recno;
- X return(retn);
- X}
- X
- X
- X/* find the next node */
- X_btnext(node_num,node,bt)
- Xshort *node_num;
- Xregister struct btnode_m *node;
- Xstruct btree *bt;
- X{
- X short _popl();
- X short _popr();
- X short s_nod;
- X
- X s_nod = *node_num;
- X
- X if(*node_num == 0)
- X {
- X /* undefined current node - wind to beginning of file */
- X return(_bthead(node_num,node,bt));
- X }
- X do
- X {
- X if(node->n.rptr == 0)
- X {
- X /* can't move right */
- X if(bt->lstak.sptr == 0)
- X {
- X /* none in stack */
- X if(_rnode(*node_num,node,bt))
- X return(BT_ERR);
- X return(BT_EOF);
- X }
- X else
- X {
- X /* can't go right & stack full (pop stack) */
- X s_nod = _popl(bt);
- X if(_rnode(s_nod,node,bt) < 0)
- X return(BT_ERR);
- X }
- X }
- X else
- X {
- X /* move right */
- X _pushr(bt,s_nod);
- X s_nod = node->n.rptr;
- X if(_rnode(s_nod,node,bt) )
- X return(BT_ERR);
- X
- X while(node->n.lptr != 0)
- X {
- X /* bottom left */
- X _pushl(bt,s_nod);
- X /* of this sub-tree */
- X s_nod = node->n.lptr;
- X if(_rnode(s_nod,node,bt))
- X return(BT_ERR);
- X }
- X }
- X } while(node->n.deleted == BT_DELETED);
- X
- X *node_num = s_nod;
- X return(0);
- X}
- X
- X/* go to the tail of the file */
- Xbttail(node_num,key,recno,bt)
- Xshort *node_num;
- Xchar **key;
- Xlong *recno;
- Xstruct btree *bt;
- X{
- X static struct btnode_m node;
- X register int retn = _bttail(node_num,&node,bt);
- X *key = node.key;
- X *recno = node.n.recno;
- X return(retn);
- X}
- X
- X/* go to the tail of the file */
- X_bttail(node_num,node,bt)
- Xshort *node_num;
- Xregister struct btnode_m *node;
- Xstruct btree *bt;
- X{
- X short s_nod;
- X
- X bt->rstak.sptr = 0;
- SHAR_EOF
- echo "End of umdb part 1"
- echo "File btree.c is continued in part 2"
- echo "2" > s3_seq_.tmp
- exit 0
-
-