mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
database: add gdbm backend
This commit is contained in:
parent
c69ed91239
commit
46bceedc98
1 changed files with 246 additions and 0 deletions
246
src/pulsecore/database-gdbm.c
Normal file
246
src/pulsecore/database-gdbm.c
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2009 Lennart Poettering
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <gdbm.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/log.h>
|
||||
|
||||
#include "database.h"
|
||||
|
||||
#define MAKE_GDBM_FILE(x) ((GDBM_FILE) (x))
|
||||
|
||||
static inline datum* datum_to_gdbm(datum *to, const pa_datum *from) {
|
||||
pa_assert(from);
|
||||
pa_assert(to);
|
||||
|
||||
to->dptr = from->data;
|
||||
to->dsize = from->size;
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
static inline pa_datum* datum_from_gdbm(pa_datum *to, const datum *from) {
|
||||
pa_assert(from);
|
||||
pa_assert(to);
|
||||
|
||||
to->data = from->dptr;
|
||||
to->size = from->dsize;
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
void pa_datum_free(pa_datum *d) {
|
||||
pa_assert(d);
|
||||
|
||||
free(d->data); /* gdbm uses raw malloc/free hence we should do that here, too */
|
||||
pa_zero(d);
|
||||
}
|
||||
|
||||
pa_database* pa_database_open(const char *fn, pa_bool_t for_write) {
|
||||
GDBM_FILE f;
|
||||
int gdbm_cache_size;
|
||||
char *path;
|
||||
|
||||
pa_assert(fn);
|
||||
|
||||
/* We include the host identifier in the file name because gdbm
|
||||
* files are CPU dependant, and we don't want things to go wrong
|
||||
* if we are on a multiarch system. */
|
||||
|
||||
path = pa_sprintf_malloc("%s."CANONICAL_HOST".gdbm", fn);
|
||||
errno = 0;
|
||||
f = gdbm_open((char*) path, 0, GDBM_NOLOCK | (for_write ? GDBM_WRCREAT : GDBM_READER), 0644, NULL);
|
||||
|
||||
if (f)
|
||||
pa_log_debug("Opened GDBM database '%s'", path);
|
||||
|
||||
pa_xfree(path);
|
||||
|
||||
if (!f) {
|
||||
if (errno == 0)
|
||||
errno = EIO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* By default the cache of gdbm is rather large, let's reduce it a bit to save memory */
|
||||
gdbm_cache_size = 10;
|
||||
gdbm_setopt(f, GDBM_CACHESIZE, &gdbm_cache_size, sizeof(gdbm_cache_size));
|
||||
|
||||
return (pa_database*) f;
|
||||
}
|
||||
|
||||
void pa_database_close(pa_database *db) {
|
||||
pa_assert(db);
|
||||
|
||||
gdbm_close(MAKE_GDBM_FILE(db));
|
||||
}
|
||||
|
||||
pa_datum* pa_database_get(pa_database *db, const pa_datum *key, pa_datum* data) {
|
||||
datum gdbm_key, gdbm_data;
|
||||
|
||||
pa_assert(db);
|
||||
pa_assert(key);
|
||||
pa_assert(data);
|
||||
|
||||
gdbm_data = gdbm_fetch(MAKE_GDBM_FILE(db), *datum_to_gdbm(&gdbm_key, key));
|
||||
|
||||
return gdbm_data.dptr ?
|
||||
datum_from_gdbm(data, &gdbm_data) :
|
||||
NULL;
|
||||
}
|
||||
|
||||
int pa_database_set(pa_database *db, const pa_datum *key, const pa_datum* data, pa_bool_t overwrite) {
|
||||
datum gdbm_key, gdbm_data;
|
||||
|
||||
pa_assert(db);
|
||||
pa_assert(key);
|
||||
pa_assert(data);
|
||||
|
||||
return gdbm_store(MAKE_GDBM_FILE(db),
|
||||
*datum_to_gdbm(&gdbm_key, key),
|
||||
*datum_to_gdbm(&gdbm_data, data),
|
||||
overwrite ? GDBM_REPLACE : GDBM_INSERT) != 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
int pa_database_unset(pa_database *db, const pa_datum *key) {
|
||||
datum gdbm_key;
|
||||
|
||||
pa_assert(db);
|
||||
pa_assert(key);
|
||||
|
||||
return gdbm_delete(MAKE_GDBM_FILE(db), *datum_to_gdbm(&gdbm_key, key)) != 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
int pa_database_clear(pa_database *db) {
|
||||
datum gdbm_key;
|
||||
|
||||
pa_assert(db);
|
||||
|
||||
gdbm_key = gdbm_firstkey(MAKE_GDBM_FILE(db));
|
||||
|
||||
while (gdbm_key.dptr) {
|
||||
datum next;
|
||||
|
||||
next = gdbm_nextkey(MAKE_GDBM_FILE(db), gdbm_key);
|
||||
|
||||
gdbm_delete(MAKE_GDBM_FILE(db), gdbm_key);
|
||||
|
||||
free(gdbm_key.dptr);
|
||||
gdbm_key = next;
|
||||
}
|
||||
|
||||
return gdbm_reorganize(MAKE_GDBM_FILE(db)) == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
signed pa_database_size(pa_database *db) {
|
||||
datum gdbm_key;
|
||||
unsigned n = 0;
|
||||
|
||||
pa_assert(db);
|
||||
|
||||
/* This sucks */
|
||||
|
||||
gdbm_key = gdbm_firstkey(MAKE_GDBM_FILE(db));
|
||||
|
||||
while (gdbm_key.dptr) {
|
||||
datum next;
|
||||
|
||||
n++;
|
||||
|
||||
next = gdbm_nextkey(MAKE_GDBM_FILE(db), gdbm_key);
|
||||
free(gdbm_key.dptr);
|
||||
gdbm_key = next;
|
||||
}
|
||||
|
||||
return (signed) n;
|
||||
}
|
||||
|
||||
pa_datum* pa_database_first(pa_database *db, pa_datum *key, pa_datum *data) {
|
||||
datum gdbm_key, gdbm_data;
|
||||
|
||||
pa_assert(db);
|
||||
pa_assert(key);
|
||||
|
||||
gdbm_key = gdbm_firstkey(MAKE_GDBM_FILE(db));
|
||||
|
||||
if (!gdbm_key.dptr)
|
||||
return NULL;
|
||||
|
||||
if (data) {
|
||||
gdbm_data = gdbm_fetch(MAKE_GDBM_FILE(db), gdbm_key);
|
||||
|
||||
if (!gdbm_data.dptr) {
|
||||
free(gdbm_key.dptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
datum_from_gdbm(data, &gdbm_data);
|
||||
}
|
||||
|
||||
datum_from_gdbm(key, &gdbm_key);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
pa_datum* pa_database_next(pa_database *db, const pa_datum *key, pa_datum *next, pa_datum *data) {
|
||||
datum gdbm_key, gdbm_data;
|
||||
|
||||
pa_assert(db);
|
||||
pa_assert(key);
|
||||
pa_assert(next);
|
||||
|
||||
if (!key)
|
||||
return pa_database_first(db, next, data);
|
||||
|
||||
gdbm_key = gdbm_nextkey(MAKE_GDBM_FILE(db), *datum_to_gdbm(&gdbm_key, key));
|
||||
|
||||
if (!gdbm_key.dptr)
|
||||
return NULL;
|
||||
|
||||
if (data) {
|
||||
gdbm_data = gdbm_fetch(MAKE_GDBM_FILE(db), gdbm_key);
|
||||
|
||||
if (!gdbm_data.dptr) {
|
||||
free(gdbm_key.dptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
datum_from_gdbm(data, &gdbm_data);
|
||||
}
|
||||
|
||||
datum_from_gdbm(next, &gdbm_key);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
int pa_database_sync(pa_database *db) {
|
||||
pa_assert(db);
|
||||
|
||||
gdbm_sync(MAKE_GDBM_FILE(db));
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue