[comp.unix.programmer] NDBM and ME

guest@geech.ai.mit.edu (Guest Account) (05/10/91)

I read the manual on ndbm but I still have a question.  I want to
store structs and the structs have pointers to variable length
strings.  If I store the struct using the data.dptr how will the
pointers remain valid after closing the database file?  I don't really
care how I do it, I just want to be able to use some kind of database
management package on a struct like
	struct system_entry {
		char *system_name;
		char *telephone_number;
		char *login_name;
		char *password;
	}

I won't know how long the strings are at compile time.

---GOOFY

adrianho@barkley.berkeley.edu (Adrian J Ho) (05/11/91)

In article <GUEST.91May10124944@geech.ai.mit.edu> guest@geech.ai.mit.edu (Guest Account) writes:
>I read the manual on ndbm but I still have a question.  I want to
>store structs and the structs have pointers to variable length
>strings.  If I store the struct using the data.dptr how will the
>pointers remain valid after closing the database file?

They don't -- you're screwed once your program terminates.

>							I don't really
>care how I do it, I just want to be able to use some kind of database
>management package on a struct like
>	   struct system_entry {
>		   char *system_name;
>		   char *telephone_number;
>		   char *login_name;
>		   char *password;
>	   }

>I won't know how long the strings are at compile time.

You don't have to -- just malloc() a string that's the total size of
all 4 fields (plus 4 for their associated nulls), then use strcpy()
to concatenate all 4 fields into the new string (be careful of the
NULLs -- that's why I didn't say strcat()).

You now have a single string with all 4 fields that can be used in an
NDBM record.  I'll leave the reverse process for you to figure out.

Oh, and if you _must_ use a guest account for some reason, please
leave a non-guest email address in your message, so that others can
reply to you directly.

Good luck!

torek@elf.ee.lbl.gov (Chris Torek) (05/11/91)

In article <ADRIANHO.91May10173137@barkley.berkeley.edu>
adrianho@barkley.berkeley.edu (Adrian J Ho) writes:
[a bunch of correct stuff]
>You now have a single string with all 4 fields that can be used in an
>NDBM record.

Note that ndbm places a (fairly small) limit on the size of any
single <key+content> pair (4096 bytes, minus overhead; this comes
to 4090 bytes for a page with one pair [1 count + 2 offsets, all
shorts, consumes 6 bytes]).

In general, you hand ndbm a blob of bytes as a content and a
separate blob of bytes as a key.  Some arbitrary time later, you
hand ndbm a blob of bytes as a key and it gives you back a blob
of bytes as a content.  The returned content is *not* at the same
`place' as the original, and is probably not at the same alignment.
Thus, for instance,

	datum.dptr = (char *)&foo;
	datum.size = sizeof(int);
	err = store(key, datum);

is OK, but

	datum = fetch(key);
	if (datum.dptr == NULL) ... handle not found ...;
	if (datum.dsize != sizeof(int)) ... handle corrupted database ...;
	foo = *(int *)datum.dptr;

is not, because `datum.dptr' may not be correctly aligned.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

adrianho@barkley.berkeley.edu (Adrian J Ho) (05/11/91)

In article <13080@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) writes:

>Note that ndbm places a (fairly small) limit on the size of any
>single <key+content> pair (4096 bytes, minus overhead; this comes
>to 4090 bytes for a page with one pair [1 count + 2 offsets, all
>shorts, consumes 6 bytes]).

Oops, forgot about that.  I doubt that the original poster will have
trouble with that limit, given the struct s/he posted, but some people
have strange addresses.  8-)

Addendum to my original post: If you have large structs that you wish
to store using the method I outlined, you'd be well advised to grab a
copy of GNU dbm:

	prep.ai.mit.edu:/pub/gnu/gdbm-1.5.tar.Z [18.71.0.38]

The record size in gdbm is theoretically unlimited.

As for the alignment problem, that's why I always do a bcopy() for
numeric data.

-----------------------------------------------------------------------------
Adrian Ho, EECS (pronounced "eeks!") Dept.		Phone: (415) 642-5563
UC Berkeley					adrianho@barkley.berkeley.edu

torek@elf.ee.lbl.gov (Chris Torek) (05/15/91)

In article <ADRIANHO.91May11011216@barkley.berkeley.edu>
adrianho@barkley.berkeley.edu (Adrian J Ho) writes:
[GNU dbm is available from]
>	prep.ai.mit.edu:/pub/gnu/gdbm-1.5.tar.Z [18.71.0.38]

I was going to let Oz or Margo post this, but neither one has yet, so:
Their database system is available from postgres.berkeley.edu as the
compressed tar file `bsd_db.tar.Z'.  This package compares quite well
versus gdbm in both space and time.  (There was some information
presented at the Winter 1991 Usenix in Dallas which does not appear
in the Proceedings.  I vaguely recall a factor of either 7 or 17
difference in performance.)
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov