Net2/usr/src/contrib/isode/quipu/turbo_disk.c

/* turbo_disk.c */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/turbo_disk.c,v 7.4 91/03/09 11:57:14 mrose Exp $";
#endif

/* 
 * $Header: /f/osi/quipu/RCS/turbo_disk.c,v 7.4 91/03/09 11:57:14 mrose Exp $
 *
 *
 * $Log:	turbo_disk.c,v $
 * Revision 7.4  91/03/09  11:57:14  mrose
 * update
 * 
 * Revision 7.3  91/02/22  09:40:07  mrose
 * Interim 6.8
 * 
 */

/*
 *				  NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


#include <stdio.h>
#include "quipu/config.h"
#include "quipu/entry.h"
#include "psap.h"
#include "quipu/malloc.h"
#include "logger.h"

#ifdef	TURBO_DISK

#include <gdbm.h>
#ifdef  BSD42
#include <sys/file.h>
#endif
#ifdef  SYS5
#include <fcntl.h>
#endif

extern RDN	parse_rdn;
extern LLog 	*log_dsap;
extern int	gdbm_errno;
extern datum	turbo_header_key;

/*
 * turbo_open -- open a dbm edb file for writing.  e is a pointer to the
 * entry to be written.  Parent is used to construct the name of
 * the file to write.  If create is 0 a new database will not be created,
 * otherwise it will and a backup of the old one will be made.
 */

static GDBM_FILE turbo_open(parent, create)
Entry	parent;
char	create;
{
	GDBM_FILE	db;
	DN		dn, get_copy_dn();
	char		*filename, *dn2edbfile();
	char		bakname[1024], turbo_gfname[1024];

	LLOG (log_dsap, LLOG_TRACE,("turbo: open"));

	/* get the name of the edb file to write to */
	dn = get_copy_dn (parent);
	if ((filename = dn2edbfile (dn)) == NULLCP) {
		dn_free (dn);
		LLOG (log_dsap, LLOG_EXCEPTIONS,("turbo: dn2edbfile failed"));
		return (NULL);
	}
	dn_free(dn);
	strcpy(turbo_gfname, filename);
	strcat(turbo_gfname, ".gdbm");
	strcpy(bakname, turbo_gfname);
	strcat(bakname, ".bak");

	/* try to open it */
	if ( create ) {
		/* first make a backup of the old one */
		(void) unlink(bakname);
		if ( link(turbo_gfname, bakname) != 0 )
			LLOG (log_dsap, LLOG_EXCEPTIONS, 
			    ("turbo: could not make backup"));
		(void) unlink(turbo_gfname);

		/* then open the new one */
		db = gdbm_open(turbo_gfname, 0, GDBM_WRCREAT, 0600, 0);
	} else
		db = gdbm_open(turbo_gfname, 0, GDBM_WRITER, 0, 0);

	if ( db == NULL ) {
		LLOG (log_dsap, LLOG_EXCEPTIONS, 
		    ("turbo: gdbm_open failed gdbm_errno %d", gdbm_errno));
		return (NULL);
	}

	return(db);
}

static turbo_write_entry(e, db)
Entry		e;
GDBM_FILE	db;
{
	static char	kbuf[512];
	static char	*buf = NULLCP;
	int		rc;
	PS		ps;
	datum		rdn;
	datum		ent;

	LLOG (log_dsap, LLOG_TRACE,("turbo: write_entry"));

	if (buf == NULLCP)
		buf = smalloc (10000);

	/* allocate the string presentation stream to print to */
	if ( (ps = ps_alloc(str_open)) == NULLPS ) {
		LLOG( log_dsap, LLOG_EXCEPTIONS, ("turbo: ps_alloc failed") );
		return(NOTOK);
	}
	if ( str_setup(ps, buf, 10000, 0) == NOTOK ) {
		LLOG( log_dsap, LLOG_EXCEPTIONS, ("turbo: str_setup failed") );
		ps_free(ps);
		return(NOTOK);
	}
	*ps->ps_ptr = 0;

	parse_rdn = e->e_name;
	rdn_print(ps, e->e_name, EDBOUT);
	*ps->ps_ptr = '\0';
	strcpy(kbuf, ps->ps_base);

	rdn.dptr = kbuf;
	rdn.dsize = strlen(rdn.dptr) + 1;

	ps_print(ps, "\n");
	as_print(ps, e->e_attributes, EDBOUT);
	ps_print(ps, "\n");
	*ps->ps_ptr = '\0';

	ent.dptr = ps->ps_base;
	ent.dsize = strlen(ent.dptr) + 1;

	if ( (rc = gdbm_store(db, rdn, ent, GDBM_REPLACE)) != 0 ) {
		LLOG (log_dsap, LLOG_EXCEPTIONS,
		    ("turbo: gdbm_store %d, gdbm_errno %d", rc, gdbm_errno));
		ps_free(ps);
		return(NOTOK);
	}

	ps_free(ps);
	return(OK);
}

/*
 * turbo_writeall -- write the entries in tree e to the proper edb
 * dbm file. the file is opened by turbo_open, then the tree is traversed,
 * via avl_apply, calling turbo_write_entry to write each entry
 */

