/*
Copyright (C) 1991, Andrew Molitor. All rights reserved.
*/
/*
#define DEBUG
*/
/*
This a a dbm emulation module for VMS, using indexed files to do
the database thang. It emulates new dbm.
*/
#include "autoconf.h"
#include "copyright.h"
#ifndef lint
static char *RCSid = "$Id: vms_dbm.c,v 1.7 1995/03/21 00:01:39 ambar Exp $";
USE(RCSid);
#endif
#include <ssdef.h>
#include <rms.h>
#include "vms_dbm.h"
static char dbmbuff[MAX_RECORD];
DBM *
dbm_open(filename, flags, mode)
char *filename;
int flags; /* Ignored. */
int mode; /* Ignored. */
{
DBM *newdb;
char *name;
int status;
/* Make a new DBM struct */
#ifdef DEBUG
printf("Opening DB file %s\n", filename);
#endif
newdb = (DBM *) malloc(sizeof(struct rmsblocks));
if (newdb == (DBM *) 0) {
return ((DBM *) 0);
}
name = (char *) malloc(strlen(filename) + 1);
if (name == (char *) 0) {
free((char *) newdb);
return ((DBM *) 0);
}
strcpy(name, filename);
/* Fill it in with stuff */
/* FAB */
newdb->fab = cc$rms_fab;
(newdb->fab).fab$l_fna = name;
(newdb->fab).fab$l_xab = &(newdb->xab);
(newdb->fab).fab$b_fns = strlen(name);
(newdb->fab).fab$b_bks = BUCKET_SIZE;
(newdb->fab).fab$b_org = FAB$C_IDX;
(newdb->fab).fab$w_mrs = MAX_RECORD;
(newdb->fab).fab$b_rfm = FAB$C_VAR;
(newdb->fab).fab$l_fop = FAB$M_CIF;
(newdb->fab).fab$b_fac = FAB$M_PUT | FAB$M_GET | FAB$M_UPD | FAB$M_DEL;
/* RAB */
newdb->rab = cc$rms_rab;
(newdb->rab).rab$l_fab = &(newdb->fab);
(newdb->rab).rab$b_rac = RAB$C_KEY;
(newdb->rab).rab$l_rop = RAB$V_UIF | RAB$V_LIM;
(newdb->rab).rab$l_ubf = dbmbuff;
(newdb->rab).rab$w_usz = MAX_RECORD;
/* XAB */
newdb->xab = cc$rms_xabkey;
(newdb->xab).xab$b_dtp = XAB$C_STG;
(newdb->xab).xab$w_pos = 0;
(newdb->xab).xab$b_siz = KEY_SIZE;
(newdb->xab).xab$b_ref = 0;
/* Try to open it */
status = sys$create(&(newdb->fab));
if ((status & 1) == 0) { /* Failed open, try to create it */
#ifdef DEBUG
printf("$open failed, status %d.\n", status);
#endif
goto bag;
}
/* We're poppin'. Connect the rab up. */
status = sys$connect(&(newdb->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$connect failed, status %d\n", status);
#endif
goto bag;
}
/* Ready to go, we hope */
#ifdef DEBUG
printf("Succeeded.\n");
#endif
return (newdb);
bag:
free((char *) newdb);
free((char *) name);
return ((DBM *) 0);
}
dbm_close(db)
DBM *db;
{
sys$close(&(db->fab));
free((db->fab).fab$l_fna);
free((char *) db);
}
datum
dbm_fetch(db, key)
DBM *db;
datum key;
{
int status;
int i;
datum answer;
char keybuff[KEY_SIZE];
char *p, *s;
/* Fill in the key part of the rab */
p = keybuff;
s = key.dptr;
for (i = 0; i < KEY_SIZE && i < key.dsize; i++)
*p++ = *s++;
while (i++ < KEY_SIZE)
*p++ = '\0';
(db->rab).rab$l_kbf = keybuff;
(db->rab).rab$b_ksz = KEY_SIZE;
/* Now go get it */
status = sys$get(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$get failed, status %d\n", status);
#endif
goto bag;
}
answer.dsize = (db->rab).rab$w_rsz - KEY_SIZE;
answer.dptr = malloc(answer.dsize);
if (answer.dptr == (char *) 0) {
goto bag;
}
bcopy((db->rab).rab$l_rbf + KEY_SIZE, answer.dptr, answer.dsize);
return (answer);
bag:
answer.dptr = (char *) 0;
answer.dsize = 0;
return (answer);
}
dbm_store(db, key, content, flags)
DBM *db;
datum key;
datum content;
int flags; /* Ignored */
{
int status;
int i;
char *p, *s;
/* Build the record */
#ifdef DEBUG
printf("dbm_store: data size = %d\n", content.dsize);
#endif
/* Fill in KEY_SIZE bytes of key */
p = dbmbuff;
s = key.dptr;
for (i = 0; i < key.dsize && i < KEY_SIZE; i++)
*p++ = *s++;
while (i++ < KEY_SIZE)
*p++ = '\0';
bcopy(content.dptr, dbmbuff + KEY_SIZE, content.dsize);
(db->rab).rab$l_rbf = dbmbuff;
(db->rab).rab$w_rsz = content.dsize + KEY_SIZE;
(db->rab).rab$l_kbf = dbmbuff;
(db->rab).rab$b_ksz = KEY_SIZE;
#ifdef DEBUG
printf("Searching for record %s, size = %d\n",
dbmbuff, (db->rab).rab$w_rsz);
#endif
status = sys$find(&(db->rab));
if (status == RMS$_NORMAL) {
status = sys$update(&(db->rab));
} else if (status == RMS$_RNF) {
#ifdef DEBUG
printf("Record not found. Trying $put %d\n", status);
#endif
status = sys$put(&(db->rab));
}
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$update/$put failed. status code %d\n", status);
#endif
return (1);
}
return (0);
}
dbm_delete(db, key)
DBM *db;
datum key;
{
int status;
int i;
datum answer;
char keybuff[KEY_SIZE];
char *p, *s;
/* Fill in the key part of the rab */
p = keybuff;
s = key.dptr;
for (i = 0; i < KEY_SIZE && i < key.dsize; i++)
*p++ = *s++;
while (i++ < KEY_SIZE)
*p++ = '\0';
(db->rab).rab$l_kbf = keybuff;
(db->rab).rab$b_ksz = KEY_SIZE;
/* Now go KILL it */
status = sys$find(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$find in delete() failed, status %d\n", status);
#endif
return (1);
}
status = sys$delete(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$delete failed, status %d\n", status);
#endif
return (1);
}
return (0);
}
datum
dbm_firstkey(db)
DBM *db;
{
int status;
datum answer;
status = sys$rewind(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$rewind failed, status == %d\n", status);
#endif
goto bag;
}
/* Set the file to sequential access */
(db->rab).rab$b_rac = RAB$C_SEQ;
status = sys$get(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$get in firstkey() failed. status = %d\n", status);
#endif
goto bag;
}
/* Save the key away */
bcopy((db->rab).rab$l_rbf, db->currkey, KEY_SIZE);
/* Put the file back to random access. */
(db->rab).rab$b_rac = RAB$C_KEY;
answer.dptr = db->currkey;
answer.dsize = strlen(db->currkey);
return (answer);
bag:
(db->rab).rab$b_rac = RAB$C_KEY;
answer.dptr = (char *) 0;
answer.dsize = 0;
return (answer);
}
datum
dbm_nextkey(db)
DBM *db;
{
int status;
datum answer;
(db->rab).rab$l_kbf = db->currkey;
(db->rab).rab$b_ksz = KEY_SIZE;
/* Seek over to the current record */
status = sys$find(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$find in nextkey() failed. Status = %d\n", status);
#endif
goto bag;
}
/* set file sequential */
(db->rab).rab$b_rac = RAB$C_SEQ;
/* Skip one */
status = sys$find(&(db->rab));
if (status == RMS$_EOF) { /* We're done! */
#ifdef DEBUG
printf("EOF detected in nextkey.\n");
#endif
status = sys$rewind(&(db->rab));
#ifdef DEBUG
if ((status & 1) == 0) {
printf("$rewind at EOF, in nextkey(), failed. status = %d\n", status);
}
#endif
goto bag;
}
status = sys$get(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$get in nextkey() failed. status = %d\n", status);
#endif
goto bag;
}
/* Save the key away */
bcopy((db->rab).rab$l_rbf, db->currkey, KEY_SIZE);
/* Put the file back to random access. */
(db->rab).rab$b_rac = RAB$C_KEY;
answer.dptr = db->currkey;
answer.dsize = strlen(db->currkey);
return (answer);
bag:
answer.dptr = (char *) 0;
answer.dsize = 0;
/* Put the file back to random access. */
(db->rab).rab$b_rac = RAB$C_KEY;
return (answer);
}