home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Education Master 1994 (4th Edition)
/
EDUCATIONS_MASTER_4TH_EDITION.bin
/
files
/
progng_c
/
smallc
/
io.cs
< prev
next >
Wrap
Text File
|
1994-01-01
|
11KB
|
399 lines
/* SDB - relation file I/O routines */
#include "stdio.h"
#include "sdbio.h"
/* global error code variable */
int dbv_errcode;
/* list of currently loaded relation definitions */
static struct relation *relations = NULL;
/* rfind - find the specified relation */
static struct relation *rfind(rname)
char *rname;
{
int fd;
char filename[RNSIZE+5];
struct relation *rptr;
/* look for relation in list currently loaded */
for (rptr = relations; rptr != NULL; rptr = rptr->rl_next)
if (db_sncmp(rname,rptr->rl_name,RNSIZE) == 0)
return (rptr);
/* create a file name */
make_fname(filename,rname);
/* lookup the relation file */
#ifdef Lattice
if ((fd = open(filename,0x8000)) == -1) /*dns*/
#else
if ((fd = open(filename,0)) == -1)
#endif
return (db_nerror(RELFNF));
/* allocate a new relation structure */
if ((rptr = malloc(sizeof(struct relation))) == NULL) {
close(fd);
return (db_nerror(INSMEM));
}
/* initialize the relation structure */
rptr->rl_scnref = 0;
/* read the header block */
if ( read(fd,&rptr->rl_header,512) != 512) {
free(rptr);
close(fd);
return (db_nerror(BADHDR));
}
/* close the relation file */
close(fd);
/* extract header information */
rptr->rl_tcnt = db_cvword(rptr->rl_header.hd_tcnt);
rptr->rl_tmax = db_cvword(rptr->rl_header.hd_tmax);
rptr->rl_data = db_cvword(rptr->rl_header.hd_data);
rptr->rl_size = db_cvword(rptr->rl_header.hd_size);
/* store the relation name */
strncpy(rptr->rl_name,rname,RNSIZE);
/* link new relation into relation list */
rptr->rl_next = relations;
relations = rptr;
/* return the new relation structure pointer */
return (rptr);
}
/* db_ropen - open a relation file */
struct scan *db_ropen(rname)
char *rname;
{
struct relation *rptr;
struct scan *sptr;
char filename[RNSIZE+5];
/* find the relation definition */
if ((rptr = rfind(rname)) == NULL)
return (NULL);
/* allocate a new scan structure */
if ((sptr = malloc(sizeof(struct scan))) == NULL)
return (db_nerror(INSMEM));
/* allocate a tuple buffer */
if ((sptr->sc_tuple = malloc(rptr->rl_size)) == NULL) {
free(sptr);
return (db_nerror(INSMEM));
}
/* initialize the scan structure */
sptr->sc_relation = rptr; /* store the relation struct addrs */
sptr->sc_dtnum = 0; /* desired tuple (non-existant) */
sptr->sc_atnum = 0; /* actual tuple (non-existant) */
sptr->sc_store = FALSE; /* no store done since open */
/* open relation file if necessary */
if (rptr->rl_scnref++ == 0) {
/* create the relation file name */
make_fname(filename,rname);
/* open the relation file */
#ifdef Lattice
if ((rptr->rl_fd = open(filename,0x8002)) == -1) { /*dns*/
#else
if ((rptr->rl_fd = open(filename,2)) == -1) {
#endif
rptr->rl_scnref--;
free(sptr->sc_tuple); free(sptr);
return (db_nerror(RELFNF));
}
}
/* return the new scan structure pointer */
return (sptr);
}
/* db_rclose - close the relation file */
int db_rclose(sptr)
struct scan *sptr;
{
struct relation *rptr,*lastrptr;
/* close relation file if this is the last reference */
if (--sptr->sc_relation->rl_scnref == 0) {
/* rewrite header if any stores took place */
if (sptr->sc_store) {
/* store the tuple count back in the header */
db_cvbytes(sptr->sc_relation->rl_tcnt,
sptr->sc_relation->rl_header.hd_tcnt);
/* write the header block */
lseek(sptr->sc_relation->rl_fd,0L,0);
if (write(sptr->sc_relation->rl_fd,
&sptr->sc_relation->rl_header,512) != 512) {
close(sptr->sc_relation->rl_fd);
free(sptr->sc_tuple); free(sptr);
return (db_ferror(BADHDR));
}
}
/* close the relation file */
close(sptr->sc_relation->rl_fd);
/* free the relation header */
lastrptr = NULL;
for (rptr = relations; rptr != NULL; rptr = rptr->rl_next) {
if (rptr == sptr->sc_relation) {
if (lastrptr == NULL)
relations = rptr->rl_next;
else
lastrptr->rl_next = rptr->rl_next;
}
lastrptr = rptr;
}
free(sptr->sc_relation);
}
/* free the scan structure */
free(sptr->sc_tuple); free(sptr);
/* return successfully */
return (TRUE);
}
/* db_rcompress - compress a relation file */
int db_rcompress(sptr)
struct scan *sptr;
{
unsigned int next,nextfree,tcnt;
/* get the last used tuple */
tcnt = sptr->sc_relation->rl_tcnt;
/* loop through all of the tuples */
for (next = nextfree = 1; next <= tcnt; next++) {
/* read the tuple */
seek(sptr,next);
if (read(sptr->sc_relation->rl_fd,
sptr->sc_tuple,sptr->sc_relation->rl_size)
!= sptr->sc_relation->rl_size)
return (db_ferror(TUPINP));
/* rewrite the tuple if it is active */
if (sptr->sc_tuple[0] == ACTIVE) {
/* rewrite it only if it must move */
if (next != nextfree) {
/* write the tuple */
seek(sptr,nextfree);
if (write(sptr->sc_relation->rl_fd,
sptr->sc_tuple,sptr->sc_relation->rl_size)
!= sptr->sc_relation->rl_size)
return (db_ferror(TUPOUT));
}
/* update the next free tuple number */
nextfree += 1;
}
}
/* update the tuple count */
sptr->sc_relation->rl_tcnt = nextfree - 1;
/* remember which tuple is in the buffer */
sptr->sc_atnum = sptr->sc_relation->rl_tcnt;
/* reset the desired tuple */
sptr->sc_dtnum = 0;
/* remember that the index needs rewriting */
sptr->sc_store = TRUE;
/* return successfully */
return (TRUE);
}
/* db_rbegin - begin scan at first tuple in relation */
db_rbegin(sptr)
struct scan *sptr;
{
/* begin with the first tuple in the file */
sptr->sc_dtnum = 0;
}
/* db_rfetch - fetch the next tuple from the relation file */
int db_rfetch(sptr)
struct scan *sptr;
{
/* look for an active tuple */
while (TRUE) {
/* check for this being the last tuple */
if (!db_rget(sptr,sptr->sc_dtnum + 1))
return (FALSE);
/* increment the tuple number */
sptr->sc_dtnum += 1;
/* return if the tuple found is active */
if (sptr->sc_tuple[0] == ACTIVE)
return (TRUE);
}
}
/* db_rupdate - update the current tuple */
int db_rupdate(sptr)
struct scan *sptr;
{
/* make sure the status byte indicates an active tuple */
sptr->sc_tuple[0] = ACTIVE;
/* write the tuple */
return (db_rput(sptr,sptr->sc_atnum));
}
/* db_rdelete - delete the current tuple */
int db_rdelete(sptr)
struct scan *sptr;
{
/* make sure the status byte indicates a deleted tuple */
sptr->sc_tuple[0] = DELETED;
/* write the tuple */
return (db_rput(sptr,sptr->sc_atnum));
}
/* db_rstore - store a new tuple */
int db_rstore(sptr)
struct scan *sptr;
{
/* make sure there's room for this tuple */
if (sptr->sc_relation->rl_tcnt == sptr->sc_relation->rl_tmax)
return (db_ferror(RELFUL));
/* make sure the status byte indicates an active tuple */
sptr->sc_tuple[0] = ACTIVE;
/* write the tuple */
if (!db_rput(sptr,sptr->sc_relation->rl_tcnt + 1))
return (FALSE);
/* update the tuple count */
sptr->sc_relation->rl_tcnt += 1;
/* remember that a tuple was stored */
sptr->sc_store = TRUE;
/* return successfully */
return (TRUE);
}
/* db_rget - get a tuple from the relation file */
int db_rget(sptr,tnum)
struct scan *sptr; unsigned int tnum;
{
/* check to see if the tuple is already in the buffer */
if (tnum == sptr->sc_atnum)
return (TRUE);
/* check for this being beyond the last tuple */
if (tnum > sptr->sc_relation->rl_tcnt)
return (db_ferror(TUPINP));
/* read the tuple */
seek(sptr,tnum);
if (read(sptr->sc_relation->rl_fd,
sptr->sc_tuple,sptr->sc_relation->rl_size)
!= sptr->sc_relation->rl_size)
return (db_ferror(TUPINP));
/* remember which tuple is in the buffer */
sptr->sc_atnum = tnum;
/* return successfully */
return (TRUE);
}
/* db_rput - put a tuple to a relation file */
int db_rput(sptr,tnum)
struct scan *sptr; unsigned int tnum;
{
/* check for this being beyond the maximum tuple */
if (tnum > sptr->sc_relation->rl_tmax)
return (db_ferror(TUPOUT));
/* write the tuple */
seek(sptr,tnum);
if (write(sptr->sc_relation->rl_fd,
sptr->sc_tuple,sptr->sc_relation->rl_size)
!= sptr->sc_relation->rl_size)
return (db_ferror(TUPOUT));
/* remember which tuple is in the buffer */
sptr->sc_atnum = tnum;
/* return successfully */
return (TRUE);
}
/* seek - seek a tuple in a relation file */
static seek(sptr,tnum)
struct scan *sptr; unsigned int tnum;
{
long offset;
offset = (long) sptr->sc_relation->rl_data +
((long) (tnum - 1) * (long) sptr->sc_relation->rl_size);
lseek(sptr->sc_relation->rl_fd,offset,0);
}
/* make_fname - make a relation name into a file name */
static make_fname(fname,rname)
char *fname,*rname;
{
strncpy(fname,rname,RNSIZE); fname[RNSIZE] = 0;
strcat(fname,".sdb");
}
/* db_nerror - store the error code and return NULL */
int db_nerror(errcode)
int errcode;
{
dbv_errcode = errcode;
return (NULL);
}
/* db_ferror - store the error code and return FALSE */
int db_ferror(errcode)
int errcode;
{
dbv_errcode = errcode;
return (FALSE);
}
/* db_cvword - convert 2 bytes to a word */
int db_cvword(bytes)
char bytes[2];
{
return (((bytes[1] & 0377) << 8) + (bytes[0] & 0377));
}
/* db_cvbytes - convert a word to 2 bytes */
db_cvbytes(word,bytes)
int word; char bytes[2];
{
bytes[0] = word;
bytes[1] = word >> 8;
}