Exemplo n.º 1
0
/*
 * Save the in-memory database mdb to the disk database dbname.
 * Return 0 if OK, -1 on error.
 */
int
db_copy_out(DB *mdb, const char *dbname, const char *uname, BTREEINFO *bti)
{
	DB *ddb;
	DBT key, data;
	int error, rv, version;

	if ((ddb = dbopen(dbname, O_RDWR|O_CREAT|O_TRUNC, 0644,
	    DB_BTREE, bti)) == NULL) {
		warn("creating %s summary", uname);
		return (-1);
	}

	error = 0;

	for (rv = DB_SEQ(mdb, &key, &data, R_FIRST);
	    rv == 0; rv = DB_SEQ(mdb, &key, &data, R_NEXT)) {
		if ((rv = DB_PUT(ddb, &key, &data, 0)) < 0) {
			warn("saving %s summary", uname);
			error = -1;
			goto out;
		}
	}
	if (rv < 0) {
		warn("retrieving %s stats", uname);
		error = -1;
	}

out:
	/* Add a version record. */
	key.data = (void*)&VERSION_KEY;
	key.size = sizeof(VERSION_KEY);
	version = 2;
	data.data = &version;
	data.size = sizeof(version);
	if ((rv = DB_PUT(ddb, &key, &data, 0)) < 0) {
		warn("add version record to %s stats", uname);
		error = -1;
	} else if (rv == 1) {
		warnx("duplicate version record in %s stats", uname);
		error = -1;
	}

	if (DB_SYNC(ddb, 0) < 0) {
		warn("syncing %s summary", uname);
		error = -1;
	}
	if (DB_CLOSE(ddb) < 0) {
		warn("closing %s summary", uname);
		error = -1;
	}
	return error;
}
Exemplo n.º 2
0
int
usracct_update(void)
{
	DB *saved_usracct_db;
	DBT key, data;
	BTREEINFO bti;
	int error, serr, nerr;

	memset(&bti, 0, sizeof(bti));
	bti.compare = uid_compare;

	saved_usracct_db = dbopen(_PATH_USRACCT, O_RDWR|O_CREAT|O_TRUNC, 0644,
	    DB_BTREE, &bti);
	if (saved_usracct_db == NULL) {
		warn("creating user accounting summary");
		return (-1);
	}

	error = 0;

	serr = DB_SEQ(usracct_db, &key, &data, R_FIRST);
	if (serr < 0) {
		warn("retrieving user accounting stats");
		error = -1;
	}
	while (serr == 0) {
		nerr = DB_PUT(saved_usracct_db, &key, &data, 0);
		if (nerr < 0) {
			warn("saving user accounting summary");
			error = -1;
			break;
		}

		serr = DB_SEQ(usracct_db, &key, &data, R_NEXT);
		if (serr < 0) {
			warn("retrieving user accounting stats");
			error = -1;
			break;
		}
	}

	if (DB_SYNC(saved_usracct_db, 0) < 0) {
		warn("syncing process accounting summary");
		error = -1;
	}
	if (DB_CLOSE(saved_usracct_db) < 0) {
		warn("closing process accounting summary");
		error = -1;
	}
	return error;
}
Exemplo n.º 3
0
int
cache_sync(void)
{
	int	x;
	Cache	*cp;

	cs_syncs++;

	if(!cache_initted)
		return(1);

	for(x = 0; x < cwidth; x++) {
		for(cp = sys_c[x].ahead; cp != (Cache *)0; cp = cp->nxt) {
			if(cp->flg & C_DIRTY) {
#ifdef	CACHE_DEBUG
				printf("sync #%d\n",cp->oid);
#endif
				if(DB_PUT(cp->op,cp->oid))
					return(1);
				cs_dbwrites++;
				cp->flg &= ~C_DIRTY;
			}
		}
		for(cp = sys_c[x].ohead; cp != (Cache *)0; cp = cp->nxt) {
			if(cp->flg & C_DIRTY) {
#ifdef	CACHE_DEBUG
				printf("sync #%d\n",cp->oid);
#endif
				if(DB_PUT(cp->op,cp->oid))
					return(1);
				cs_dbwrites++;
				cp->flg &= ~C_DIRTY;
			}
		}
	}
	return(0);
}
Exemplo n.º 4
0
int
usracct_add(const struct cmdinfo *ci)
{
	DBT key, data;
	struct userinfo newui;
	uid_t uid;
	int rv;

	uid = ci->ci_uid;
	key.data = &uid;
	key.size = sizeof uid;

	rv = DB_GET(usracct_db, &key, &data, 0);
	if (rv < 0) {
		warn("get key %u from user accounting stats", uid);
		return (-1);
	} else if (rv == 0) {	/* it's there; copy whole thing */
		/* add the old data to the new data */
		bcopy(data.data, &newui, data.size);
		if (newui.ui_uid != uid) {
			warnx("key %u != expected record number %u",
			    newui.ui_uid, uid);
			warnx("inconsistent user accounting stats");
			return (-1);
		}
	} else {		/* it's not there; zero it and copy the key */
		bzero(&newui, sizeof newui);
		newui.ui_uid = ci->ci_uid;
	}

	newui.ui_calls += ci->ci_calls;
	newui.ui_utime += ci->ci_utime;
	newui.ui_stime += ci->ci_stime;
	newui.ui_mem += ci->ci_mem;
	newui.ui_io += ci->ci_io;

	data.data = &newui;
	data.size = sizeof newui;
	rv = DB_PUT(usracct_db, &key, &data, 0);
	if (rv < 0) {
		warn("add key %u to user accounting stats", uid);
		return (-1);
	} else if (rv != 0) {
		warnx("DB_PUT returned 1");
		return (-1);
	}

	return (0);
}
Exemplo n.º 5
0
/*
 * Create the in-memory database, *mdb.
 * If iflag is not set, fill-in mdb with the records of the disk-based
 * database dbname.
 * Upgrade old-version records by calling v1_to_v2.
 * Return 0 if OK, -1 on error.
 */
