mapistore only supplies init/release and add/del backend contexts.
This commit also includes a sqlite3 backend skeleton (open/close sqlite db)
- A temporary mapistore testing tool has been added locally for implementation checks.
.PHONY: mapiproxy
-mapiproxy: idl \
- libmapiproxy \
- libmapiserver \
- mapiproxy/dcesrv_mapiproxy.$(SHLIBEXT) \
- mapiproxy-modules \
- mapiproxy-servers
-
-mapiproxy-install: mapiproxy mapiproxy-modules-install mapiproxy-servers-install libmapiproxy-install libmapiserver-install
+mapiproxy: idl \
+ libmapiproxy \
+ libmapiserver \
+ libmapistore \
+ mapiproxy/dcesrv_mapiproxy.$(SHLIBEXT) \
+ mapiproxy-modules \
+ mapiproxy-servers
+
+mapiproxy-install: mapiproxy \
+ mapiproxy-modules-install \
+ mapiproxy-servers-install \
+ libmapiproxy-install \
+ libmapiserver-install \
+ libmapistore-install
$(INSTALL) -d $(DESTDIR)$(SERVER_MODULESDIR)
$(INSTALL) -m 0755 mapiproxy/dcesrv_mapiproxy.$(SHLIBEXT) $(DESTDIR)$(SERVER_MODULESDIR)
-mapiproxy-uninstall: mapiproxy-modules-uninstall mapiproxy-servers-uninstall libmapiproxy-uninstall libmapiserver-uninstall
+mapiproxy-uninstall: mapiproxy-modules-uninstall \
+ mapiproxy-servers-uninstall \
+ libmapiproxy-uninstall \
+ libmapiserver-uninstall \
+ libmapistore-uninstall
rm -f $(DESTDIR)$(SERVER_MODULESDIR)/dcesrv_mapiproxy.*
rm -f $(DESTDIR)$(libdir)/libmapiproxy.*
rm -f $(DESTDIR)$(includedir)/libmapiproxy.h
-mapiproxy-clean:: mapiproxy-modules-clean mapiproxy-servers-clean libmapiproxy-clean libmapiserver-clean
+mapiproxy-clean:: mapiproxy-modules-clean \
+ mapiproxy-servers-clean \
+ libmapiproxy-clean \
+ libmapiserver-clean \
+ libmapistore-clean
rm -f mapiproxy/*.o mapiproxy/*.po
rm -f mapiproxy/dcesrv_mapiproxy.$(SHLIBEXT)
ln -fs $< $@
+################
+# libmapistore
+################
+
+libmapistore: mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION) \
+ $(OC_MAPISTORE) \
+ mapistore_test
+
+libmapistore-install: $(OC_MAPISTORE_INSTALL)
+ $(INSTALL) -m 0755 mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)
+ ln -sf libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)/libmapistore.$(SHLIBEXT)
+ $(INSTALL) -d $(DESTDIR)$(includedir)/mapistore
+ $(INSTALL) -m 0644 mapiproxy/libmapistore/mapistore.h $(DESTDIR)$(includedir)/mapistore/
+ $(INSTALL) -m 0644 mapiproxy/libmapistore/mapistore_errors.h $(DESTDIR)$(includedir)/mapistore/
+ $(INSTALL) -m 0644 mapiproxy/libmapiserver.pc $(DESTDIR)$(libdir)/pkgconfig
+
+libmapistore-clean: $(OC_MAPISTORE_CLEAN)
+ rm -f mapiproxy/libmapistore/*.po mapiproxy/libmapistore/*.o
+ rm -f mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION)
+ rm -f mapiproxy/libmapistore.$(SHLIBEXT).$(LIBMAPISTORE_SO_VERSION)
+
+libmapistore-uninstall: $(OC_MAPISTORE_UNINSTALL)
+ rm -f $(DESTDIR)$(libdir)/libmapistore.*
+ rm -rf $(DESTDIR)$(includedir)/mapistore
+ rm -f $(DESTDIR)$(libdir)/pkgconfig/libmapistore.pc
+
+libmapistore-distclean: libmapistore-clean
+ rm -f mapiproxy/libmapistore.pc
+
+distclean:: libmapistore-distclean
+
+mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION): mapiproxy/libmapistore/mapistore_interface.po \
+ mapiproxy/libmapistore/mapistore_processing.po \
+ mapiproxy/libmapistore/mapistore_backend.po
+ @$(CC) -o $@ $(DSOOPT) -Wl,-soname,libmapistore.$(SHLIBEXT).$(LIBMAPISTORE_SO_VERSION) $^ -L. $(LIBS)
+
+mapiproxy/libmapistore.$(SHLIBEXT).$(LIBMAPISTORE_SO_VERSION): libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+#####################
+# mapistore backends
+#####################
+
+mapistore_sqlite3: mapiproxy/libmapistore/backends/mapistore_sqlite3.$(SHLIBEXT)
+
+mapistore_sqlite3-install:
+ $(INSTALL) -d $(DESTDIR)$(libdir)/mapistore_backends
+ $(INSTALL) -m 0755 mapiproxy/libmapistore/backends/mapistore_sqlite3.$(SHLIBEXT) $(DESTDIR)$(libdir)/mapistore_backends/
+
+mapistore_sqlite3-uninstall:
+ rm -rf $(DESTDIR)$(libdir)/mapistore_backends
+
+mapistore_sqlite3-clean:
+ rm -f mapiproxy/libmapistore/backends/mapistore_sqlite3.o
+ rm -f mapiproxy/libmapistore/backends/mapistore_sqlite3.po
+
+clean:: mapistore_sqlite3-clean
+
+mapistore_sqlite3-distclean: mapistore_sqlite3-clean
+ rm -f mapiproxy/libmapistore/backends/mapistore_sqlite3.so
+
+distclean:: mapistore_sqlite3-distclean
+
+mapiproxy/libmapistore/backends/mapistore_sqlite3.$(SHLIBEXT): mapiproxy/libmapistore/backends/mapistore_sqlite3.po
+ @echo "Linking mapistore module $@"
+ @$(CC) $(SQLITE_CFLAGS) -o $@ $(DSOOPT) $^ -L. $(LIBS) $(SQLITE_LIBS)
+
+#######################
+# mapistore test tools
+#######################
+
+mapistore_test: bin/mapistore_test
+
+bin/mapistore_test: mapiproxy/libmapistore/tests/mapistore_test.o \
+ mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LIBS) -lpopt
+
+mapistore_clean:
+ rm -f mapiproxy/libmapistore/tests/*.o
+ rm -f bin/mapistore_test
+
+clean:: mapistore_clean
+
####################
# mapiproxy modules
####################
sambaprefix=@sambaprefix@
DSOOPT=-shared -fPIC
-CFLAGS=@CFLAGS@ -I. -Wall -Wmissing-prototypes -Wstrict-prototypes -g3 \
- -DDEFAULT_LDIF=\"$(datadir)/setup/profiles\"
+CFLAGS=@CFLAGS@ -I. -Wall -Wmissing-prototypes -Wstrict-prototypes -g3 \
+ -DDEFAULT_LDIF=\"$(datadir)/setup/profiles\" \
+ -DMAPISTORE_BACKEND_INSTALLDIR=\"$(libdir)/mapistore_backends\" \
+ -DMAPISTORE_MAPPING_PATH=\"$(prefix)/private/mapistore\"
# This value should be determined by configure at some point
SHLIBEXT=so
OC_SERVER_INSTALL=@OC_SERVER_INSTALL@
OC_SERVER_UNINSTALL=@OC_SERVER_UNINSTALL@
+# MAPISTORE BACKENDS
+OC_MAPISTORE=@OC_MAPISTORE@
+OC_MAPISTORE_CLEAN=@OC_MAPISTORE_CLEAN@
+OC_MAPISTORE_INSTALL=@OC_MAPISTORE_INSTALL@
+OC_MAPISTORE_UNINSTALL=@OC_MAPISTORE_UNINSTALL@
+
+SQLITE_CFLAGS=@SQLITE_CFLAGS@
+SQLITE_LIBS=@SQLITE_LIBS@
# SWIG
SWIGDIRS-ALL=@SWIGDIRSALL@
OC_$2_INSTALL+=" $1-install"
OC_$2_UNINSTALL+=" $1-uninstall"
;;
- SERVER)
+ SERVER|MAPISTORE)
OC_$2+=" $1"
+ OC_$2_CLEAN+="$1-clean"
OC_$2_INSTALL+=" $1-install"
OC_$2_UNINSTALL+=" $1-uninstall"
;;
esac
AC_SUBST(OC_$2)
+ AC_SUBST(OC_$2_CLEAN)
AC_SUBST(OC_$2_INSTALL)
AC_SUBST(OC_$2_UNINSTALL)
fi
+dnl ##########################################################################
+dnl libmapistore backends dependencies
+dnl ##########################################################################
+
+dnl --------------------------------------------------------------------------
+dnl Check for sqlite3
+dnl --------------------------------------------------------------------------
+PKG_CHECK_MODULES(SQLITE, sqlite3, SQLITEFOUND=yes, [SQLITEFOUND=no])
+AC_SUBST(SQLITE_CFLAGS)
+AC_SUBST(SQLITE_LIBS)
+
+if test x"$SQLITEFOUND" = x"yes"; then
+ OC_RULE_ADD(mapistore_sqlite3, MAPISTORE)
+fi
+
dnl ##########################################################################
dnl torture dependencies
dnl Makefiles
dnl ***********************
AC_CONFIG_FILES([config.mk libmapi.pc libmapiadmin.pc libocpf.pc mapiproxy/libmapiproxy.pc
- mapiproxy/libmapiserver.pc Doxyfile libmapi++/Doxyfile libocpf/Doxyfile
- libmapiadmin/Doxyfile libmapi/Doxyfile mapiproxy/Doxyfile utils/mapitest/Doxyfile])
+ mapiproxy/libmapiserver.pc mapiproxy/libmapistore.pc Doxyfile libmapi++/Doxyfile
+ libocpf/Doxyfile libmapiadmin/Doxyfile libmapi/Doxyfile mapiproxy/Doxyfile
+ utils/mapitest/Doxyfile])
AC_OUTPUT
* OpenChange Server:
- mapiproxy: $enable_mapiproxy
+ * OpenChange mapistore backends:
+ - sqlite3: $enable_mapistore_sqlite3
+
* OpenChange Tools:
- openchangeclient: $enable_openchangeclient
- mapiprofile: $enable_mapiprofile
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@prefix@/share
+datadir=@datadir@
+
+Name: MAPISTORE
+Description: MAPI Storage Abstraction Layer library
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lmapistore
+Libs.private: @LIBS@
+Cflags: -I${includedir}
+Requires: talloc tdb
--- /dev/null
+/*
+ OpenChange Storage Abstraction Layer library
+ MAPIStore SQLite backend
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+#include "mapistore_sqlite3.h"
+
+
+/**
+ \details Initialize sqlite3 mapistore backend
+
+ \return MAPISTORE_SUCCESS on success
+ */
+static int sqlite3_init(void)
+{
+ DEBUG(0, ("sqlite3 backend initialized\n"));
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Create a connection context to the sqlite3 backend
+
+ \param mem_ctx pointer to the memory context
+ \param uri pointer to the database path
+ \param context_id pointer to the context identifier the function
+ returns
+
+ \return MAPISTORE_SUCCESS on success
+ */
+static int sqlite3_create_context(TALLOC_CTX *mem_ctx, const char *uri, void **private_data)
+{
+ struct sqlite3_context *sqlite_ctx;
+ sqlite3 *db;
+ int ret;
+
+ DEBUG(0, ("[%s:%d]\n", __FUNCTION__, __LINE__));
+
+ ret = sqlite3_open(uri, &db);
+ if (ret) {
+ DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__,
+ sqlite3_errmsg(db)));
+ sqlite3_close(db);
+ return -1;
+ }
+
+ sqlite_ctx = talloc_zero(mem_ctx, struct sqlite3_context);
+ sqlite_ctx->db = db;
+ sqlite_ctx->private_data = NULL;
+
+ *private_data = (void *)sqlite_ctx;
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Delete a connection context from the sqlite3 backend
+
+ \return MAPISTORE_SUCCESS on success
+ */
+static int sqlite3_delete_context(void *private_data)
+{
+ struct sqlite3_context *sqlite_ctx = (struct sqlite3_context *)private_data;
+ int ret;
+
+ DEBUG(5, ("[%s:%d]\n", __FUNCTION__, __LINE__));
+
+ if (!private_data) {
+ return MAPISTORE_SUCCESS;
+ }
+
+ ret = sqlite3_close(sqlite_ctx->db);
+ if (ret) return MAPISTORE_ERROR;
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Entry point for mapistore SQLite backend
+
+ \return MAPISTORE_SUCCESS on success, otherwise -1
+ */
+int mapistore_init_backend(void)
+{
+ struct mapistore_backend backend;
+ int ret;
+
+ /* Fill in our name */
+ backend.name = "sqlite3";
+ backend.description = "mapistore sqlite3 backend";
+ backend.namespace = "sqlite://";
+
+ /* Fill in all the operations */
+ backend.init = sqlite3_init;
+ backend.create_context = sqlite3_create_context;
+ backend.delete_context = sqlite3_delete_context;
+
+ /* Register ourselves with the MAPIPROXY subsystem */
+ ret = mapistore_backend_register(&backend);
+ if (ret != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("Failed to register the '%s' mapistore backend!\n", backend.name));
+ return ret;
+ }
+
+ return MAPISTORE_SUCCESS;
+}
--- /dev/null
+/*
+ OpenChange Storage Abstraction Layer library
+ MAPIStore SQLite backend
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+#ifndef __MAPISTORE_SQLITE3_H
+#define __MAPISTORE_SQLITE3_H
+
+#include <mapiproxy/libmapistore/mapistore.h>
+#include <mapiproxy/libmapistore/mapistore_errors.h>
+#include <libmapi/dlinklist.h>
+#include <sqlite3.h>
+
+struct sqlite3_context {
+ sqlite3 *db;
+ void *private_data;
+};
+
+
+__BEGIN_DECLS
+
+int mapistore_init_backend(void);
+
+__END_DECLS
+
+#endif /* ! __MAPISTORE_SQLITE3_H */
--- /dev/null
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+#ifndef __MAPISTORE_H
+#define __MAPISTORE_H
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#ifndef _PUBLIC_
+#define _PUBLIC_
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <tdb.h>
+#include <talloc.h>
+#include <util/debug.h>
+
+#define MAPISTORE_SUCCESS 0
+
+typedef int (*init_backend_fn) (void);
+
+#define MAPISTORE_INIT_MODULE "mapistore_init_backend"
+
+struct mapistore_backend {
+ const char *name;
+ const char *description;
+ const char *namespace;
+
+ int (*init)(void);
+ int (*create_context)(TALLOC_CTX *, const char *, void **);
+ int (*delete_context)(void *);
+};
+
+struct backend_context {
+ const struct mapistore_backend *backend;
+ void *private_data;
+ uint32_t context_id;
+};
+
+struct backend_context_list {
+ struct backend_context *ctx;
+ struct backend_context_list *prev;
+ struct backend_context_list *next;
+};
+
+struct processing_context;
+
+struct mapistore_context {
+ struct processing_context *processing_ctx;
+ struct backend_context_list *context_list;
+};
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+__BEGIN_DECLS
+
+/* definitions from mapistore_interface.c */
+struct mapistore_context *mapistore_init(TALLOC_CTX *, const char *);
+int mapistore_release(struct mapistore_context *);
+int mapistore_add_context(struct mapistore_context *, const char *uri, uint32_t *);
+int mapistore_del_context(struct mapistore_context *, uint32_t);
+const char *mapistore_errstr(int);
+
+/* definitions from mapistore_processing.c */
+int mapistore_set_mapping_path(const char *);
+
+/* definitions from mapistore_backend.c */
+extern int mapistore_backend_register(const void *);
+const char *mapistore_backend_get_installdir(void);
+init_backend_fn *mapistore_backend_load(TALLOC_CTX *, const char *);
+
+bool mapistore_backend_run_init(init_backend_fn *);
+
+__END_DECLS
+
+#endif /* ! __MAPISTORE_H */
--- /dev/null
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Note: init and load functions have been copied from
+ samba4/source4/param/util.c initially wrote by Jelmer.
+
+ Copyright (C) Jelmer Vernooij 2005-2007
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <dirent.h>
+
+#include "mapistore.h"
+#include "mapistore_errors.h"
+#include "mapistore_private.h"
+#include <libmapi/dlinklist.h>
+
+#include <util.h>
+#include <util/debug.h>
+
+/**
+ \file mapistore_backend.c
+
+ \brief mapistore backends management API
+ */
+
+
+static struct mstore_backend {
+ struct mapistore_backend *backend;
+} *backends = NULL;
+
+int num_backends;
+
+
+/**
+ \details Register mapistore backends
+
+ \param _backend pointer to the mapistore backend to register
+
+ \return MAPISTORE_SUCCESS on success
+ */
+_PUBLIC_ extern int mapistore_backend_register(const void *_backend)
+{
+ const struct mapistore_backend *backend = _backend;
+
+ backends = realloc_p(backends, struct mstore_backend, num_backends + 1);
+ if (!backends) {
+ smb_panic("out of memory in mapistore_backend_register");
+ }
+
+ backends[num_backends].backend = smb_xmemdup(backend, sizeof (*backend));
+ backends[num_backends].backend->name = smb_xstrdup(backend->name);
+
+ num_backends++;
+
+ DEBUG(3, ("MAPISTORE backend '%s' registered\n", backend->name));
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Return the full path where mapistore backends are
+ installed.
+
+ \return Pointer to the full path where backends are installed.
+ */
+_PUBLIC_ const char *mapistore_backend_get_installdir(void)
+{
+ return MAPISTORE_BACKEND_INSTALLDIR;
+}
+
+
+/**
+ \details Obtain the backend init function from a shared library
+ file
+
+ \param path full path to the backend shared library
+
+ \return Pointer to the initialization function on success,
+ otherwise NULL.
+ */
+static init_backend_fn load_backend(const char *path)
+{
+ void *handle;
+ void *init_fn;
+
+ handle = dlopen(path, RTLD_NOW);
+ if (handle == NULL) {
+ DEBUG(0, ("Unable to open %s: %s\n", path, dlerror()));
+ return NULL;
+ }
+
+ init_fn = dlsym(handle, MAPISTORE_INIT_MODULE);
+
+ if (init_fn == NULL) {
+ DEBUG(0, ("Unable to find %s() in %s: %s\n",
+ MAPISTORE_INIT_MODULE, path, dlerror()));
+ DEBUG(1, ("Loading mapistore backend '%s' failed\n", path));
+ dlclose(handle);
+ return NULL;
+ }
+
+ return (init_backend_fn) init_fn;
+}
+
+
+/**
+ \details Load backends from specified directory
+
+ \param mem_ctx pointer to the memory context
+ \param pointer to the backends shared library folder
+
+ \return allocated array of functions pointers to initialization
+ functions on success, otherwise NULL.
+ */
+static init_backend_fn *load_backends(TALLOC_CTX *mem_ctx, const char *path)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char *filename;
+ int success = 0;
+ init_backend_fn *ret;
+
+ ret = talloc_array(mem_ctx, init_backend_fn, 2);
+ ret[0] = NULL;
+
+ dir = opendir(path);
+ if (dir == NULL) {
+ talloc_free(ret);
+ return NULL;
+ }
+
+ while ((entry = readdir(dir))) {
+ if (ISDOT(entry->d_name) || ISDOTDOT(entry->d_name)) {
+ continue;
+ }
+
+ filename = talloc_asprintf(mem_ctx, "%s/%s", path, entry->d_name);
+ ret[success] = load_backend(filename);
+ if (ret[success]) {
+ ret = talloc_realloc(mem_ctx, ret, init_backend_fn, success + 2);
+ success++;
+ ret[success] = NULL;
+ }
+
+ talloc_free(filename);
+ }
+
+ closedir(dir);
+
+ return ret;
+}
+
+
+/**
+ \details Load the initialization functions from backends DSO
+
+ \param mem_ctx pointer to the memory context
+ \param path pointer to the backend's DSO folder
+
+ \return allocated array of functions pointers to initialization
+ functions on success, otherwise NULL.
+ */
+_PUBLIC_ init_backend_fn *mapistore_backend_load(TALLOC_CTX *mem_ctx, const char *path)
+{
+ if (!path) {
+ path = mapistore_backend_get_installdir();
+ }
+
+ return load_backends(mem_ctx, path);
+}
+
+
+/**
+ \details Run specified initialization functions.
+
+ \param fns pointer to an array of mapistore backends initialization
+ functions
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapistore_backend_run_init(init_backend_fn *fns)
+{
+ int i;
+ bool ret = true;
+
+ if (fns == NULL) {
+ return true;
+ }
+
+ for (i = 0; fns[i]; i++) {
+ ret &= (bool)fns[i]();
+ }
+
+ return ret;
+}
+
+
+/**
+ \details Initialize mapistore backends
+
+ \param mem_ctx pointer to the memory context
+ \param path pointer to folder where mapistore backends are
+ installed
+
+ \return MAPISTORE_SUCCESS on success, otherwise
+ MAPISTORE_ERR_BACKEND_INIT
+ */
+int mapistore_backend_init(TALLOC_CTX *mem_ctx, const char *path)
+{
+ init_backend_fn *ret;
+ bool status;
+ int retval;
+ int i;
+
+ ret = mapistore_backend_load(mem_ctx, path);
+ status = mapistore_backend_run_init(ret);
+ talloc_free(ret);
+
+ for (i = 0; i < num_backends; i++) {
+ if (backends[i].backend) {
+ DEBUG(3, ("MAPISTORE backend '%s' loaded\n", backends[i].backend->name));
+ retval = backends[i].backend->init();
+ }
+ }
+
+ return (status != true) ? MAPISTORE_SUCCESS : MAPISTORE_ERR_BACKEND_INIT;
+}
+
+
+/**
+ \details Create backend context
+
+ \param mem_ctx pointer to the memory context
+ \param namespace the backend namespace
+ \param uri the backend parameters which can be passes inline
+
+ \return a valid backend_context pointer on success, otherwise NULL
+ */
+struct backend_context *mapistore_backend_create_context(TALLOC_CTX *mem_ctx, const char *namespace,
+ const char *uri)
+{
+ struct backend_context *context;
+ int retval;
+ bool found;
+ void *private_data = NULL;
+ int i;
+
+ DEBUG(0, ("namespace is %s and backend_uri is '%s'\n", namespace, uri));
+ for (i = 0; i < num_backends; i++) {
+ if (backends[i].backend->namespace &&
+ !strcmp(namespace, backends[i].backend->namespace)) {
+ found = true;
+ retval = backends[i].backend->create_context(mem_ctx, uri, &private_data);
+ if (retval != MAPISTORE_SUCCESS) {
+ return NULL;
+ }
+
+ break;
+ }
+ }
+ if (found == false) {
+ DEBUG(0, ("MAPISTORE: no backend with namespace '%s' is available\n", namespace));
+ return NULL;
+ }
+
+ context = talloc_zero(mem_ctx, struct backend_context);
+ context->backend = backends[i].backend;
+ context->private_data = private_data;
+ talloc_steal(context, context->private_data);
+
+ return context;
+}
+
+
+/**
+ \details Delete a context from the specified backend
+
+ \param bctx pointer to the backend context
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_backend_delete_context(struct backend_context *bctx)
+{
+ if (!bctx->backend->delete_context) return MAPISTORE_ERROR;
+
+ return bctx->backend->delete_context(bctx->private_data);
+}
--- /dev/null
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file mapistore_errors.h
+
+ \brief Thie header providers a set of result codes for MAPISTORE
+ function calls.
+ */
+
+#ifndef __MAPISTORE_ERRORS_H
+#define __MAPISTORE_ERRORS_H
+
+/**
+ The function call succeeded.
+ */
+#define MAPISTORE_SUCCESS 0
+
+/**
+ The function call failed for some non-specific reason.
+ */
+#define MAPISTORE_ERROR 1
+
+/**
+ The function call failed because it was unable to allocate the
+ memory required by underlying operations.
+ */
+#define MAPISTORE_ERR_NO_MEMORY 2
+
+/**
+ The function call failed because underlying context has already
+ been initialized
+ */
+#define MAPISTORE_ERR_ALREADY_INITIALIZED 3
+
+/**
+ The function call failed because context has not been initialized.
+ */
+#define MAPISTORE_ERR_NOT_INITIALIZED 4
+
+/**
+ The function call failed because an internal mapistore storage
+ component has corrupted data.
+ */
+#define MAPISTORE_ERR_CORRUPTED 5
+
+/**
+ The function call failed because one of the function parameters is
+ invalid
+ */
+#define MAPISTORE_ERR_INVALID_PARAMETER 6
+
+/**
+ The function call failed because the directory doesn't exist
+ */
+#define MAPISTORE_ERR_NO_DIRECTORY 7
+
+/**
+ The function call failed because the underlying function couldn't
+ open a database.
+ */
+#define MAPISTORE_ERR_DATABASE_INIT 8
+
+/**
+ The function call failed because the underlying function didn't run
+ a database operation successfully.
+ */
+#define MAPISTORE_ERR_DATABASE_OPS 9
+
+/**
+ The function failed to register a storage backend
+ */
+#define MAPISTORE_ERR_BACKEND_REGISTER 10
+
+/**
+ One of more storage backend initialization functions failed to
+ complete successfully.
+ */
+#define MAPISTORE_ERR_BACKEND_INIT 11
+
+/**
+ The function failed because mapistore failed to create a context
+ */
+#define MAPISTORE_ERR_CONTEXT_FAILED 12
+
+/**
+ The function failed because the provided namespace is invalid
+ */
+#define MAPISTORE_ERR_INVALID_NAMESPACE 13
+
+#endif /* ! __MAPISTORE_ERRORS_H */
--- /dev/null
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+#include "mapistore.h"
+#include "mapistore_errors.h"
+#include "mapistore_private.h"
+#include <libmapi/dlinklist.h>
+
+#include <string.h>
+
+/**
+ \details Initialize the mapistore context
+
+ \param mem_ctx pointer to the memory context
+
+ \return allocate mapistore context on success, otherwise NULL
+ */
+_PUBLIC_ struct mapistore_context *mapistore_init(TALLOC_CTX *mem_ctx, const char *path)
+{
+ int retval;
+ struct mapistore_context *mstore_ctx;
+
+ mstore_ctx = talloc_zero(mem_ctx, struct mapistore_context);
+ if (!mstore_ctx) {
+ return NULL;
+ }
+
+ mstore_ctx->processing_ctx = talloc_zero(mstore_ctx, struct processing_context);
+ retval = mapistore_init_mapping_context(mstore_ctx->processing_ctx);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(5, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, mapistore_errstr(retval)));
+ talloc_free(mstore_ctx);
+ return NULL;
+ }
+
+ retval = mapistore_backend_init(mem_ctx, path);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(5, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, mapistore_errstr(retval)));
+ talloc_free(mstore_ctx);
+ return NULL;
+ }
+
+ mstore_ctx->context_list = NULL;
+
+ return mstore_ctx;
+}
+
+
+/**
+ \details Release the mapistore context and destroy any data
+ associated
+
+ \param mstore_ctx pointer to the mapistore context
+
+ \note The function needs to rely on talloc destructors which is not
+ implemented in code yet.
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_release(struct mapistore_context *mstore_ctx)
+{
+ if (!mstore_ctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+
+ talloc_free(mstore_ctx->processing_ctx);
+ talloc_free(mstore_ctx->context_list);
+ talloc_free(mstore_ctx);
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Add a new connection context to mapistore
+
+ \param mstore_ctx pointer to the mapistore context
+ \param uri the connection context URI
+ \param pointer to the context identifier the function returns
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_add_context(struct mapistore_context *mstore_ctx,
+ const char *uri, uint32_t *context_id)
+{
+ TALLOC_CTX *mem_ctx;
+ int retval;
+ struct backend_context *backend_ctx;
+ struct backend_context_list *backend_list;
+ char *namespace;
+ char *namespace_start;
+ char *backend_uri;
+
+ /* Step 1. Perform Sanity Checks on URI */
+ if (!uri || strlen(uri) < 4) {
+ return MAPISTORE_ERR_INVALID_NAMESPACE;
+ }
+
+ mem_ctx = talloc_named(NULL, 0, "mapistore_add_context");
+ namespace = talloc_strdup(mem_ctx, uri);
+ namespace_start = namespace;
+ namespace = strchr(namespace, ':');
+ if (!namespace) {
+ DEBUG(0, ("[%s:%d]: Error - Invalid namespace '%s'\n", __FUNCTION__, __LINE__, namespace_start));
+ talloc_free(mem_ctx);
+ return MAPISTORE_ERR_INVALID_NAMESPACE;
+ }
+
+ if (namespace[1] && namespace[1] == '/' &&
+ namespace[2] && namespace[2] == '/' &&
+ namespace[3]) {
+ backend_uri = talloc_strdup(mem_ctx, &namespace[3]);
+ namespace[3] = '\0';
+ backend_ctx = mapistore_backend_create_context((TALLOC_CTX *)mstore_ctx, namespace_start, backend_uri);
+ if (!backend_ctx) {
+ return MAPISTORE_ERR_CONTEXT_FAILED;
+ }
+
+ backend_list = talloc_zero((TALLOC_CTX *) mstore_ctx, struct backend_context_list);
+ talloc_steal(backend_list, backend_ctx);
+ backend_list->ctx = backend_ctx;
+ retval = mapistore_get_context_id(mstore_ctx->processing_ctx, &backend_list->ctx->context_id);
+ if (retval != MAPISTORE_SUCCESS) {
+ talloc_free(mem_ctx);
+ return MAPISTORE_ERR_CONTEXT_FAILED;
+ }
+ *context_id = backend_list->ctx->context_id;
+ DLIST_ADD_END(mstore_ctx->context_list, backend_list, struct backend_context_list *);
+
+ } else {
+ DEBUG(0, ("[%s:%d]: Error - Invalid URI '%s'\n", __FUNCTION__, __LINE__, uri));
+ talloc_free(mem_ctx);
+ return MAPISTORE_ERR_INVALID_NAMESPACE;
+ }
+
+ talloc_free(mem_ctx);
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Delete an existing connection context from mapistore
+
+ \param mstore_ctx pointer to the mapistore context
+ \param context_id the context identifier referencing the context to
+ delete
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_del_context(struct mapistore_context *mstore_ctx,
+ uint32_t context_id)
+{
+ struct backend_context_list *el;
+ int retval;
+ bool found = false;
+
+ /* Sanity checks */
+ if (!mstore_ctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+ if (!mstore_ctx->processing_ctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+ if (!mstore_ctx->context_list) return MAPISTORE_ERR_NOT_INITIALIZED;
+
+ /* Step 0. Ensure the context exists */
+ for (el = mstore_ctx->context_list; el; el = el->next) {
+ if (el->ctx && el->ctx->context_id == context_id) {
+ found = true;
+ break;
+ }
+ }
+ if (found == false) return MAPISTORE_ERR_INVALID_PARAMETER;
+
+ /* Step 1. Delete the context within backend */
+ retval = mapistore_backend_delete_context(el->ctx);
+ if (retval) return retval;
+
+ /* Step 2. Delete the context from the processing layer */
+
+ /* Step 2. Add the free'd context id to the free list */
+ retval = mapistore_free_context_id(mstore_ctx->processing_ctx, context_id);
+ return retval;
+}
+
+
+/**
+ \details return a string explaining what a mapistore error constant
+ means.
+
+ \param mapistore_err the mapistore error constant
+
+ \return constant string
+ */
+_PUBLIC_ const char *mapistore_errstr(int mapistore_err)
+{
+ switch (mapistore_err) {
+ case MAPISTORE_SUCCESS:
+ return "Success";
+ case MAPISTORE_ERROR:
+ return "Non-specific error";
+ case MAPISTORE_ERR_NO_MEMORY:
+ return "No memory available";
+ case MAPISTORE_ERR_ALREADY_INITIALIZED:
+ return "Already initialized";
+ case MAPISTORE_ERR_NOT_INITIALIZED:
+ return "Not initialized";
+ case MAPISTORE_ERR_NO_DIRECTORY:
+ return "No such file or directory";
+ case MAPISTORE_ERR_DATABASE_INIT:
+ return "Database initialization failed";
+ case MAPISTORE_ERR_DATABASE_OPS:
+ return "database operation failed";
+ case MAPISTORE_ERR_BACKEND_REGISTER:
+ return "storage backend registration failed";
+ case MAPISTORE_ERR_BACKEND_INIT:
+ return "storage backend initialization failed";
+ }
+
+ return "Unknown error";
+}
--- /dev/null
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+#ifndef __MAPISTORE_PRIVATE_H__
+#define __MAPISTORE_PRIVATE_H__
+
+#ifndef ISDOT
+#define ISDOT(path) ( \
+ *((const char *)(path)) == '.' && \
+ *(((const char *)(path)) + 1) == '\0' \
+ )
+#endif
+
+#ifndef ISDOTDOT
+#define ISDOTDOT(path) ( \
+ *((const char *)(path)) == '.' && \
+ *(((const char *)(path)) + 1) == '.' && \
+ *(((const char *)(path)) + 2) == '\0' \
+ )
+#endif
+
+
+/**
+ Identifier mapping context.
+
+ This structure stores PR_MID and PR_FID identifiers to backend
+ identifiers mapping. It points on 2 databases, one with "in use"
+ identifiers and another one with a list of "free identifiers" which
+ are added when an object is deleted, moved, etc.
+
+ The last_id structure member references the last identifier value
+ which got created. There is no identifier available with a value
+ higher than last_id.
+ */
+struct id_mapping_context {
+ TDB_CONTEXT *used_ctx;
+ TDB_CONTEXT *free_ctx;
+ uint64_t last_id;
+};
+
+
+/**
+ Free context identifier list
+
+ This structure is a double chained list storing unused context
+ identifiers.
+ */
+struct context_id_list {
+ uint32_t context_id;
+ struct context_id_list *prev;
+ struct context_id_list *next;
+};
+
+
+struct processing_context {
+ struct id_mapping_context *mapping_ctx;
+ struct context_id_list *free_ctx;
+ uint32_t last_context_id;
+ uint64_t dflt_start_id;
+};
+
+
+/**
+ The database name where in use ID mappings are stored
+ */
+#define MAPISTORE_DB_LAST_ID_KEY "mapistore_last_id"
+#define MAPISTORE_DB_LAST_ID_VAL 0x15000
+
+#define MAPISTORE_DB_NAME_USED_ID "mapistore_id_mapping_used.tdb"
+#define MAPISTORE_DB_NAME_FREE_ID "mapistore_id_mapping_free.tdb"
+
+__BEGIN_DECLS
+
+/* definitions from mapistore_processing.c */
+const char *mapistore_get_mapping_path(void);
+int mapistore_init_mapping_context(struct processing_context *);
+int mapistore_get_context_id(struct processing_context *, uint32_t *);
+int mapistore_free_context_id(struct processing_context *, uint32_t);
+
+
+/* definitions from mapistore_backend.c */
+int mapistore_backend_init(TALLOC_CTX *, const char *);
+struct backend_context *mapistore_backend_create_context(TALLOC_CTX *, const char *, const char *);
+int mapistore_backend_delete_context(struct backend_context *);
+
+__END_DECLS
+
+#endif /* ! __MAPISTORE_PRIVATE_H__ */
--- /dev/null
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "mapistore.h"
+#include "mapistore_errors.h"
+#include "mapistore_private.h"
+#include <libmapi/dlinklist.h>
+
+#include <tdb.h>
+
+static struct id_mapping_context *mapping_ctx = NULL;
+char *mapping_path = NULL;
+
+
+/**
+ \details Set the mapping path
+
+ \param path pointer to the mapping path
+
+ \note The mapping path can be set unless id_mapping_context is
+ initialized. If path is NULL and mapping path is not yet
+ initialized, then mapping_path will be reset to its default value
+ when the initialization routine is called.
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_set_mapping_path(const char *path)
+{
+ TALLOC_CTX *mem_ctx;
+ DIR *dir;
+
+ /* Sanity checks */
+ if (mapping_ctx) {
+ return MAPISTORE_ERR_ALREADY_INITIALIZED;
+ }
+
+ /* Case 1. Path is set to NULL */
+ if (!path) {
+ if (mapping_path) {
+ talloc_free(mapping_path);
+ }
+ mapping_path = NULL;
+ return MAPISTORE_SUCCESS;
+ }
+
+ if (mapping_path) {
+ talloc_free(mapping_path);
+ }
+
+ /* Case 2. path is initialized */
+
+ /* Step 1. Check if path is valid path */
+ dir = opendir(path);
+ if (!dir) {
+ return MAPISTORE_ERR_NO_DIRECTORY;
+ }
+
+ /* Step 2. TODO: Check for write permissions */
+
+ mem_ctx = talloc_autofree_context();
+ mapping_path = talloc_strdup(mem_ctx, path);
+ return MAPISTORE_SUCCESS;
+}
+
+/**
+ \details Return the current mapping path
+
+ \return pointer to the mapping path.
+ */
+const char *mapistore_get_mapping_path(void)
+{
+ return (!mapping_path) ? MAPISTORE_MAPPING_PATH : (const char *)mapping_path;
+}
+
+
+/**
+ \details Initialize the ID mapping context or return the existing
+ one if already initialized.
+
+ \param pctx pointer to the processing context
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+int mapistore_init_mapping_context(struct processing_context *pctx)
+{
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ TALLOC_CTX *mem_ctx;
+ char *dbpath;
+ uint64_t last_id;
+ char *tmp_buf;
+ int ret;
+
+ if (!pctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+
+ /* Step 0. return existing mapping context if already initialized */
+ if (mapping_ctx) {
+ pctx->mapping_ctx = mapping_ctx;
+ return MAPISTORE_SUCCESS;
+ } else {
+ mapping_ctx = talloc_named(NULL, 0, "mapping_context");
+ if (!mapping_ctx) return MAPISTORE_ERR_NO_MEMORY;
+ }
+
+ mem_ctx = talloc_named(NULL, 0, "mapistore_init_mapping_context");
+
+ /* Step 1. Open/Create the used ID database */
+ if (!mapping_ctx->used_ctx) {
+ dbpath = talloc_asprintf(mem_ctx, "%s/%s", mapistore_get_mapping_path(), MAPISTORE_DB_NAME_USED_ID);
+ mapping_ctx->used_ctx = tdb_open(dbpath, 0, 0, O_RDWR|O_CREAT, 0600);
+ talloc_free(dbpath);
+ if (!mapping_ctx->used_ctx) {
+ DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, strerror(errno)));
+ talloc_free(mem_ctx);
+ talloc_free(mapping_ctx);
+ return MAPISTORE_ERR_DATABASE_INIT;
+ }
+ }
+
+ /* Step 2. Open/Create the free ID database */
+ if (!mapping_ctx->free_ctx) {
+ dbpath = talloc_asprintf(mem_ctx, "%s/%s", mapistore_get_mapping_path(), MAPISTORE_DB_NAME_FREE_ID);
+ mapping_ctx->free_ctx = tdb_open(dbpath, 0, 0, O_RDWR|O_CREAT, 0600);
+ talloc_free(dbpath);
+ if (!mapping_ctx->free_ctx) {
+ DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, strerror(errno)));
+ talloc_free(mem_ctx);
+ talloc_free(mapping_ctx);
+ return MAPISTORE_ERR_DATABASE_INIT;
+ }
+ }
+
+ /* Step 3. Retrieve the last ID value */
+ key.dptr = (unsigned char *) MAPISTORE_DB_LAST_ID_KEY;
+ key.dsize = strlen(MAPISTORE_DB_LAST_ID_KEY);
+
+ dbuf = tdb_fetch(mapping_ctx->used_ctx, key);
+
+ /* If the record doesn't exist, insert it */
+ if (!dbuf.dptr || !dbuf.dsize) {
+ dbuf.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%llx", (uint64_t) MAPISTORE_DB_LAST_ID_VAL);
+ dbuf.dsize = strlen((const char *) dbuf.dptr);
+ last_id = MAPISTORE_DB_LAST_ID_VAL;
+
+ ret = tdb_store(mapping_ctx->used_ctx, key, dbuf, TDB_INSERT);
+ talloc_free(dbuf.dptr);
+ if (ret == -1) {
+ DEBUG(3, ("[%s:%d]: Unable to create %s record: %s\n", __FUNCTION__, __LINE__,
+ MAPISTORE_DB_LAST_ID_KEY, tdb_errorstr(mapping_ctx->used_ctx)));
+ talloc_free(mem_ctx);
+ talloc_free(mapping_ctx);
+
+ return MAPISTORE_ERR_DATABASE_OPS;
+ }
+
+ } else {
+ tmp_buf = talloc_strndup(mem_ctx, (char *)dbuf.dptr, dbuf.dsize);
+ free(dbuf.dptr);
+ last_id = strtoull(tmp_buf, NULL, 16);
+ talloc_free(tmp_buf);
+ }
+
+ mapping_ctx->last_id = last_id;
+
+ pctx->mapping_ctx = mapping_ctx;
+ talloc_free(mem_ctx);
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Return an unused or new context identifier
+
+ \param pctx pointer to the processing context
+ \param context_id pointer to the context identifier the function
+ returns
+
+ \return a non zero context identifier on success, otherwise 0.
+ */
+int mapistore_get_context_id(struct processing_context *pctx, uint32_t *context_id)
+{
+ struct context_id_list *el;
+
+ /* Sanity checks */
+ if (!pctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+
+ /* Step 1. The free context list doesn't exist yet */
+ if (!pctx->free_ctx) {
+ pctx->last_context_id++;
+ *context_id = pctx->last_context_id;
+ }
+
+ /* Step 2. We have a free list */
+ for (el = pctx->free_ctx; el; el = el->next) {
+ if (el->context_id) {
+ *context_id = el->context_id;
+ DLIST_REMOVE(pctx->free_ctx, el);
+ break;
+ }
+ }
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Add a context identifier to the list
+
+ \param pctx pointer to the processing context
+ \param context_id the identifier referencing the context to free
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+int mapistore_free_context_id(struct processing_context *pctx, uint32_t context_id)
+{
+ struct context_id_list *el;
+
+ /* Sanity checks */
+ if (!pctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+
+ /* Step 1. Ensure the list is not corrupted */
+ for (el = pctx->free_ctx; el; el = el->next) {
+ if (el->context_id == context_id) {
+ return MAPISTORE_ERR_CORRUPTED;
+ }
+ }
+
+ /* Step 2. Create the element and add it to the list */
+ el = talloc_zero((TALLOC_CTX *)pctx, struct context_id_list);
+ el->context_id = context_id;
+ DLIST_ADD_END(pctx->free_ctx, el, struct context_id_list *);
+
+ return MAPISTORE_SUCCESS;
+}
--- /dev/null
+/*
+ OpenChange Storage Abstraction Layer library test tool
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+#include "mapiproxy/libmapistore/mapistore.h"
+#include <talloc.h>
+#include <core/ntstatus.h>
+#include <samba/popt.h>
+#include <param.h>
+#include <util/debug.h>
+
+/**
+ \file mapistore_test.c
+
+ \brief Test mapistore implementation
+ */
+
+
+int main(int argc, const char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ int retval;
+ struct mapistore_context *mstore_ctx;
+ struct loadparm_context *lp_ctx;
+ poptContext pc;
+ int opt;
+ const char *opt_debug = NULL;
+ uint32_t context_id = 0;
+ uint32_t context_id2 = 0;
+
+ enum { OPT_DEBUG=1000 };
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUG, "set the debug level", NULL },
+ { NULL, 0, 0, NULL, 0, NULL, NULL }
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "mapistore_test");
+ lp_ctx = loadparm_init(mem_ctx);
+ lp_load_default(lp_ctx);
+ setup_logging(NULL, DEBUG_STDOUT);
+
+ pc = poptGetContext("mapistore_test", argc, argv, long_options, 0);
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_DEBUG:
+ opt_debug = poptGetOptArg(pc);
+ break;
+ }
+ }
+
+ poptFreeContext(pc);
+
+ if (opt_debug) {
+ lp_set_cmdline(lp_ctx, "log level", opt_debug);
+ }
+
+ retval = mapistore_set_mapping_path("/tmp");
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ mstore_ctx = mapistore_init(mem_ctx, NULL);
+ if (!mstore_ctx) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ retval = mapistore_add_context(mstore_ctx, "sqlite:///tmp/test.db", &context_id);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ retval = mapistore_add_context(mstore_ctx, "sqlite:///tmp/test2.db", &context_id2);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ DEBUG(0, ("Context ID: [1] = %d and [2] = %d\n", context_id, context_id2));
+
+ retval = mapistore_del_context(mstore_ctx, context_id);
+ retval = mapistore_del_context(mstore_ctx, context_id2);
+
+ retval = mapistore_release(mstore_ctx);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ return 0;
+}