home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-23 | 54.2 KB | 1,323 lines |
- Newsgroups: comp.sources.misc
- From: richid@owlnet.rice.edu (Richard Parvin Jernigan)
- Subject: v33i119: mbase - MetalBase 5.0, Portable database engine, Part01/08
- Message-ID: <csm-v33i119=mbase.165613@sparky.IMD.Sterling.COM>
- X-Md4-Signature: 4e160b28912fbbc8564f40f7508addad
- Date: Mon, 23 Nov 1992 22:57:13 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: richid@owlnet.rice.edu (Richard Parvin Jernigan)
- Posting-number: Volume 33, Issue 119
- Archive-name: mbase/part01
- Environment: AMIGA, MS-DOS, HP-UX, XENIX, UNIX, ULTRIX, SGI, SU, Curses
- Supersedes: mbase: Volume 28, Issue 40-44
-
- [ This version of mbase has been released as donateware. Donate if you wish ]
- [ but you are not required to. See the file readme.too for more specifics. ]
- [ For archiving purposes, I do not consider this shareware. -Kent+ ]
-
- MetalBase 5.0 is a simple database engine, designed to be portable between
- almost any platform; Unix, MS-DOS, HP, Mac PW, NeXT, sgi, and many more, small-
- model and up. This latest release has more field types, three-phase locking
- to ensure multi-user access without any system-based IPC, and internal caching
- to provide twice the speed and up for rebalancing indices. A conversion
- utility for MetalBase 4.0 and 4.1a relations is provided. Other features
- include run-time encryption on all platforms, creation of relations on-the-fly
- and a flexible report writer.
-
- Richid
- -------------------------------------------------------------------------------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: advert dox dox/mbase.dox sample src src/util1.c
- # Wrapped by kent@sparky on Mon Nov 23 16:33:11 1992
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 8)."'
- if test -f 'advert' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'advert'\"
- else
- echo shar: Extracting \"'advert'\" \(1397 characters\)
- sed "s/^X//" >'advert' <<'END_OF_FILE'
- XAdvertisement :) MetalBase 5.0
- X-------------------------------------------------------------------------------
- X
- XI'm looking for either of two things:
- X
- X - An internet newsfeed (ANY feed, stable or not) local to central Iowa,
- X around Ames/Des Moines preferably.
- X
- X - A job located somewhere in Iowa, again, preferably near Des Moines. I
- X know, I know--"Iowa???" That's what everyone says. But my SO is starting
- X school at Grinnell this fall, and I wanna be around for it.
- X
- X Microsoft's being nice to me, but my internship will be over around
- X January of 1993; and 'cause of regulations, they can't hire an intern
- X again until X months after the last internship ended. So I've gotta find
- X somebody else instead...
- X
- X If your company is in need of a very experienced Unix/MSDOS/VMS
- X C/C++/Pascal/FORTRAN/680x0/80x86/6502 programmer, let me know and I'll
- X float you a resume. I'm unsure of my internet connection for a while, so
- X contact me through:
- X Richard P Jernigan IV
- X PO Box 827
- X Norris, TN 37828
- X 615-494-0445
- X Okay. So what are the odds I'll get a response to that? :)
- X
- XPostScript: I actually DID get a response! Didn't take 'em up 'cause
- X I'm doin that summer thang at Microsoft. But as I said, that's
- X almost over.
- X
- END_OF_FILE
- if test 1397 -ne `wc -c <'advert'`; then
- echo shar: \"'advert'\" unpacked with wrong size!
- fi
- # end of 'advert'
- fi
- if test ! -d 'dox' ; then
- echo shar: Creating directory \"'dox'\"
- mkdir 'dox'
- fi
- if test -f 'dox/mbase.dox' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dox/mbase.dox'\"
- else
- echo shar: Extracting \"'dox/mbase.dox'\" \(33032 characters\)
- sed "s/^X//" >'dox/mbase.dox' <<'END_OF_FILE'
- X /\
- X / \
- X../ \....METALBASE Version 5.0..............................................
- X / \
- X/ \ Written From October 1990 by Huan-Ti
- X\ /
- X \ / Revision 3.1 released December 10th 1990
- X \ / Revision 3.2 released December 10th 1991
- X \ / Revision 4.0 released Febuary 14th 1992
- X \/ Revision 4.1 released April 1st 1992
- X Revision 4.1a released May 10th 1992
- X Revision 5.0 released October 1st 1992
- X
- X
- X
- X
- X
- X
- X "And Calvin ate. And Food Lion went out of business. Amen."
- X
- X --1st Calvin 4:8
- X
- X
- XWHY_METALBASE_?________________________________________________________________
- X
- X The Amiga 500 multi-tasks. Wow. It has great graphics. Yeah. Phenomenal
- Xsound. Yippee. It costs $500. I bought one.
- X A DBase package costs more than the computer. So does Paradox. And
- XInformix. And almost every other database package on the market. I didn't
- Xbuy one.
- X But I needed a database for my system--anybody who's ever worked with a
- Xdatabase knows they're addictive; code that's written without a flexible
- Xdatabase backing it up lacks something. And DBase wants $600 to put that
- Xsomething back into programs. No thanks.
- X That's why MetalBase was written... its forerunners (versions 1.0 and
- X2.0, not available) were designed by the same author with the Amiga line's
- Xneeds specifically in mind: relatively slow floppy drives (Compared to hard
- Xdrives), so sparse read-head maneuvering was essential. Relatively small
- Xmemory, when compared with the amounts of memory required by most C compilers
- X(Lattice needs roughly 300k just to run, for example), so the code had to be
- Xconsise, pure, and use few variables. Expansion was always available; hard
- Xdrives, huge memory capacities, extra processors, ram drives -- so the system
- Xhad to be readily expandible and flexible enough to meet the requirements of
- Xboth a 512k, 1-drive machine and a 32-megabyte, 200-meg hard drive-driven
- Xsetup. And they were.
- X The problem was, Amigas can multi-task. So what is the rest of the
- Xcomputer doing while a database runs around looking up records on one drive?
- XNothing. Why not let it look up records on another drive? Fine... that works.
- XWhat about on the same drive... using, say, a ram disk, so there are no real
- Xread-heads to worry about positioning? That would mean each relation would
- Xhave to support multi-user access... a requirement around which MetalBase
- Xversions 3.0 and up focus. Not only can any given terminal access many files
- Xat once, but on multi-terminal systems, each terminal can work simultaneously
- Xon any given file. Terminals can each use as many relations as a system will
- Xallow, and each relation can be used by some sixty-four users at once. The
- Xcode used to create MetalBase 3.X and up is completely compatible with the
- XUnix operating system and all of its derivatives, so its inherent multi-user
- Xability places it in firm working footing on the most advanced systems on the
- Xmarket.
- X But the IBM users complained. And the unix users complained. And lo,
- Xeven the Amiga people complained--the code didn't work all the time, and
- Xwas generally crude. So MetalBase 4.0 solved these troubles and more--a
- Xcomplete rewrite of the engine has provided even faster and more efficient
- Xalgorithms, which keep MetalBase indices in AVL balance at all times. More
- Xconvenient functions and operations (such as build's ability to create header
- Xfiles for your code which reflect a schema's structure) have been added,
- Xalong with several utility programs for maintaining your database.
- X Relations are designed by a user to match his/her exact requirements,
- Xindices placed as needed on single or composite fields, and records can be
- Xadded, retrieved, changed, and deleted as any C programmer so desires. The
- Xinterface is as simple as possible, very fast in execution, and provides a wide
- Xrange of error types for exact specification of problems. A user on any
- Xterminal can choose to lock out other users from any number of relations, so
- Xsweeping changes in data will not be read by others before they can take
- Xplace. Automatic temporary locks are placed on a relation which is about
- Xto undergo a deletion or addition, strategically delaying other users' access
- Xto files for less than seconds, so that no data will be read until all indices
- Xhave been updated correctly. This process is entirely system-driven; users
- Xnever need worry about it at all. If one user is adding a record to a
- Xrelation, any terminal requesting a record lookup will simply wait until the
- Xaddition is complete before proceeding. As records are deleted and added
- Xthrough normal use, the algorithms used to update indices automatically keep
- Xthem at top operating speeds, so any given relation's number of records can
- Xgrow exponentially while causing only a linear increase in look-up time. Any
- Xrelation can contain over four billion records (Nearly four billion more than
- Xmost systems will ever need), and each record's length can be as large as its
- Xsystem's memory can handle. In perspective, MetalBase is infinitely
- Xexpandible, while requiring very little of the system on which it operates.
- X
- X[ The actual number of records allowable is 4,294,967,296... if you were to
- X add one record a second, it would take over 136 years to reach this limit ]
- X
- XRELATION_DESIGN________________________________________________________________
- X
- X A sample relation. Data Field # -> 1 2 3 4 5
- X is read by selecting one Record # _____ ___ ____ ___ ___________
- X record from the others by 1 |_____|___|____|___|___________|
- X various criteria, and 2 |_____|___|____|___|___________|
- X returning it to the user. 3 |Smith| 12| 114| A2|Houston, TX|
- X Record 3 (In this example-- 4 |-----|---|----|---|-----------|
- X actual MetalBase records need
- X no such numbering system), if returned, would be placed in a structure
- X containing Smith,12,114,A2, and Houston,TX in the appropriate elements.
- X
- X A relation is a collection of records, each record consisting of the same
- Xnumber of fields--blocks of data whose individual lengths remain constant from
- Xrecord to record. Each field need not have the same length as the others in
- Xany given record, but from record to record, a field's length will remain the
- Xsame. The data the fields contain is, of course, the main purpose of a
- Xdatabase--when thousands of records exist, a system without a database would
- Xneed vast amounts of time to find any given record. Databases decrease
- Xdramatically record retrieval time, while requiring as little additional time
- Xto add new and change old records as possible.
- X The key to a database is its indices--pointers arranged in such a fashion
- Xas to show the system where to look for the record for which it is searching.
- XThe more of these collections of pointers, or indices, a database has, the
- Xgreater the number of different fields a system can search through in order to
- Xfind a record meeting certain criteria for a field (Or fields... a single index
- Xcan be used to first sort records by one field, and also sort duplicates with
- Xrespect to a second field, etc. MetalBase allows these composite indices to
- Xkey off of as many as 999 different fields). However, databases require time
- Xto update each index every time you add, delete, or change a field which has an
- Xindex placed upon it. So although retrieval criteria possibilites are expanded
- Xby using many indices, the amount of time required to change the existing
- Xrecords in a database will also increase. For this reason, the number of
- Xindices a relation will have should be considered carefully--use what is
- Xneeded, but no more.
- X
- X Relations are built from schema files, which decribe the relation in a
- Xmore human-friendly syntax. See build.dox for a more complete description of
- Xthis process.
- X
- XIMPLEMENTAION__________________________________________________________________
- X
- X A sample program implementing MetalBase follows:
- X
- X #include <mbase.h>
- X #include "equipment.h"
- X
- X main ()
- X {
- X relation *rel;
- X
- X if ((rel = mb_inc ("/usr/joe/equipment", strtokey("key"))) == RNULL) {
- X printf ("Can't open database - %s.\n", mb_error);
- X mb_exit (1);
- X }
- X
- X equipment_rec.price_code = 114.20; /* Set up initial values */
- X strcpy (equipment_rec.part_numb, "117"); /* to search for... */
- X
- X if (mb_sel (rel, 0, &equipment_rec, EQUAL, NULL) != 0) {
- X printf ("%s.\n", mb_error);
- X mb_exit (1);
- X }
- X
- X /* Now that we've found a record, change it to something else... */
- X
- X equipment_rec.num_purch = 14;
- X strcpy (equipment_rec.customer, "Su");
- X strcpy (equipment_rec.part_numb, "112");
- X strcpy (equipment_rec.shop_addr, "Dallas, TX");
- X equipment_rec.price_code = 12;
- X
- X mb_upd (rel, &equipment_rec); /* Update the current selection */
- X
- X mb_rmv (rel); // Unnecessary before mb_exit(), but good practice.
- X mb_exit (0); // Always a good idea to use mb_exit() with MetalBase.
- X }
- X
- X Manipulation of relations using MetalBase is simple... by including the
- XMetalBase header file in your programs and compiling using the option "-lmb"
- X(Or "library ..., mbase.lib;", depending on your compiler), you add extra
- Xcommands to C. A summary of these follows:
- X
- X - mb_inc (filename, int) -- this command includes a relation on your desktop,
- X so that it becomes accessable. Any relation you wish to work with
- X must be included using this call. If mb_inc returns RNULL ( defined
- X as (relation *)0 ), an error has occurred (The most likely one is that
- X the relation cannot be found under the given directory--mb_errno will
- X be set to an error number, and mb_error (global char*) will contain
- X text regarding the problem). Note that "filename" does NOT include the
- X ".rel" suffix. BUILD, in analog, does not require that you include the
- X ".s" suffix on the name of the schema you are working with, but the
- X schema file itself must end in ".s", as relations must end in ".rel",
- X forms in ".frm" and reports in ".rpt".
- X
- X The integer passed in is the encryption key for the relation--see the
- X section on encryption for more information. Note that MetalBase 3.0,
- X as it does not support encryption, does not require this integer; all
- X versions 3.1 and up do. Sorry for the inconvenience.
- X
- X I also STRONGLY recommend the use of the function strtokey() to
- X obtain this integer from an ascii string... all utility programs
- X shipped with MetalBase ask for "Encryption Key"s, and they expect
- X a string to hash up with strtokey(). So if you use encryption but
- X not this method of getting the integer, you're SOL when trying to
- X use vr or report. In fact, I encourage this so strongly that, in
- X future releases, I may replace the integer argument with a string
- X argument and do away with strtokey() entirely.
- X
- X - mb_tst (filename) -- This function goes through all the steps needed to
- X make sure a given relation can be opened, but doesn't open it (thus
- X it doesn't need an encryption key). vr uses this one to make sure
- X it can open a relation before asking for a key; that's pretty much
- X its only use.
- X
- X - mb_sel (file, index, buffer, action, comparison_buffer) -- this command
- X searches a given relation for the record you desire, described by
- X "action" and "comparison_value". "file" is a pointer to the structure
- X returned by mb_inc... this structure is used in all other functions to
- X indicate which relation you intend to work with. "index" is the index
- X number by which you wish to search... numbered sequentially by the
- X order in which they were defined in the schema, starting with the
- X number 0. To save trouble when changing schema, it is recommended you
- X use the routine idxnum() to look up an index number by name. "buffer"
- X is merely a structure (like &equipment_rec above) into which MetalBase
- X can return the record, when found. A list of valid actions follows:
- X FIRST (or FRST) -- searches for the first record alphabetically.
- X LAST -- similarly, seeks the last record alphabetically.
- X NEXT -- searches for the next sequential record alphabetically.
- X PREVIOUS (PREV) -- as NEXT, searches for the previous record.
- X EQUAL (EQUL) -- seeks a record containing fields exactly those in
- X "comparison_buffer". If the index used allows duplicates and
- X some exist, EQUAL returns the first of these: all duplicates
- X can be found by subsequent "NEXT" searches. Note that the
- X comparison_buffer and the return buffer need not be the same
- X space, although they may.
- X GTEQ -- EQUAL returns a NOT_FOUND error if a record cannot be found
- X to precisely match the comparison. GTEQ acts as EQUAL in all
- X respects but this; GTEQ will find the record greater
- X alphabetically, or precisely equal to (if one exists), the
- X comparison. In the event that duplicates of the record exist
- X ("Duplicate" being defined logically as a record whose fields
- X used by the current index are precisely equal to another such
- X record's fields for the same index), GTEQ returns the first
- X of these: all duplicates can be found by subsequent "NEXT"
- X searches.
- X GTHAN (GTHN) -- Acts as GTEQ, except GTHAN will ignore precise
- X matches. Useful if you wish to begin searching names, say,
- X after the "Smith"'s. Another way to accomplish this would be
- X to use LTEQ + "Smith", followed by a NEXT...
- X LTEQ -- Searches for a record less alphabetically, or equal to (if
- X one exists), the comparison. In the event that duplicates of
- X the record about to be returned exist, LTEQ returns the last of
- X these: all duplicates can be found by subsequent "PREVIOUS"
- X searches.
- X LTHN (LTHAN) -- Similar to LTEQ in all but one regard: LTHAN will
- X not return a precise duplicate, instead searching to its
- X left for the record before it.
- X CURR (CURRENT) -- After a record is found by a search, MetalBase
- X remembers the location of the record. Searching with the
- X action CURRENT re-reads this most recent record, and returns
- X it in its entirety. As with FIRST, LAST, NEXT and PREVIOUS,
- X the value of "comparison_value" is irrelevant in CURRENT --
- X however, CURRENT is also oblivious to index used (As no
- X actual searching takes place... MetalBase merely recalls a
- X known record).
- X Please note that the above-described action names merely stand for
- X integers, and MetalBase will not understand if you use quotes around
- X the names. These actions must also be written in upper-case.
- X "comparison_buffer" is a structure identical to "buffer", but any
- X data in any of the fields is used for comparison when searching for
- X EQUAL, GTEQ, LTEQ, GTHAN or LTHAN. There are three ways to use that--
- X give it a new record...
- X sample_str sample_rec, target_rec;
- X target_rec.num = 15;
- X mb_sel (rel, idxnum("ix_num"), &sample_rec, EQUAL, &target_rec)
- X or, the same one twice...
- X sample_str sample_rec;
- X sample_rec.num = 15;
- X mb_sel (rel, idxnum("ix_num"), &sample_rec, EQUAL, &sample_rec)
- X or, what I do most, pass in NULL as the comparison (works just like
- X the one above):
- X sample_str sample_rec;
- X sample_rec.num = 15;
- X mb_sel (rel, idxnum("ix_num"), &sample_rec, EQUAL, NULL)
- X All three of these would have the same effect.
- X
- X - mb_upd (file, new_rec) -- After a record is found, it may be updated
- X through mb_upd. MetalBase simply replaces the old record's fields with
- X those indicated in "new_rec". This process usually requires more time
- X than any other, as the record must be disconnected from each index in
- X turn, changed, and reconnected. Occasionally, changing a record will
- X not change certain indices--when this occurs, the index is simply
- X skipped. An update, like an add, will be aborted if the changes would
- X violate a no-duplicates-allowed index.
- X
- X - mb_del (file) -- After a record is found, it may be removed completely by
- X use of mb_del. Once a record is deleted thus, it CANNOT be retrieved.
- X Pre-5.0 versions of MetalBase used a second argument for tracking the
- X current pointer; this code was broken and I removed it. :) So now
- X there's no second argument--again, sorry for changing things on ya.
- X
- X - mb_add (file, new_rec) -- This command adds a new record to a relation. If
- X adding the record described by "new_rec" would violate a non-duplicate
- X index, the addition to the relation will be aborted and an error
- X returned (See the section on Errors, below).
- X
- X - mb_lck (file) -- If, as an example, a program reads a record from a relation
- X used by many terminals simulaneously, waits for a user to enter a new
- X value for one of its fields, and updates the record, it could prove
- X disastrous if the record was read by one terminal, then another...
- X updated on one & re-written, and re-updated by the second terminal. To
- X prevent this type of scenario, mb_lck, when used, excludes other users
- X from reading or writing to a relation. Every operation they try
- X (including mb_inc()) will return MB_LOCKED until the process which
- X called mb_lck() calls mb_unl().
- X
- X - mb_unl (file) -- Removes a lock placed on a relation by mv_lck.
- X
- X - mb_rmv (file) -- This command removes a relation from your desktop. If the
- X file has been locked previously (via mb_lck), the lock is removed.
- X
- X - mb_die () -- This command removes all open relations from your desktop, as
- X if you'd called each one in turn with mb_rmv(file).
- X
- X - mb_exit (ret_code) -- Calls mb_die(), followed by exit(ret_code).
- X
- X - mb_num (file) -- Returns the number of records in a relation. Wheeee...
- X
- X
- XERRORS_________________________________________________________________________
- X
- XIn addition, see the separate documentation on troubleshooting, under the name
- Xtrouble.dox. There's not much, but I tried...
- X
- XBuild / Errors :
- X
- X Cannot open <file.s>............The schema indicated to Build cannot
- X be found.
- X File <file.s> holds no schema...The schema indicated cannot be used
- X definition as a definition of a relation. The
- X most likely cause is that the file is
- X empty.
- X Field <field> declared after....All fields must be declared before any
- X indices indices are declared.
- X Field <field> declared twice....Field names must be unique. Spaces are
- X not allowed in field names.
- X No fields declared before.......A relation must contain fields, and these
- X end reached must be declared before any indices.
- X Incorrect syntax................The definition of a field's length has
- X been entered incorrectly.
- X Field <field> undefined.........An index has been placed on a non-
- X existant field. Check spelling.
- X No fields declared before end...The schema definition is incomplete: it
- X reached must contain at least one field and
- X one index.
- X No indices declared before.....See the above error description.
- X end reached
- X Identifier <?> not recognized...The only valid words for the beginning
- X of a line are "relation" or a relation-
- X name (as the first line), "field",
- X "index", and (optionally) "end".
- X Cannot open relation............The file <file.rel> cannot be written...
- X possible causes are a media error or
- X write-protection on the file.
- X Relation is busy................Relations cannot be re-built until it is
- X not being worked with by any users.
- X The file about to be created....If you build a relation where a relation
- X already exists of the same name already exists, any
- X data in the existing relation will be
- X erased in favor of the new, empty
- X relation.
- X
- XMetalBase / Errors :
- X
- XMetalBase routines either return necessary information (such as, mb_inc()
- Xreturns a relation-pointer, and mb_num() the number of records in a relation),
- Xor 0 to indicate success. The global variable mb_errno will be set to MB_OKAY
- X(0) on success, and another error number (in the 1000's) on failure; the
- Xvariable mb_error is a character string which will always describe the most
- Xrecent error. Possible errors are:
- X
- X 0..MB_OKAY............This is the generic no-problem return code. All
- X functions except mb_inc should return 0 if
- X they have been able to function properly.
- X 1001..MB_NO_ROOM.........Too many relations are open at once -- mb_inc
- X cannot allocate enough space for the new
- X relation. This error can be prevented by
- X re-defining MAX_REL, as with build's warning
- X messages, to a value greater than its default
- X of 5. In addition, having many files open at
- X once may require that you warn <stdio.h>
- X (or config.sys, if you're using MSDOS)...
- X consult your system manuals.
- X 1002..MB_NO_MEMORY.......A malloc() has failed, and the task must be
- X aborted. This is a bad, bad thing to happen.
- X How d'ya fix it? Well, that's hard to say...
- X look around and make sure you're free()'ing any
- X memory you malloc().
- X 1003..MB_NO_OPEN.........The file "file.rel", where "file" is the name
- X passed to mb_inc, cannot be opened. In all
- X probability, it does not exist.
- X 1004..MB_NO_READ.........The file <file.rel> cannot be read. This error
- X is returned only from mb_inc, and is probably
- X caused by read-protection placed on the file.
- X 1005..MB_FORMAT..........This is the generic this-shouldn't-have-happened
- X error. Check out trouble.dox for a quick
- X explanation of what could cause it.
- X 1006..MB_LOCKED..........This error is returned if another user has
- X locked the relation you're trying to access...
- X wait until they haven't, and you'll be fine.
- X 1007..MB_BUSY............Only a certain number of users is allowed to
- X access a relation at any given time. The
- X limits are:
- X MetalBase 3.1, 3.2.........120
- X MetalBase 4.0...............63
- X MetalBase 4.1, 4.1a, 5.0...255
- X 1008..MB_BAD_REL.........This essentially means that the relation* you
- X passed to a function was not returned by
- X a call to mb_inc()... it's an invalid pointer.
- X 1009..MB_NO_WRITE........This error is produced when the relation you've
- X opened can't be written to... perhaps you don't
- X have permission.
- X 1010..MB_TIMEOUT.........A user has stopped a program during a record
- X addition, deletion, or update. These functions
- X place temporary locks on a file, which are
- X removed at the end of their respective
- X procedures. Normally other functions will
- X simply wait for the file to be unlocked, but if
- X the wait time becomes excessive, this error is
- X returned and the function aborted. Try the
- X function again, and if you recieve this error
- X a second time, see the section on Utilites to
- X remove the lock manually.
- X
- X Note that this error is no longer used, as of
- X revision 4.1.
- X 1011..MB_BAD_REC.........A null pointer to a record has been received.
- X So essentially, you've given NULL instead
- X of &rec. Stupid thing to do. :(
- X 1012..MB_CORRUPT.........This relation has an error on an index. See the
- X section on Utilites to repair it. Try to find
- X which index you were working with at the time
- X of the error, in order to speed repair.
- X 1013..MB_BAD_DUP.........The record that has been offered for addition/
- X update would violate an index that has been
- X declared not to allow duplicates.
- X 1014..MB_NO_CURR.........In order to perform a delete or an update,
- X you must have already issued mb_sel() to
- X determine which record you wish to modify.
- X This error indicates you have not done so.
- X 1015..MB_BAD_IDX.........A bad index number has been passed to mb_sel.
- X Valid numbers range 0 through the number of
- X indices in a relation, minus 1.
- X 1016..MB_NO_SUCH.........Generic code returned when the record described
- X cannot be found in the relation searched. If
- X you feel it should have been found, check the
- X index number, action, and comparison value used
- X in the search.
- X 1017..MB_UNKNOWN.........A very unlikely error, receipt of this code
- X indicates you have passed a number greater than
- X 12 or less than 0 to mb_sel as an action.
- X 1018..MB_NO_FIELDS.......You're trying to create a new relation without
- X specifying any fields for it. Stupid you.
- X 1019..MB_NO_INDICES......You're trying to create a new relation without
- X specifying any inidces for it.
- X 1020..MB_BAD_INDEX.......An index you're trying to create has no fields.
- X Remember that the format for indices being
- X created is "nnn,nnn,nnn" --no whitespace
- X allowed without using BUILD.
- X 1021..MB_DISKFULL........This will only happen on mb_add() or when using
- X mbconv, the 4.0+ => 5.0 conversion utility,
- X and is returned whenever there isn't enough
- X free space on the drive to perform the
- X requested operation.
- X 1022..MB_BAD_SERIAL......This will only happen on mb_upd(), if you've
- X changed the serial number of the record
- X you're trying to update. You can't. It won't
- X let you.
- X 1023..MB_TMPDIR..........On some systems, MetalBase requires that you
- X have the environment variable "TMP" set to
- X an appropriate directory for temporary files;
- X for example, "TMP=/tmp; export TMP" or
- X "set TMP=C:\TMP". If you prefer, you can
- X use the variable "TEMP" instead.
- X 1024..MB_TMPERR..........MetalBase cannot work with the directory you've
- X defined as per error #1023 (see TROUBLE.DOX).
- X
- XUTILITIES______________________________________________________________________
- X
- X Five utilities have been released with this package; one, called blast,
- Xremoves user- and system-placed locks on a relation and sets the number of
- Xusers the relation thinks are using it to zero. Impromper closing of a
- Xrelation (ie, not closing one) will cause the number of users to build up
- Xuntil it cannot be used any longer.
- X
- X The second utility included is called vr, for View Relation. Please see
- Xthe separate documentation under ../dox/vr.dox for its description and
- Xinstructions for its use.
- X
- X The third utility is called report... it generates reports of a relation's
- Xcontents. There is sparse documentation under ../dox/report.dox; it might
- Xhelp, it might not. Play with it and it'll work--honest. :)
- X
- X The fourth, and newest utility, is called mbconv--it converts pre-5.0
- XMetalBase relations to 5.0 syntax. Note that the process is safe but
- Xirreversable; and your schema files may need semicolons added just to be
- Xcomplete.
- X
- X And, the final utility is called "form"--it compiles data-entry templates
- Xinto .h files your programs include for data-entry. There's practically
- Xno documentation; just the one example under ../sample. Good luck to you.
- X
- X Other supporting utilities to MetalBase have not been released with this
- Xpackage, primarily because I have not bothered to write them yet. See the
- XReadMe.Too file up one directory to see how to register yourself with me, as
- XI'll write any of the following upon request once you're registered (and
- Xmaybe before, if I have time).
- X
- X Future utilities:
- X
- X * Repair of bad indices and recover of unreclaimed space from
- X previous deletes
- X
- X * Utility to change a relation's schema without destroying its
- X contents (oh boy...)
- X
- X * Relation import/export from standard, Emailable text files.
- X
- X
- XENCRYPTION______________________________________________________________________
- X
- X MetalBase 3.1 and up (not 3.0) automatically encrypt all files unless
- Xtold otherwise. When a relation is opened (using mb_inc()), an integer
- Xencryption-key is passed in to MetalBase. Any records which are added to that
- Xrelation are encrypted using this key, and any records which are retrieved are
- Xdecrypted similarly before they are returned. In this way, any information
- Xwhich is physically stored is encrypted beyond recognition. As long as this
- Xinteger key is the same every time the relation is opened, the encryption is
- Xtotally user-transparent: records are passed to mb_inc and mb_upd in normal
- Xtext, and are retrieved in normal text, but are stored garbled. If the key
- Xchanges, however, the records retreived in the second session will be decrypted
- Xunder the new key, whereas they were encrypted under the former... and the
- Xoutput will be meaningless, for numbers and strings alike.
- X
- X Note that the encryption is apparently working for ALL supported machines
- Xnow--however, this has always been the hardest part to port between machines.
- XIf necessary (or if you simply want to), compile mbase.c (and vr.c/sample.c/
- Xwhatever) with -DNOENCRYPT, and it'll be turned off.
- X
- X For a more thorough explanation of MetalBase's encryption process, see the
- Xseparate documentation crypt.dox.
- X
- X--
- X ___
- X .-',' /\
- X / (_______.------------------. / \ Huan-Ti
- X ( _______|))))))))))))))))))| \ /
- X )__( `------------------' \/
- X `----' richid@owlnet.rice.edu
- X
- END_OF_FILE
- if test 33032 -ne `wc -c <'dox/mbase.dox'`; then
- echo shar: \"'dox/mbase.dox'\" unpacked with wrong size!
- fi
- # end of 'dox/mbase.dox'
- fi
- if test ! -d 'sample' ; then
- echo shar: Creating directory \"'sample'\"
- mkdir 'sample'
- fi
- if test ! -d 'src' ; then
- echo shar: Creating directory \"'src'\"
- mkdir 'src'
- fi
- if test -f 'src/util1.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/util1.c'\"
- else
- echo shar: Extracting \"'src/util1.c'\" \(16120 characters\)
- sed "s/^X//" >'src/util1.c' <<'END_OF_FILE'
- X/*
- X * METALBASE 5.0
- X *
- X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
- X * [ t-richj@microsoft.com ]
- X */
- X
- X#define UTIL_C
- X#include "mbase.h"
- X#include "internal.h"
- X
- Xextern int _started;
- Xextern relation *_list[MAX_REL];
- X
- X/****************************************************************************/
- X
- X#ifdef LONGARGS
- X static void _dec_user (relation *);
- X#else
- X static void _dec_user();
- X#endif
- X
- Xvoid
- X_seterr (err)
- Xmb_err err;
- X{
- X switch (mb_errno = err)
- X {
- X case MB_OKAY: mb_error="No error"; break;
- X case MB_NO_ROOM: mb_error="MAX_REL is #defined to be too small"; break;
- X case MB_NO_MEMORY:mb_error="Not enough memory for requested task"; break;
- X case MB_NO_OPEN: mb_error="Cannot open given filename"; break;
- X case MB_NO_READ: mb_error="Cannot read given filename"; break;
- X case MB_FORMAT: mb_error="Relation is not in MB 5.0 format"; break;
- X case MB_LOCKED: mb_error="Relation is locked by another user"; break;
- X case MB_BUSY: mb_error="Relation is too busy"; break;
- X case MB_BAD_REL: mb_error="Function passed bad relation struct"; break;
- X case MB_NO_WRITE: mb_error="Cannot write given to relation"; break;
- X case MB_TIMEOUT: mb_error="Temporary lock has not been removed"; break;
- X case MB_BAD_REC: mb_error="A null rec pointer has been received"; break;
- X case MB_CORRUPT: mb_error="A corrupt index has been detected"; break;
- X case MB_BAD_DUP: mb_error="Addition would violate a nodups idx"; break;
- X case MB_NO_CURR: mb_error="Current record required for operation";break;
- X case MB_BAD_IDX: mb_error="A bad index number has been received"; break;
- X case MB_NO_SUCH: mb_error="The specified record can't be found"; break;
- X case MB_UNKNOWN: mb_error="Search command invalid"; break;
- X case MB_NO_FIELDS: mb_error="The new relation has no fields"; break;
- X case MB_NO_INDICES: mb_error="The new relation has no indices"; break;
- X case MB_BAD_INDEX: mb_error="The new index has no fields"; break;
- X case MB_DISKFULL: mb_error="There is not enough free space left"; break;
- X case MB_BAD_SERIAL: mb_error="The record's serial number changed"; break;
- X case MB_TMPDIR: mb_error="You must define a TMP directory"; break;
- X case MB_TMPERR: mb_error="Cannot work with TMP directory"; break;
- X default: mb_error="Undefined error--rebuild and pray"; break;
- X }
- X}
- X
- Xrelation *
- X_fill_info (rel, fld, idx)
- Xrelation *rel;
- Xlong fld, idx;
- X{
- X register int i, j;
- X int s, e;
- X char temp[4], buf[128];
- X short tshort;
- X#ifdef STRUCT_4
- X int done = 0;
- X#endif
- X
- X rel->iser = rel->num_f; /* Until we find otherwise */
- X
- X for (i=rel->rec_len=0; i<rel->num_f; i++)
- X {
- X if (lseek (rel->relcode, fld, 0) != fld)
- X {
- X _clr_lck (rel); free (rel);
- X relerr (MB_FORMAT, RNULL);
- X }
- X
- X readx (rel->relcode, buf, 1); rel->type[i] = (ftype)buf[0];
- X readx (rel->relcode, &tshort, 2);
- X switch (rel->type[i])
- X {
- X case T_SHORT:
- X case T_USHORT: rel->siz[i] = 2; /* sizeof(short) */ break;
- X case T_FLOAT: rel->siz[i] = 4; /* sizeof(float) */ break;
- X case T_DOUBLE:
- X case T_MONEY: rel->siz[i] = 8; /* sizeof(double) */ break;
- X case T_TIME:
- X case T_LONG:
- X case T_ULONG: rel->siz[i] = 4; /* sizeof(long) */ break;
- X case T_DATE: rel->siz[i] = 4; /* sizeof(long) */ break;
- X case T_PHONE: rel->siz[i] = 20; /* char[20] */ break;
- X case T_SERIAL: rel->siz[i] = 4; /* sizeof(long) */
- X rel->iser = i;
- X break;
- X default: rel->siz[i] = (int)tshort; break;
- X }
- X
- X#ifdef STRUCT_1
- X if (rel->type[i] != T_CHAR && rel->type[i] != T_PHONE)
- X {
- X if (rel->siz[i] == 8) rel->rec_len = round8(rel->rec_len);
- X else if (rel->siz[i] == 4) rel->rec_len = round4(rel->rec_len);
- X else rel->rec_len = round2(rel->rec_len);
- X }
- X#endif
- X
- X#ifdef STRUCT_3
- X if (rel->type[i] != T_CHAR && rel->type[i] != T_PHONE)
- X {
- X if (rel->siz[i] == 2) rel->rec_len = round2(rel->rec_len);
- X else rel->rec_len = round4(rel->rec_len);
- X }
- X#endif
- X
- X#ifdef STRUCT_4
- X if (rel->type[i] != T_CHAR && rel->type[i] != T_PHONE)
- X {
- X done=1;
- X rel->rec_len = round2(rel->rec_len);
- X }
- X#endif
- X
- X rel->start[i] = rel->rec_len;
- X rel->rec_len += rel->siz[i];
- X
- X readx (rel->relcode, buf, 20);
- X
- X for (j=0; buf[j]!='|'; j++)
- X ;
- X fld += (long)j+4; /* Advance to next field */
- X
- X buf[j] = 0; strcpy (rel->name[i], buf);
- X }
- X
- X#ifdef STRUCT_1
- X rel->rec_len = round8(rel->rec_len);
- X#endif
- X
- X#ifdef STRUCT_3
- X rel->rec_len = round4(rel->rec_len);
- X#endif
- X
- X#ifdef STRUCT_4
- X if (done)
- X rel->rec_len = round2(rel->rec_len);
- X#endif
- X
- X if (lseek (rel->relcode, idx, 0) != idx)
- X {
- X _clr_lck (rel);
- X free (rel);
- X relerr (MB_FORMAT, RNULL);
- X }
- X
- X for (i=0; i<rel->num_i; i++)
- X {
- X readx (rel->relcode, buf, 1); e=(int)buf[0]; /* Dups/NoDups */
- X readx (rel->relcode, buf, 1); s=(int)buf[0]; /* Num/Fields */
- X readx (rel->relcode, buf, 20);
- X
- X for (j=0; buf[j]!=':'; j++)
- X ;
- X
- X idx += (long)j + 3L;
- X lseek (rel->relcode, idx, 0); /* Advance to index' fields */
- X
- X buf[j] = 0;
- X strcpy (rel->iname[i], buf);
- X rel->itype[i]=e; sprintf (rel->idxs[i], "%03d", s);
- X
- X for (j=0; j<s; j++)
- X {
- X readx (rel->relcode, &tshort, 2);
- X sprintf (temp, "%03d", tshort);
- X strcat (rel->idxs[i], temp);
- X }
- X
- X idx = lseek (rel->relcode, 0L, 1); /* Get current position */
- X }
- X
- X rel->hack = idx; /* Current position == reserved segment */
- X
- X if (rel->ver == verCURRENT && ! rel->rdonly)
- X {
- X lseek (rel->lckcode, lckPOS_USERS, 0);
- X readx (rel->lckcode, buf, 1);
- X buf[0] = (char)((unsigned int)buf[0] +1); /* Increment the */
- X lseek (rel->lckcode, lckPOS_USERS, 0); /* number of users */
- X writx (rel->lckcode, buf, 1);
- X
- X _clr_lck (rel);
- X }
- X
- X relerr (MB_OKAY, rel);
- X}
- X
- Xvoid
- X_close_proc (rel)
- Xrelation *rel;
- X{
- X if (rel->ver == verCURRENT)
- X {
- X (void)mb_unl (rel);
- X _dec_user (rel);
- X }
- X
- X close (rel->relcode);
- X free (rel);
- X}
- X
- Xvoid
- X_divine_mask (rel, key)
- Xrelation *rel;
- Xint key;
- X{
- X rel->mask = (char)(
- X ((key & (int)0x04) << 5) | /* 00000100 -> 10000000 */
- X ((key & (int)0x30) << 1) | /* 00110000 -> 01100000 */
- X ((key & (int)0x80) >> 3) | /* 10000000 -> 00010000 */
- X ((key & (int)0x03) << 2) | /* 00000011 -> 00001100 */
- X ((key & (int)0x40) >> 5) | /* 01000000 -> 00000010 */
- X ((key & (int)0x08) >> 3)); /* 00001000 -> 00000001 */
- X}
- X
- Xint
- X_identify (rel)
- Xrelation *rel;
- X{
- X register int i;
- X if (rel == RNULL || !_started) return -1;
- X for (i=0; i<MAX_REL; i++)
- X if (_list[i] == rel) break;
- X if (i == MAX_REL) return -1;
- X if (rel->ver != verCURRENT) return -2;
- X return i;
- X}
- X
- Xmb_err
- X_format (rel, rec, stage)
- Xrelation *rel;
- Xdataptr rec;
- Xint stage;
- X{
- X register int i;
- X double tdbl;
- X long nexts, tlong;
- X int a;
- X long ac,pre,num,ext;
- X char *pch, temp[25];
- X
- X if (! rec) baderr (MB_BAD_REC);
- X
- X if (stage == 2)
- X { GO_NEXTS (rel);
- X readx (rel->relcode, &nexts, 4);
- X }
- X
- X for (i=a=0; i<rel->num_f; i++)
- X {
- X if (stage == 1)
- X {
- X if (rel->type[i] == T_PHONE)
- X {
- X pch = (char *)rec + rel->start[i];
- X scn_phone (&ac,&pre,&num,&ext, pch);
- X strcpy (temp, fmt_phone (ac,pre,num,ext, -1));
- X strncpy (pch, temp, 20);
- X }
- X if (rel->type[i] == T_MONEY)
- X {
- X tdbl = *(double *)((char *)rec+rel->start[i]);
- X tlong = (long)(tdbl * 100.0); tdbl = (double)tlong / 100.0;
- X *(double *)((char *)rec+rel->start[i]) = tdbl;
- X }
- X }
- X else
- X {
- X if (rel->type[i] == T_SERIAL)
- X {
- X *(long *)((char *)rec+rel->start[i]) = nexts;
- X rel->serial = nexts;
- X _cryptf ((dataptr)((char *)rec+rel->start[i]), 4, rel->mask);
- X a = 1;
- X }
- X }
- X }
- X
- X if (a)
- X {
- X GO_NEXTS (rel); nexts++;
- X writx (rel->relcode, &nexts, 4);
- X }
- X
- X return MB_OKAY;
- X}
- X
- Xvoid
- X_crypt (rel, rec)
- Xrelation *rel;
- Xdataptr rec;
- X{
- X#ifndef NOENCRYPT
- X register int i;
- X
- X if (rel->mask)
- X for (i=0; i<rel->num_f; i++)
- X _cryptf ((char *)rec+rel->start[i], rel->siz[i], rel->mask);
- X#else
- X ; /* Some compilers complain about null-functions */
- X#endif
- X}
- X
- Xvoid
- X_cryptf (rec, siz, mask)
- Xdataptr rec;
- Xint siz, mask;
- X{
- X#ifndef NOENCRYPT
- X register int i;
- X register char *c;
- X
- X if (mask != 0)
- X for (i=0,c=rec; i<siz; i++,c++)
- X { *c ^= mask;
- X mask = (mask + 1) & (int)0xFF;
- X }
- X#else
- X ; /* Some compilers complain about null-functions */
- X#endif
- X}
- X
- Xmb_err
- X_check_dup (rel, rec, idx, ign)
- Xrelation *rel;
- Xdataptr rec;
- Xint idx;
- Xlong ign;
- X{
- X dataptr mem;
- X long pos;
- X int dir;
- X
- X if (rel->itype[idx] == 1) reterr (MB_OKAY, 0);
- X
- X GO_TOP (rel, idx);
- X readx (rel->relcode, &pos, 4);
- X if (pos==0L)
- X reterr (MB_OKAY, 0);
- X
- X if ((mem = (dataptr)malloc (1+ rel->rec_len)) == NULL)
- X reterr (MB_NO_MEMORY, -1);
- X
- X for (;;)
- X {
- X dir = _compare (rel, rec, _memrec(rel,pos,mem), idx);
- X
- X if (dir == 0)
- X {
- X if (pos == ign) break; /* If we're about to change the rec, okay */
- X free (mem);
- X
- X reterr (MB_BAD_DUP, -1);
- X }
- X
- X GO_POINT (rel, pos, idx, dir);
- X readx (rel->relcode, &pos, 4);
- X
- X if (pos == 0L) break;
- X }
- X free (mem);
- X
- X reterr (MB_OKAY, MB_OKAY);
- X}
- X
- Xlong
- X_append (rel, rec)
- Xrelation *rel;
- Xdataptr rec;
- X{
- X long rcd, temp;
- X register int i;
- X char buf[2];
- X
- X lseek (rel->relcode, POS_NUMREC, 0);
- X readx (rel->relcode, &rcd, 4); rcd++;
- X lseek (rel->relcode, POS_NUMREC, 0);
- X writx (rel->relcode, &rcd, 4);
- X
- X GO_START (rel, rcd);
- X
- X for (i=0,temp=0L,buf[0]=BAL_EV; i<rel->num_i; i++)
- X {
- X writx (rel->relcode, &temp, 4);
- X writx (rel->relcode, &temp, 4);
- X writx (rel->relcode, &temp, 4);
- X writx (rel->relcode, buf, 1);
- X }
- X writx (rel->relcode, rec, rel->rec_len);
- X
- X return rcd;
- X}
- X
- Xvoid
- X_remove (rel, bad)
- Xrelation *rel;
- Xlong bad;
- X{
- X int i, dir;
- X long rep, tmp;
- X char temp[5];
- X dataptr buf;
- X
- X lseek (rel->relcode, POS_NUMREC, 0);
- X readx (rel->relcode, &rep, 4); rep--;
- X lseek (rel->relcode, POS_NUMREC, 0);
- X writx (rel->relcode, &rep, 4); rep++; /* Find replacement record */
- X
- X if (rep == bad) return;
- X
- X if ((buf=(dataptr)malloc (rel->rec_len +13*rel->num_i +1)) == NULL) return;
- X
- X GO_START (rel, rep);
- X readx (rel->relcode, buf, rel->rec_len +13*rel->num_i);
- X GO_START (rel, bad);
- X writx (rel->relcode, buf, rel->rec_len +13*rel->num_i);
- X
- X for (i = 0; i < rel->num_i; i++)
- X {
- X GO_POINT (rel, rep, i, 0);
- X readx (rel->relcode, &tmp, 4);
- X GO_BAL (rel, rep, i);
- X readx (rel->relcode, temp, 1); dir = (temp[0] & PARDIR);
- X
- X if (tmp == 0L)
- X GO_TOP (rel, i);
- X else
- X GO_POINT (rel, tmp, i, (dir ? 1 : -1));
- X writx (rel->relcode, &bad, 4);
- X
- X GO_POINT (rel, rep, i, -1);
- X readx (rel->relcode, &tmp, 4);
- X if (tmp != 0L)
- X {
- X GO_POINT (rel, tmp, i, 0);
- X writx (rel->relcode, &bad, 4);
- X }
- X
- X GO_POINT (rel, rep, i, 1);
- X readx (rel->relcode, &tmp, 4);
- X if (tmp != 0L)
- X {
- X GO_POINT (rel, tmp, i, 0);
- X writx (rel->relcode, &bad, 4);
- X }
- X }
- X
- X free (buf);
- X}
- X
- Xmb_err
- X_link (rel, rcd) /* CACHED */
- Xrelation *rel;
- Xlong rcd;
- X{
- X register int i;
- X
- X _free_cache ();
- X
- X for (i=0; i<rel->num_i; i++)
- X {
- X _drop (rel, rcd, i, 0L);
- X if (_check (rel, rcd, 0L, i))
- X {
- X _flush_cache (rel, i);
- X return mb_errno;
- X }
- X _flush_cache (rel, i);
- X }
- X return MB_OKAY;
- X}
- X
- Xvoid
- X_drop (rel, rcd, idx, top) /* CACHED */
- Xrelation *rel;
- Xlong rcd, top;
- Xint idx;
- X{
- X long pos, par;
- X int dir;
- X char temp[5];
- X dataptr a, b;
- X cache *ptr;
- X
- X ptr = _read_cache (rel, top, idx);
- X if (top == 0L)
- X {
- X pos = ptr->num;
- X par = 0L;
- X }
- X else
- X {
- X par = ptr->parent;
- X pos = top;
- X }
- X
- X a = (dataptr)malloc (1+ rel->rec_len);
- X b = (dataptr)malloc (1+ rel->rec_len);
- X
- X for ( ; pos != 0L; )
- X {
- X ptr = _read_cache (rel, pos, idx);
- X temp[0] = ptr->parbal;
- X
- X dir = _compare (rel, _memrec(rel,rcd,a), b=_memrec(rel,pos,b), idx );
- X/*
- X * POSSIBLE ERROR POINT -- _memrec is being used twice in one
- X * function call. If it's going to be a problem, it'll show up after
- X * the second add, delete or update.... if it doesn't, this isn't
- X * the cause of your trouble.
- X *
- X */
- X
- X if (dir == 0)
- X {
- X dir = ((temp[0] & BAL) == BAL_RT || (temp[0] & BAL) == BAL_FR) ? -1:1;
- X }
- X temp[0] += dir;
- X
- X _change_cache (ptr, parbal, temp[0]);
- X
- X par = pos;
- X pos = _cache_field (ptr, dir);
- X }
- X
- X free (a); free (b);
- X
- X if (par == 0L)
- X {
- X ptr = _read_cache (rel, 0L, idx);
- X _change_cache (ptr, num, rcd);
- X }
- X else
- X {
- X temp[0] = (char)(((dir==1) ? PARDIR:0) | BAL_EV);
- X
- X ptr = _read_cache (rel, rcd, idx);
- X _change_cache (ptr, parbal, temp[0]);
- X
- X ptr = _read_cache (rel, par, idx);
- X if (dir == -1) _changeqcache (ptr, left, rcd);
- X else if (dir == 0) _changeqcache (ptr, parent, rcd);
- X else _changeqcache (ptr, right, rcd);
- X ptr->changed = 1;
- X }
- X
- X ptr = _read_cache (rel, rcd, idx);
- X _change_cache (ptr, parent, par);
- X}
- X
- Xmb_err
- X_check (rel, st, ed, idx) /* CACHED */
- Xrelation *rel;
- Xlong st, ed;
- Xint idx;
- X{
- X long pos, tmp;
- X cache *ptr;
- X
- X for (pos = st; pos != ed; )
- X {
- X if (pos == 0L) break;
- X
- X ptr = _read_cache (rel, pos, idx);
- X tmp = ptr->parent;
- X
- X if (! BALANCED ( (ptr->parbal & BAL) ))
- X if (_balance (rel, pos, idx, (int)(ptr->parbal & BAL)))
- X return mb_errno;
- X pos = tmp;
- X }
- X
- X return MB_OKAY;
- X}
- X
- X/****************************************************************************/
- X
- Xint
- Xcompare (rel, ptra, ptrb, idx) /* -1 == ptra < ptrb */
- Xrelation *rel;
- Xdataptr ptra, ptrb;
- Xint idx;
- X{
- X int i;
- X if (_identify (rel) < 0) interr (MB_BAD_REL, -1);
- X if (idx < 0 || idx >= rel->num_i) interr (MB_BAD_IDX, -1);
- X if (ptra == ptrb) interr (MB_OKAY, 0);
- X
- X _crypt (rel, ptra);
- X _crypt (rel, ptrb);
- X i = _compare (rel, ptra, ptrb, idx);
- X _crypt (rel, ptra);
- X _crypt (rel, ptrb);
- X interr (MB_OKAY, i);
- X}
- X
- Xint
- Xidxnum (rel, name)
- Xrelation *rel;
- Xchar *name;
- X{
- X int i;
- X
- X if (_identify (rel) < 0) interr (MB_BAD_REL, -1);
- X
- X for (i = 0; i < rel->num_i; i++)
- X if (! strcmp (name, rel->iname[i]))
- X break;
- X if (i == rel->num_i) interr (MB_BAD_IDX, -1);
- X
- X interr (MB_OKAY, i);
- X}
- X
- Xstatic void
- X_dec_user (rel)
- Xrelation *rel;
- X{
- X char buf[2];
- X
- X lseek (rel->lckcode, lckPOS_USERS, 0);
- X readx (rel->lckcode, buf, 1);
- X buf[0] = (char)((unsigned int)buf[0] -1);
- X if ((uchar)buf[0] > 254) buf[0] = 0;
- X lseek (rel->lckcode, lckPOS_USERS, 0); writx (rel->lckcode, buf, 1);
- X}
- X
- END_OF_FILE
- if test 16120 -ne `wc -c <'src/util1.c'`; then
- echo shar: \"'src/util1.c'\" unpacked with wrong size!
- fi
- # end of 'src/util1.c'
- fi
- echo shar: End of archive 1 \(of 8\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 8 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-