Beispiel #1
0
/**
 * Is value data of a given old size replaceable in situ with new data?
 */
bool
replaceable(size_t old_size, size_t new_size, bool big)
{
#ifdef BIGDATA
	size_t ol = big ? bigval_length(old_size) : old_size;
	size_t nl = big ? bigval_length(new_size) : new_size;

	return ol == nl;
#else	/* !BIGDATA */
	(void) big;
	return old_size == new_size;
#endif	/* BIGDATA */
}
Beispiel #2
0
/**
 * Put large value data into the .dat and fill in the supplied .pag buffer
 * with the block numbers where the value is stored and other size information.
 *
 * @param db		the sdbm database
 * @param bval		start of big value in the page
 * @param blen		length of big value in the page
 * @param val		start of value data
 * @param vlen		length of value
 *
 * @return TRUE if value was written successfully in the .dat file.
 */
gboolean
bigval_put(DBM *db, char *bval, size_t blen, const char *val, size_t vlen)
{
	g_assert(bigval_length(vlen) == blen);

	if (!big_file_alloc(db, bigval_blocks(bval), bigblocks(vlen)))
		return FALSE;

	/*
	 * Write the value header:
	 *
	 * value size
	 */

	poke_be32(bval, (guint32) vlen);

	/*
	 * And now the indirection block numbers of the value, pointing in .dat.
	 */

	if (0 != big_store(db, bigval_blocks(bval), val, vlen)) {
		big_file_free(db, bigval_blocks(bval), bigblocks(vlen));
		return FALSE;
	}

	return TRUE;
}
Beispiel #3
0
/**
 * Mark .dat blocks used to hold the value described in the .pag space as
 * being allocated in the bitmap checking array.
 *
 * @param db		the sdbm database
 * @param bval		start of big value in the page
 * @param blen		length of big value in the page
 */
void
bigval_mark_used(DBM *db, const char *bval, size_t blen)
{
	size_t len = big_length(bval);

	if (bigval_length(len) != blen) {
		g_carp("sdbm: \"%s\": %s: inconsistent value length %lu in .pag",
			sdbm_name(db), G_STRFUNC, (unsigned long) len);
		return;
	}

	big_file_mark_used(db, bigval_blocks(bval), bigblocks(len));
}
Beispiel #4
0
/**
 * Validate .dat blocks used to hold the value described in the .pag space.
 *
 * @param db		the sdbm database
 * @param bval		start of big value in the page
 * @param blen		length of big value in the page
 *
 * @return TRUE on success.
 */
gboolean
bigval_check(DBM *db, const char *bval, size_t blen)
{
	size_t len = big_length(bval);

	if (bigval_length(len) != blen) {
		g_warning("sdbm: \"%s\": found inconsistent value length %lu, "
			"would span %lu bytes in .pag instead of the %lu present",
			sdbm_name(db), (unsigned long) len,
			(unsigned long) bigkey_length(len), (unsigned long) blen);
		return FALSE;
	}

	return big_file_check("value", db, bigval_blocks(bval), bigblocks(len));
}
Beispiel #5
0
/**
 * Free .dat blocks used to hold the value described in the .pag space.
 *
 * @param db		the sdbm database
 * @param bval		start of big value in the page
 * @param blen		length of big value in the page
 *
 * @return TRUE on success.
 */
gboolean
bigval_free(DBM *db, const char *bval, size_t blen)
{
	size_t len = big_length(bval);

	if (bigval_length(len) != blen) {
		g_warning("sdbm: \"%s\": "
			"bigval_free: inconsistent key length %lu in .pag",
			sdbm_name(db), (unsigned long) len);
		return FALSE;
	}

	big_file_free(db, bigval_blocks(bval), bigblocks(len));
	return TRUE;
}
Beispiel #6
0
/**
 * Get value data from the block numbers held in the .pag value.
 *
 * @param db		the sdbm database
 * @param bval		start of big value in the page
 * @param blen		length of big value in the page
 *
 * @return pointer to read value (scratch buffer) if OK, NULL on error.
 */
char *
bigval_get(DBM *db, const char *bval, size_t blen)
{
	size_t len = big_length(bval);
	DBMBIG *dbg = db->big;

	if (bigval_length(len) != blen) {
		g_warning("sdbm: \"%s\": "
			"bigval_get: inconsistent value length %lu in .pag",
			sdbm_name(db), (unsigned long) len);
		return NULL;
	}

	if (-1 == big_fetch(db, bigval_blocks(bval), len))
		return NULL;

	return dbg->scratch;
}
Beispiel #7
0
bool
putpair(DBM *db, char *pag, datum key, datum val)
{
#ifdef BIGDATA
	/*
	 * Our strategy for using big values is the following: if the key+value
	 * won't fit in expanded form in the page, there's no question we have
	 * to use a big value and/or big key.
	 *
	 * If it would fit however but the size of key+value is >= DBM_PAIRMAX/2
	 * and the value will waste less than half the .dat page then we force a
	 * big value to be used.  The rationale is to avoid filling-up the page
	 * and ending up having to split it later on for the next hashing conflict.
	 *
	 * NOTE: any change to the logic below must also be reported to
	 * sdbm_storage_needs().
	 */

	if (
		key.dsize <= DBM_PAIRMAX && DBM_PAIRMAX - key.dsize >= val.dsize &&
		(
			key.dsize + val.dsize < DBM_PAIRMAX / 2 ||
			val.dsize < DBM_BBLKSIZ / 2
		)
	) {
		/* Expand both the key and the value in the page */
		putpair_ext(pag, key, FALSE, val, FALSE);
	} else {
		unsigned n;
		unsigned off;
		unsigned short *ino = (unsigned short *) pag;
		size_t vl;
		bool largeval;

		off = ((n = ino[0]) > 0) ? offset(ino[n]) : DBM_PBLKSIZ;

		/*
		 * Avoid large keys if possible since comparisons involve extra I/Os.
		 * Therefore try to see if we can get away with only storing the
		 * value as a large item.
		 */

		vl = bigval_length(val.dsize);

		/*
		 * Handle the key first.
		 */

		if (key.dsize > DBM_PAIRMAX || DBM_PAIRMAX - key.dsize < vl) {
			size_t kl = bigkey_length(key.dsize);
			/* Large key (and could use a large value as well) */
			off -= kl;
			if (!bigkey_put(db, pag + off, kl, key.dptr, key.dsize))
				return FALSE;
			ino[n + 1] = off | BIG_FLAG;
			largeval = val.dsize > DBM_PAIRMAX / 2 ||
				val.dsize > DBM_PAIRMAX - bigkey_length(key.dsize);
		} else {
			/* Regular inlined key, only the value will be held in .dat */
			off -= key.dsize;
			memcpy(pag + off, key.dptr, key.dsize);
			ino[n + 1] = off;
			largeval = TRUE;
		}

		/*
		 * Now the data.
		 */

		if (largeval) {
			off -= vl;
			if (!bigval_put(db, pag + off, vl, val.dptr, val.dsize))
				return FALSE;
			ino[n + 2] = off | BIG_FLAG;
		} else {
			off -= val.dsize;
			memcpy(pag + off, val.dptr, val.dsize);
			ino[n + 2] = off;
		}

		ino[0] += 2;	/* Stored 2 items: 1 key, 1 value */
	}
#else
	(void) db;
	putpair_ext(pag, key, FALSE, val, FALSE);
#endif	/* BIGDATA */

	return TRUE;
}