turbo_writeall(e)
Entry	e;
{
	GDBM_FILE	db, turbo_open();
	DN		dn;
	char		*filename;
	int		save_heap;
	Entry		akid;

	LLOG (log_dsap, LLOG_TRACE, ("turbo: writeall"));

	save_heap = mem_heap;
	GENERAL_HEAP;

	if ((db = turbo_open(e, 1)) == NULL) {
		mem_heap = save_heap;
		return(NOTOK);
	}

	akid = (Entry) avl_getone(e->e_children);
	if (turbo_write_header(db, e, akid ? akid->e_data : e->e_data) != OK) {
		(void) gdbm_close(db);
		mem_heap = save_heap;
		return(NOTOK);
	}

	if (avl_apply(e->e_children, turbo_write_entry, db, NOTOK,
	    AVL_PREORDER) != AVL_NOMORE) {
		(void) gdbm_close(db);
		mem_heap = save_heap;
		return(NOTOK);
	}

	(void) gdbm_close(db);
	mem_heap = save_heap;
	return(OK);
}

/*
 * turbo_write -- write the single entry pointed to by e to the proper
 * edb dbm file.  The edb dbm file is opened by turbo_open, then a new
 * header is written by turbo_write_header, and finally the entry is 
 * written with a call to turbo_write_entry.
 */

turbo_write(e)
Entry	e;
{
	GDBM_FILE	db, turbo_open();
	int		save_heap;

	LLOG (log_dsap, LLOG_TRACE, ("turbo: write"));

	save_heap = mem_heap;
	GENERAL_HEAP;

	if ( (db = turbo_open(e->e_parent, 0)) == NULL ) {
		mem_heap = save_heap;
		return(NOTOK);
	}

	if ( turbo_write_header(db, e->e_parent, e->e_data) != OK ) {
		(void) gdbm_close(db);
		mem_heap = save_heap;
		return(NOTOK);
	}

	if ( turbo_write_entry(e, db) != OK ) {
		(void) gdbm_close(db);
		mem_heap = save_heap;
		return(NOTOK);
	}

	(void) gdbm_close(db);
	mem_heap = save_heap;
	return(OK);
}

/*
 * turbo_delete -- delete the entry pointed to by p from the proper
 * edb dbm file.
 */

turbo_delete(e)
Entry	e;
{
	static char	deletekey[256];
	int		rc;
	GDBM_FILE	db, turbo_open();
	PS		ps;
	datum		key;
	int		save_heap;

	LLOG (log_dsap, LLOG_TRACE,("turbo: delete"));

	save_heap = mem_heap;
	GENERAL_HEAP;

	if ( (db = turbo_open(e->e_parent, 0)) == NULL ) {
		mem_heap = save_heap;
		return(NOTOK);
	}

	if ( turbo_write_header(db, e->e_parent, e->e_data) != OK ) {
		(void) gdbm_close(db);
		mem_heap = save_heap;
		return(NOTOK);
	}

	/* allocate the string presentation stream to print the key to */
	if ( (ps = ps_alloc(str_open)) == NULLPS ) {
		mem_heap = save_heap;
		return(NOTOK);
	}
	if ( str_setup(ps, deletekey, sizeof(deletekey), 0) == NOTOK ) {
		ps_free(ps);
		mem_heap = save_heap;
		return(NOTOK);
	}
	*ps->ps_ptr = 0;

	rdn_print(ps, e->e_name, EDBOUT);
	*ps->ps_ptr = '\0';
	key.dptr = ps->ps_base;
	key.dsize = strlen(key.dptr) + 1;

	if ( (rc = gdbm_delete(db, key)) != 0 ) {
		LLOG (log_dsap, LLOG_EXCEPTIONS,
		    ("turbo: gdbm_delete %d gdbm_errno %d", rc, gdbm_errno));
		ps_free(ps);
		(void) gdbm_close(db);
		mem_heap = save_heap;
		return(NOTOK);
	}

	ps_free(ps);
	(void) gdbm_close(db);
	mem_heap = save_heap;
	return(OK);
}

/*
 * turbo_write_header -- write a new header for the edb dbm file db.
 * The version is taken from e's parent version
 */

turbo_write_header(db, parent, datatype)
GDBM_FILE	db;
Entry		parent;
{
	static char	hbuf[256];
	int		rc;
	char		*type;
	char		*version, *new_version();
	datum		newheader;
	int		save_heap;

	LLOG (log_dsap, LLOG_TRACE, ("turbo: write_header"));

	save_heap = mem_heap;
	GENERAL_HEAP;

	switch (datatype) {
	case E_DATA_MASTER:
		type = "MASTER";
		break;
	case E_TYPE_SLAVE :
		type = "SLAVE";
		break;
	default:
		type = "CACHE";
		break;
	}

	if (parent != NULLENTRY)
		version = parent->e_edbversion;
	else
		version = new_version();

	(void) sprintf(hbuf, "%s\n%s\n", type, version);

	newheader.dptr = hbuf;
	newheader.dsize = strlen(newheader.dptr) + 1;

	if ((rc = gdbm_store(db, turbo_header_key, newheader, GDBM_REPLACE))
	    != 0) {
		LLOG (log_dsap, LLOG_EXCEPTIONS,
		    ("turbo: gdbm_store %d gdbm_errno %d", rc, gdbm_errno));
		mem_heap = save_heap;
		return(NOTOK);
	}
	mem_heap = save_heap;
	return(OK);
}

#else

turbo_delete_dummy (){}
#endif