2
OpenChange Storage Abstraction Layer library
6
Copyright (C) Wolfgang Sourdeau 2011
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3 of the License, or
11
(at your option) any later version.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program. If not, see <http://www.gnu.org/licenses/>.
24
#include "mapistore.h"
25
#include "mapistore_errors.h"
26
#include "mapistore_private.h"
27
#include <dlinklist.h>
28
#include "libmapi/libmapi_private.h"
32
static void mapistore_replica_mapping_set_next_replid(struct tdb_context *, uint16_t);
33
static uint16_t mapistore_replica_mapping_get_next_replid(struct tdb_context *);
36
- 0x01 is for server replica
37
- 0x02 is for GetLocalReplicaIDs */
40
\details Search the replica_mapping record matching the username
42
\param mstore_ctx pointer to the mapistore context
43
\param username the username to lookup
45
\return pointer to the tdb_wrap structure on success, otherwise NULL
47
static struct replica_mapping_context_list *mapistore_replica_mapping_search(struct mapistore_context *mstore_ctx, const char *username)
49
struct replica_mapping_context_list *el;
52
if (!mstore_ctx) return NULL;
53
if (!mstore_ctx->replica_mapping_list) return NULL;
54
if (!username) return NULL;
56
for (el = mstore_ctx->replica_mapping_list; el; el = el->next) {
57
if (el && el->username && !strcmp(el->username, username)) {
66
\details Open connection to replica_mapping database for a given user
68
\param mstore_ctx pointer to the mapistore context
69
\param username name for which the replica_mapping database has to be
72
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
75
static int context_list_destructor(struct replica_mapping_context_list *rmctx)
77
tdb_close(rmctx->tdb);
82
_PUBLIC_ enum mapistore_error mapistore_replica_mapping_add(struct mapistore_context *mstore_ctx, const char *username, struct replica_mapping_context_list **rmctxp)
85
struct replica_mapping_context_list *rmctx;
89
MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
90
MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL);
92
/* Step 1. Search if the context already exists */
93
rmctx = mapistore_replica_mapping_search(mstore_ctx, username);
95
MAPISTORE_RETVAL_IF(rmctx, MAPISTORE_SUCCESS, NULL);
97
mem_ctx = talloc_named(NULL, 0, "mapistore_replica_mapping_init");
98
rmctx = talloc_zero(mstore_ctx->replica_mapping_list, struct replica_mapping_context_list);
100
/* Step 1. Open/Create the replica_mapping database */
101
dbpath = talloc_asprintf(mem_ctx, "%s/%s/" MAPISTORE_DB_REPLICA_MAPPING,
102
mapistore_get_mapping_path(), username);
103
rmctx->tdb = tdb_open(dbpath, 0, 0, O_RDWR|O_CREAT, 0600);
105
DEBUG(3, ("[%s:%d]: %s (%s)\n", __FUNCTION__, __LINE__, strerror(errno), dbpath));
107
talloc_free(mem_ctx);
108
return MAPISTORE_ERR_DATABASE_INIT;
110
talloc_set_destructor(rmctx, context_list_destructor);
111
rmctx->username = talloc_strdup(rmctx, username);
112
rmctx->ref_count = 0;
113
DLIST_ADD_END(mstore_ctx->replica_mapping_list, rmctx, struct replica_mapping_context_list *);
117
talloc_free(mem_ctx);
119
return MAPISTORE_SUCCESS;
122
/* _PUBLIC_ enum mapistore_error mapistore_replica_mapping_add(struct mapistore_context *mstore_ctx, const char *username) */
124
/* TALLOC_CTX *mem_ctx; */
125
/* char *dbpath = NULL; */
127
/* /\* Sanity checks *\/ */
128
/* MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL); */
129
/* MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL); */
131
/* mem_ctx = talloc_named(NULL, 0, "mapistore_replica_mapping_add"); */
133
/* /\* Step 1. Open/Create the replica_mapping database *\/ */
134
/* dbpath = talloc_asprintf(mem_ctx, "%s/%s/" MAPISTORE_DB_REPLICA_MAPPING, */
135
/* mapistore_get_mapping_path(), username); */
136
/* mstore_ctx->replica_mapping_ctx = tdb_wrap_open(mstore_ctx, dbpath, 0, 0, O_RDWR|O_CREAT, 0600); */
137
/* talloc_free(dbpath); */
138
/* if (!mstore_ctx->replica_mapping_ctx) { */
139
/* DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, strerror(errno))); */
140
/* talloc_free(mem_ctx); */
141
/* return MAPISTORE_ERR_DATABASE_INIT; */
143
/* if (mapistore_replica_mapping_get_next_replid(mstore_ctx->replica_mapping_ctx->tdb) == 0xffff) { */
144
/* mapistore_replica_mapping_set_next_replid(mstore_ctx->replica_mapping_ctx->tdb, 0x3); */
147
/* talloc_free(mem_ctx); */
149
/* return MAPI_E_SUCCESS; */
152
static void mapistore_replica_mapping_set_next_replid(struct tdb_context *tdb, uint16_t replid) {
154
TDB_DATA replid_data;
158
mem_ctx = talloc_zero(NULL, void);
161
key.dptr = (unsigned char *) "next_replid";
162
key.dsize = strlen((const char *) key.dptr);
164
replid_data.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%.4x", replid);
165
replid_data.dsize = strlen((const char *) replid_data.dptr);
167
ret = tdb_exists(tdb, key);
168
op = (ret) ? TDB_MODIFY : TDB_INSERT;
169
tdb_store(tdb, key, replid_data, op);
171
talloc_free(mem_ctx);
174
static uint16_t mapistore_replica_mapping_get_next_replid(struct tdb_context *tdb) {
176
TDB_DATA replid_data;
182
key.dptr = (unsigned char *) "next_replid";
183
key.dsize = strlen((const char *) key.dptr);
185
ret = tdb_exists(tdb, key);
190
replid_data = tdb_fetch(tdb, key);
192
tmp_data = talloc_strndup(NULL, (char *) replid_data.dptr, replid_data.dsize);
193
replid = strtoul(tmp_data, NULL, 16);
194
talloc_free(tmp_data);
199
static void mapistore_replica_mapping_add_pair(struct tdb_context *tdb, const struct GUID *guidP, uint16_t replid)
205
mem_ctx = talloc_zero(NULL, void);
208
guid_key.dptr = (unsigned char *) GUID_string(mem_ctx, guidP);
209
guid_key.dsize = strlen((const char *) guid_key.dptr);
211
replid_key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%.4x", replid);
212
replid_key.dsize = strlen((const char *) replid_key.dptr);
214
tdb_store(tdb, guid_key, replid_key, TDB_INSERT);
215
tdb_store(tdb, replid_key, guid_key, TDB_INSERT);
217
talloc_free(mem_ctx);
220
static enum mapistore_error mapistore_replica_mapping_search_guid(struct tdb_context *tdb, const struct GUID *guidP, uint16_t *replidP)
227
mem_ctx = talloc_zero(NULL, void);
229
guid_key.dptr = (unsigned char *) GUID_string(mem_ctx, guidP);
230
guid_key.dsize = strlen((const char *) guid_key.dptr);
232
ret = tdb_exists(tdb, guid_key);
234
talloc_free(mem_ctx);
235
return MAPISTORE_ERROR;
238
replid_key = tdb_fetch(tdb, guid_key);
239
*replidP = strtoul((char *) replid_key.dptr + 2, NULL, 16);
241
talloc_free(mem_ctx);
243
return MAPISTORE_SUCCESS;
247
\details Search a replica guid in the database, creates it if it does not exist
249
\param mstore_ctx pointer to the mapistore context
250
\param guidP the replica guid
251
\param replidP pointer to the returned replica id
253
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
255
_PUBLIC_ enum mapistore_error mapistore_replica_mapping_guid_to_replid(struct mapistore_context *mstore_ctx, const char *username, const struct GUID *guidP, uint16_t *replidP)
259
struct replica_mapping_context_list *list;
261
ret = mapistore_replica_mapping_add(mstore_ctx, username, &list);
262
MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERROR, NULL);
263
MAPISTORE_RETVAL_IF(!list, MAPISTORE_ERROR, NULL);
265
ret = mapistore_replica_mapping_search_guid(list->tdb, guidP, replidP);
266
if (ret == MAPISTORE_SUCCESS) {
270
new_replid = mapistore_replica_mapping_get_next_replid(list->tdb);
271
if (new_replid == 0xffff) { /* should never occur */
272
DEBUG(0, ("%s: FATAL: next replica id is not configured for this database\n", __FUNCTION__));
273
return MAPISTORE_ERROR;
276
mapistore_replica_mapping_add_pair(list->tdb, guidP, new_replid);
277
mapistore_replica_mapping_set_next_replid(list->tdb, new_replid + 1);
279
*replidP = new_replid;
281
return MAPISTORE_SUCCESS;
285
\details Search a replica id in the database
287
\param mstore_ctx pointer to the mapistore context
288
\param replid the replica id
289
\param guidP pointer to the returned replica guid
291
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
293
_PUBLIC_ enum mapistore_error mapistore_replica_mapping_replid_to_guid(struct mapistore_context *mstore_ctx, const char *username, uint16_t replid, struct GUID *guidP)
296
TDB_DATA guid_key, replid_key;
298
struct replica_mapping_context_list *list;
300
ret = mapistore_replica_mapping_add(mstore_ctx, username, &list);
301
MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERROR, NULL);
302
MAPISTORE_RETVAL_IF(!list, MAPISTORE_ERROR, NULL);
304
mem_ctx = talloc_zero(NULL, void);
306
replid_key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%.4x", replid);
307
replid_key.dsize = strlen((const char *) replid_key.dptr);
309
ret = tdb_exists(list->tdb, replid_key);
311
talloc_free(mem_ctx);
312
return MAPISTORE_ERROR;
315
guid_key = tdb_fetch(list->tdb, replid_key);
316
GUID_from_string((char *) guid_key.dptr, guidP);
318
talloc_free(mem_ctx);
320
return MAPISTORE_SUCCESS;