lib: provide config API

This is a thin wrapper around the Xapian metadata API. The job of this
layer is to keep the config key value pairs from colliding with other
metadata by transparently prefixing the keys, along with the usual glue
to provide a C interface.

The split of _get_config into two functions is to allow returning of the
return value with different memory ownership semantics.
This commit is contained in:
David Bremner 2016-03-22 07:54:47 -03:00
parent 7e6e23c36e
commit 3458e3c89c
4 changed files with 166 additions and 0 deletions

View file

@ -49,6 +49,7 @@ libnotmuch_cxx_srcs = \
$(dir)/index.cc \
$(dir)/message.cc \
$(dir)/query.cc \
$(dir)/config.cc \
$(dir)/thread.cc
libnotmuch_modules := $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o)

87
lib/config.cc Normal file
View file

@ -0,0 +1,87 @@
/* config.cc - API for database metadata
*
* Copyright © 2016 David Bremner
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/ .
*
* Author: David Bremner <david@tethera.net>
*/
#include "notmuch.h"
#include "notmuch-private.h"
#include "database-private.h"
static const std::string CONFIG_PREFIX = "C";
notmuch_status_t
notmuch_database_set_config (notmuch_database_t *notmuch,
const char *key,
const char *value)
{
notmuch_status_t status;
Xapian::WritableDatabase *db;
status = _notmuch_database_ensure_writable (notmuch);
if (status)
return status;
try {
db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
db->set_metadata (CONFIG_PREFIX + key, value);
} catch (const Xapian::Error &error) {
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
notmuch->exception_reported = TRUE;
_notmuch_database_log (notmuch, "Error: A Xapian exception occurred setting metadata: %s\n",
error.get_msg().c_str());
}
return NOTMUCH_STATUS_SUCCESS;
}
static notmuch_status_t
_metadata_value (notmuch_database_t *notmuch,
const char *key,
std::string &value)
{
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
try {
value = notmuch->xapian_db->get_metadata (CONFIG_PREFIX + key);
} catch (const Xapian::Error &error) {
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
notmuch->exception_reported = TRUE;
_notmuch_database_log (notmuch, "Error: A Xapian exception occurred getting metadata: %s\n",
error.get_msg().c_str());
}
return status;
}
notmuch_status_t
notmuch_database_get_config (notmuch_database_t *notmuch,
const char *key,
char **value)
{
std::string strval;
notmuch_status_t status;
if (! value)
return NOTMUCH_STATUS_NULL_POINTER;
status = _metadata_value (notmuch, key, strval);
if (status)
return status;
*value = strdup (strval.c_str ());
return NOTMUCH_STATUS_SUCCESS;
}

View file

@ -1838,6 +1838,26 @@ notmuch_filenames_move_to_next (notmuch_filenames_t *filenames);
void
notmuch_filenames_destroy (notmuch_filenames_t *filenames);
/**
* set config 'key' to 'value'
*
*/
notmuch_status_t
notmuch_database_set_config (notmuch_database_t *db, const char *key, const char *value);
/**
* retrieve config item 'key', assign to 'value'
*
* keys which have not been previously set with n_d_set_config will
* return an empty string.
*
* return value is allocated by malloc and should be freed by the
* caller.
*/
notmuch_status_t
notmuch_database_get_config (notmuch_database_t *db, const char *key, char **value);
/**
* interrogate the library for compile time features
*/

58
test/T590-libconfig.sh Executable file
View file

@ -0,0 +1,58 @@
#!/usr/bin/env bash
test_description="library config API"
. ./test-lib.sh || exit 1
add_email_corpus
cat <<EOF > c_head
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <notmuch.h>
void run(int line, notmuch_status_t ret)
{
if (ret) {
fprintf (stderr, "line %d: %s\n", line, ret);
exit (1);
}
}
#define RUN(v) run(__LINE__, v);
int main (int argc, char** argv)
{
notmuch_database_t *db;
char *val;
notmuch_status_t stat;
RUN(notmuch_database_open (argv[1], NOTMUCH_DATABASE_MODE_READ_WRITE, &db));
EOF
cat <<EOF > c_tail
RUN(notmuch_database_destroy(db));
}
EOF
test_begin_subtest "notmuch_database_{set,get}_config"
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
{
RUN(notmuch_database_set_config (db, "testkey1", "testvalue1"));
RUN(notmuch_database_set_config (db, "testkey2", "testvalue2"));
RUN(notmuch_database_get_config (db, "testkey1", &val));
printf("testkey1 = %s\n", val);
RUN(notmuch_database_get_config (db, "testkey2", &val));
printf("testkey2 = %s\n", val);
}
EOF
cat <<'EOF' >EXPECTED
== stdout ==
testkey1 = testvalue1
testkey2 = testvalue2
== stderr ==
EOF
test_expect_equal_file EXPECTED OUTPUT
test_done