int
db_copy_in(DB **mdb, const char *dbname, const char *uname, BTREEINFO *bti,
    int (*v1_to_v2)(DBT *key, DBT *data))
{
	DBT key, data;
	DB *ddb;
	int error, rv, version;

	if ((*mdb = dbopen(NULL, O_RDWR, 0, DB_BTREE, bti)) == NULL)
		return (-1);

	if (iflag)
		return (0);

	if ((ddb = dbopen(dbname, O_RDONLY, 0, DB_BTREE, bti)) == NULL) {
		if (errno == ENOENT)
			return (0);
		warn("retrieving %s summary", uname);
		db_destroy(*mdb, uname);
		return (-1);
	}

	error = 0;

	/* Obtain/set version. */
	version = 1;
	key.data = (void*)&VERSION_KEY;
	key.size = sizeof(VERSION_KEY);

	rv = DB_GET(ddb, &key, &data, 0);
	if (rv < 0) {
		warn("get version key from %s stats", uname);
		error = -1;
		goto closeout;
	} else if (rv == 0) {	/* It's there; verify version. */
		if (data.size != sizeof(version)) {
			warnx("invalid version size %zd in %s",
			    data.size, uname);
			error = -1;
			goto closeout;
		}
		memcpy(&version, data.data, data.size);
		if (version != 2) {
			warnx("unsupported version %d in %s",
			    version, uname);
			error = -1;
			goto closeout;
		}
	}

	for (rv = DB_SEQ(ddb, &key, &data, R_FIRST); rv == 0;
	    rv = DB_SEQ(ddb, &key, &data, R_NEXT)) {

		/* See if this is a version record. */
		if (key.size == sizeof(VERSION_KEY) &&
		    memcmp(key.data, VERSION_KEY, sizeof(VERSION_KEY)) == 0)
			continue;

		/* Convert record from v1, if needed. */
		if (version == 1 && v1_to_v2(&key, &data) < 0) {
			warn("converting %s stats", uname);
			error = -1;
			goto closeout;
		}

		/* Copy record to the in-memory database. */
		if ((rv = DB_PUT(*mdb, &key, &data, 0)) < 0) {
			warn("initializing %s stats", uname);
			error = -1;
			goto closeout;
		}
	}
	if (rv < 0) {
		warn("retrieving %s summary", uname);
		error = -1;
	}

closeout:
	if (DB_CLOSE(ddb) < 0) {
		warn("closing %s summary", uname);
		error = -1;
	}

	if (error)
		db_destroy(*mdb, uname);
	return (error);
}
Exemplo n.º 6
0
/*
put an object back into the cache. this is complicated by the
fact that when a function calls this with an object, the object
is *already* in the cache, since calling functions operate on
pointers to the cached objects, and may or may not be actively
modifying them. in other words, by the time the object is handed
to cache_put, it has probably already been modified, and the cached
version probably already reflects those modifications!

so - we do a couple of things: we make sure that the cached
object is actually there, and set its dirty bit. if we can't
find it - either we have a (major) programming error, or the
*name* of the object has been changed, or the object is a totally
new creation someone made and is inserting into the world.

in the case of totally new creations, we simply accept the pointer
to the object and add it into our environment. freeing it becomes
the responsibility of the cache code. DO NOT HAND A POINTER TO
CACHE_PUT AND THEN FREE IT YOURSELF!!!!

There are other sticky issues about changing the object pointers
of MUDs and their names. This is left as an exercise for the
reader.
*/
int
cache_put(Object *obj, int oid)
{
	Cache	*cp;
	int	hv = 0;
	static const char	*nmmesg = "cache_put: cannot allocate memory ";

	/* firewall */
	if(obj == (Object *)0 || oid < 0 || !cache_initted) {
#ifdef	CACHE_VERBOSE
		writelog();
		fprintf(stderr, "cache_put:  NULL object/id - programmer error\n");
#endif
		return(1);
	}

	cs_writes++;

	/* generate hash */
	hv = objid_hash(oid,cwidth);

	/* step one, search active chain, and if we find the obj, dirty it */
	for(cp = sys_c[hv].ahead; cp != (Cache *)0; cp = cp->nxt) {
		if(cp->oid == oid) {

			/* already dirty? */
			if(cp->flg & C_DIRTY)
				cs_whits++;

			if (cp->flg & C_DEAD) {
			    fprintf(stderr, "found dead on active chain, 0x%08lx 0x%08lx\n", (long) cp->op, (long) obj);
			}
			/* OWIE! - bait & switch */
			if(obj != cp->op) {
#ifdef	CACHE_DEBUG
				printf("cache_put bait&switch #%d 0x%08lx\n",cp->oid,(long) cp->op);
#endif
				if(cp->op != (Object *)0)
					free_object(cp->op);
				cp->op = obj;
			}

#ifdef	CACHE_DEBUG
			printf("cache_put #%d %d\n",cp->oid,cp->op);
#endif
			cp->flg |= C_DIRTY;
			return(0);
		}
	}

	/* step two, search in-active chain */
	for(cp = sys_c[hv].ohead; cp != (Cache *)0; cp = cp->nxt) {
		if(cp->oid == oid) {

			/* already dirty? */
			if(cp->flg & C_DIRTY)
				cs_whits++;

			/* OWIE! - bait & switch */
			if(obj != cp->op) {
#ifdef	CACHE_DEBUG
				printf("cache_put bait&switch #%d %d\n",cp->oid,cp->op);
#endif
				if(cp->op != (Object *)0)
					free_object(cp->op);
				cp->op = obj;
			}

#ifdef	CACHE_DEBUG
			printf("cache_put #%d %d\n",cp->oid,cp->op);
#endif
			cp->flg |= C_DIRTY;
			return(0);
		}
	}

	/* a totally new object. make a slot in the cache for it. */
	if((cp = sys_c[hv].otail) == (Cache *)0) {

		/* no room on the chain!! chain must grow! */
		if((cp = (Cache *)malloc(sizeof(Cache))) == (Cache *)0)
			panic(nmmesg);
		cp->oid = -1;
		cp->op = (Object *)0;
		cs_objects++;
	} else {

		/* there is a dirty object still in memory? write. */
		if((cp->flg & C_DIRTY) && cp->oid >= 0 && cp->op != (Object *)0) {

#ifdef	CACHE_DEBUG
			printf("cache_put #%d clean-out %d\n",cp->oid,cp->op);
#endif
			/* if this fails we are a hurting puppy. */
			if(DB_PUT(cp->op,cp->oid))
				return(1);
			cs_dbwrites++;
		}

		/* unlink from inactive chain */
		if(cp->prv != (Cache *)0) {
			sys_c[hv].otail = cp->prv;
			cp->prv->nxt = cp->nxt;
		} else {
			sys_c[hv].ohead = sys_c[hv].otail = (Cache *)0;
		}
	}


	/* point it at the new object */
	if(cp->op != (Object *)0)
		free_object(cp->op);
	cp->op = obj;

	cp->oid = oid;

	/* mark new dodad as dirty */
	cp->flg = C_NOFLG | C_DIRTY;


	/* link at head of active chain */
	cp->nxt = sys_c[hv].ahead;
	if(sys_c[hv].ahead == (Cache *)0)
		sys_c[hv].atail = cp;
	cp->prv = (Cache *)0;
	if(cp->nxt != (Cache *)0)
		cp->nxt->prv = cp;
	sys_c[hv].ahead = cp;


#ifdef	CACHE_DEBUG
	printf("cache_put #%d new in cache %d\n",cp->oid,cp->op);
#endif

	/* e finito ! */
	return(0);
}
Exemplo n.º 7
0
/*
search the cache for an object, and if it is not found, thaw it.
this code is probably a little bigger than it needs be because I
had fun and unrolled all the pointer juggling inline.
*/
Object	*
cache_get(int oid)
{
	Cache		*cp;
	int		hv = 0;
	Object		*ret;
	static const char	*nmmesg = "cache_get:  cannot allocate memory";

	/* firewall */
	if(!cache_initted) {
#ifdef	CACHE_VERBOSE
		writelog();
		fprintf(stderr, "cache_get:  cache not initted\n");
#endif
		return((Object *)0);
	}

#ifdef	CACHE_DEBUG
	printf("get #%d\n",oid);
#endif

	if (oid < 0) 
	    return((Object *)0);
	cs_reads++;

	hv = objid_hash(oid,cwidth);

	/* search active chain first */
	for(cp = sys_c[hv].ahead; cp != (Cache *)0; cp = cp->nxt) {
		if(!(cp->flg & C_DEAD) && cp->oid == oid) {
			cs_rhits++;
			cs_ahits++;
#ifdef	CACHE_DEBUG
			printf("return #%d active cache %d\n",cp->oid,cp->op);
#endif
			return(cp->op);
		}
	}

	/* search in-active chain second */
	for(cp = sys_c[hv].ohead; cp != (Cache *)0; cp = cp->nxt) {
		if(!(cp->flg & C_DEAD) && cp->oid == oid) {

			/* dechain from in-active chain */
			if(cp->nxt == (Cache *)0)
				sys_c[hv].otail = cp->prv;
			else
				cp->nxt->prv = cp->prv;
			if(cp->prv == (Cache *)0)
				sys_c[hv].ohead = cp->nxt;
			else
				cp->prv->nxt = cp->nxt;

			/* insert at head of active chain */
			cp->nxt = sys_c[hv].ahead;
			if(sys_c[hv].ahead == (Cache *)0)
				sys_c[hv].atail = cp;
			cp->prv = (Cache *)0;
			if(cp->nxt != (Cache *)0)
				cp->nxt->prv = cp;
			sys_c[hv].ahead = cp;

			/* done */
			cs_rhits++;
#ifdef	CACHE_DEBUG
			printf("return #%d old cache %d\n",cp->oid,cp->op);
#endif
			return(cp->op);
		}
	}

	/* DARN IT - at this point we have a certified, type-A cache miss */

	/* thaw the object from wherever. */
	if((ret = DB_GET(oid)) == (Object *)0) {
		cs_fails++;
#ifdef	CACHE_DEBUG
		printf("#%d not in db\n",oid);
#endif
		return((Object *)0);
	}
	cs_dbreads++;

	/* if there are no old cache object holders left, allocate one */
	if(sys_c[hv].otail == (Cache *)0) {

		if((cp = (Cache *)malloc(sizeof(Cache))) == (Cache *)0)
			panic(nmmesg);
		cp->oid = oid;

		cp->flg = C_NOFLG;

		/* linkit at head of active chain */
		cp->nxt = sys_c[hv].ahead;
		if(sys_c[hv].ahead == (Cache *)0)
			sys_c[hv].atail = cp;
		cp->prv = (Cache *)0;
		if(cp->nxt != (Cache *)0)
			cp->nxt->prv = cp;
		sys_c[hv].ahead = cp;
		cs_objects++;
#ifdef	CACHE_DEBUG
		printf("return #%d loaded into cache %d\n",cp->oid,cp->op);
#endif
		return(cp->op = ret);
	}

	/* unlink old cache chain tail */
	cp = sys_c[hv].otail;
	if(cp->prv != (Cache *)0) {
		sys_c[hv].otail = cp->prv;
		cp->prv->nxt = cp->nxt;
	} else	/* took last one */
		sys_c[hv].ohead = sys_c[hv].otail = (Cache *)0;

	/* if there is a dirty object still in memory, write it */
	if((cp->flg & C_DIRTY) && cp->oid >= 0 && cp->op != (Object *)0) {
#ifdef	CACHE_DEBUG
		printf("clean #%d from cache %d\n",cp->oid,cp->op);
#endif
		if(DB_PUT(cp->op,cp->oid))
			return((Object *)0);
		cs_dbwrites++;
	}

	/* free object's data */
	if(cp->op != (Object *)0)
		free_object(cp->op);
	cp->op = ret;
	cp->oid = oid;
	cp->flg = C_NOFLG;

	/* relink at head of active chain */
	cp->nxt = sys_c[hv].ahead;
	if(sys_c[hv].ahead == (Cache *)0)
		sys_c[hv].atail = cp;
	cp->prv = (Cache *)0;
	if(cp->nxt != (Cache *)0)
		cp->nxt->prv = cp;
	sys_c[hv].ahead = cp;

#ifdef	CACHE_DEBUG
	printf("return #%d loaded into cache %d\n",cp->oid,cp->op);
#endif
	return(ret);
}
Exemplo n.º 8
0
int
usracct_init(void)
{
	DB *saved_usracct_db;
	BTREEINFO bti;
	int error;
	int ndups = 0;

	memset(&bti, 0, sizeof(bti));
	bti.compare = uid_compare;

	usracct_db = dbopen(NULL, O_RDWR|O_CREAT|O_TRUNC, 0644, DB_BTREE, &bti);
	if (usracct_db == NULL)
		return (-1);

	error = 0;
	if (!iflag) {
		DBT key, data;
		int serr, nerr;

		saved_usracct_db = dbopen(_PATH_USRACCT, O_RDONLY, 0, DB_BTREE,
		    &bti);
		if (saved_usracct_db == NULL) {
			error = (errno == ENOENT) ? 0 : -1;
			if (error)
				warn("retrieving user accounting summary");
			goto out;
		}

		serr = DB_SEQ(saved_usracct_db, &key, &data, R_FIRST);
		if (serr < 0) {
			warn("retrieving user accounting summary");
			error = -1;
			goto closeout;
		}
		while (serr == 0) {
			nerr = DB_PUT(usracct_db, &key, &data, R_NOOVERWRITE);
			if (nerr < 0) {
				warn("initializing user accounting stats");
				error = -1;
				break;
			} 
			if (nerr == 1) {
				warnx("duplicate key in `%s': %s",
				    _PATH_USRACCT, fmt(&key));
				if (ndups++ == 5) {
					warnx("too many duplicate keys;"
					    " `%s' possibly corrupted.",
					    _PATH_USRACCT);
					error = -1;
					break;
				}
			}

			serr = DB_SEQ(saved_usracct_db, &key, &data, R_NEXT);
			if (serr < 0) {
				warn("retrieving user accounting summary");
				error = -1;
				break;
			}
		}

closeout:
		if (DB_CLOSE(saved_usracct_db) < 0) {
			warn("closing user accounting summary");
			error = -1;
		}
	}

out:
	if (error != 0)
		usracct_destroy();
	return (error);
}