summaryrefslogtreecommitdiffstats
path: root/ldap/servers/plugins/replication/repl5.h
blob: a9a185302e6686eead004d684f9c4f06e87daced (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
/** BEGIN COPYRIGHT BLOCK
 * 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; version 2 of the License.
 * 
 * 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, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA.
 * 
 * In addition, as a special exception, Red Hat, Inc. gives You the additional
 * right to link the code of this Program with code not covered under the GNU
 * General Public License ("Non-GPL Code") and to distribute linked combinations
 * including the two, subject to the limitations in this paragraph. Non-GPL Code
 * permitted under this exception must only link to the code of this Program
 * through those well defined interfaces identified in the file named EXCEPTION
 * found in the source code files (the "Approved Interfaces"). The files of
 * Non-GPL Code may instantiate templates or use macros or inline functions from
 * the Approved Interfaces without causing the resulting work to be covered by
 * the GNU General Public License. Only Red Hat, Inc. may make changes or
 * additions to the list of Approved Interfaces. You must obey the GNU General
 * Public License in all respects for all of the Program code and other code used
 * in conjunction with the Program except the Non-GPL Code covered by this
 * exception. If you modify this file, you may extend this exception to your
 * version of the file, but you are not obligated to do so. If you do not wish to
 * provide this exception without modification, you must delete this exception
 * statement from your version and license this file solely under the GPL without
 * exception. 
 * 
 * 
 * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
 * Copyright (C) 2010 Red Hat, Inc.
 * All rights reserved.
 * END COPYRIGHT BLOCK **/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif


/* repl5.h - 5.0 replication header */
 
#ifndef _REPL5_H_
#define _REPL5_H_

#include <limits.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#ifndef _WIN32
#include <sys/param.h>
#endif /* _WIN32 */

#include "portable.h" /* GGOODREPL - is this cheating? */
#include "repl_shared.h"
#include "llist.h"
#include "repl5_ruv.h"
#include "cl4.h"

#define REPLICA_TYPE_WINDOWS 1
#define REPLICA_TYPE_MULTIMASTER 0
#define REPL_DIRSYNC_CONTROL_OID "1.2.840.113556.1.4.841"
#define REPL_RETURN_DELETED_OBJS_CONTROL_OID "1.2.840.113556.1.4.417"
#define REPL_WIN2K3_AD_OID "1.2.840.113556.1.4.1670"

/* DS 5.0 replication protocol OIDs */
#define REPL_START_NSDS50_REPLICATION_REQUEST_OID "2.16.840.1.113730.3.5.3"
#define REPL_END_NSDS50_REPLICATION_REQUEST_OID "2.16.840.1.113730.3.5.5"
#define REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID "2.16.840.1.113730.3.5.6"
#define REPL_NSDS50_REPLICATION_RESPONSE_OID "2.16.840.1.113730.3.5.4"
#define REPL_NSDS50_UPDATE_INFO_CONTROL_OID    "2.16.840.1.113730.3.4.13"
#define REPL_NSDS50_INCREMENTAL_PROTOCOL_OID "2.16.840.1.113730.3.6.1"
#define REPL_NSDS50_TOTAL_PROTOCOL_OID "2.16.840.1.113730.3.6.2"
/* DS7.1 introduces pipelineing in the protocol : really not much different to the 5.0 
 * protocol, but enough change to make it unsafe to interoperate the two. So we define 
 * new OIDs for 7.1 here. The supplier server looks for these on the consumer and 
 * if they're not there it falls back to the older 5.0 non-pipelined protocol */
#define REPL_NSDS71_INCREMENTAL_PROTOCOL_OID "2.16.840.1.113730.3.6.4"
#define REPL_NSDS71_TOTAL_PROTOCOL_OID "2.16.840.1.113730.3.6.3"
/* The new protocol OIDs above do not help us with determining if a consumer
 * Supports them or not. That's because they're burried inside the start replication 
 * extended operation, and are not visible in the support controls and operations list 
 * So, we add a new extended operation for the 7.1 total protocol. This is partly because
 * the total protocol is slightly different (no LDAP_BUSY allowed in 7.1) and partly
 * because we need a handy way to spot the difference between a pre-7.1 and post-7.0 
 * consumer at the supplier */
#define REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID "2.16.840.1.113730.3.5.9"
/* DS9.0 introduces replication session callbacks that can send/receive
 * arbitrary data when starting a replication session.  This requires a
 * new set of start and response extops. */
#define REPL_START_NSDS90_REPLICATION_REQUEST_OID "2.16.840.1.113730.3.5.12"
#define REPL_NSDS90_REPLICATION_RESPONSE_OID "2.16.840.1.113730.3.5.13"


/* DS 5.0 replication protocol error codes */
#define NSDS50_REPL_REPLICA_READY 0x00 /* Replica ready, go ahead */
#define NSDS50_REPL_REPLICA_BUSY 0x01 /* Replica busy, try later */
#define NSDS50_REPL_EXCESSIVE_CLOCK_SKEW 0x02 /* Supplier clock too far ahead */
#define NSDS50_REPL_PERMISSION_DENIED 0x03 /* Bind DN not allowed to send updates */
#define NSDS50_REPL_DECODING_ERROR 0x04 /* Consumer couldn't decode extended operation */
#define NSDS50_REPL_UNKNOWN_UPDATE_PROTOCOL 0x05 /* Consumer doesn't understand suplier's update protocol */
#define NSDS50_REPL_NO_SUCH_REPLICA 0x06 /* Consumer holds no such replica */
#define NSDS50_REPL_BELOW_PURGEPOINT 0x07 /* Supplier provided a CSN below the consumer's purge point */
#define NSDS50_REPL_INTERNAL_ERROR 0x08 /* Something bad happened on consumer */
#define NSDS50_REPL_REPLICA_RELEASE_SUCCEEDED 0x09 /* Replica released successfully */
#define NSDS50_REPL_LEGACY_CONSUMER 0x0A    /* replica is a legacy consumer */
#define NSDS50_REPL_REPLICAID_ERROR 0x0B	/* replicaID doesn't seem to be unique */
#define NSDS50_REPL_DISABLED 0x0C	/* replica suffix is disabled */
#define NSDS50_REPL_UPTODATE 0x0D	/* replica is uptodate */
#define NSDS50_REPL_BACKOFF 0x0E        /* replica wants master to go into backoff mode */
#define NSDS50_REPL_REPLICA_NO_RESPONSE 0xff /* No response received */

/* Protocol status */
#define PROTOCOL_STATUS_UNKNOWN 701
#define PROTOCOL_STATUS_INCREMENTAL_AWAITING_CHANGES 702
#define PROTOCOL_STATUS_INCREMENTAL_ACQUIRING_REPLICA 703
#define PROTOCOL_STATUS_INCREMENTAL_RELEASING_REPLICA 704
#define PROTOCOL_STATUS_INCREMENTAL_SENDING_UPDATES 705
#define PROTOCOL_STATUS_INCREMENTAL_BACKING_OFF 706
#define PROTOCOL_STATUS_INCREMENTAL_NEEDS_TOTAL_UPDATE 707
#define PROTOCOL_STATUS_INCREMENTAL_FATAL_ERROR 708
#define PROTOCOL_STATUS_TOTAL_ACQUIRING_REPLICA 709
#define PROTOCOL_STATUS_TOTAL_RELEASING_REPLICA 710
#define PROTOCOL_STATUS_TOTAL_SENDING_DATA 711

/* To Allow Consumer Initialisation when adding an agreement - */
#define STATE_PERFORMING_TOTAL_UPDATE 501
#define STATE_PERFORMING_INCREMENTAL_UPDATE 502

#define MAX_NUM_OF_MASTERS		64
#define REPL_SESSION_ID_SIZE	64

/* Attribute names for replication agreement attributes */
extern const char *type_nsds5ReplicaHost;
extern const char *type_nsds5ReplicaPort;
extern const char *type_nsds5TransportInfo;
extern const char *type_nsds5ReplicaBindDN;
extern const char *type_nsds5ReplicaCredentials;
extern const char *type_nsds5ReplicaBindMethod;
extern const char *type_nsds5ReplicaRoot;
extern const char *type_nsds5ReplicatedAttributeList;
extern const char *type_nsds5ReplicaUpdateSchedule;
extern const char *type_nsds5ReplicaInitialize;
extern const char *type_nsds5ReplicaTimeout;
extern const char *type_nsds5ReplicaBusyWaitTime;
extern const char *type_nsds5ReplicaSessionPauseTime;

/* Attribute names for windows replication agreements */
extern const char *type_nsds7WindowsReplicaArea;
extern const char *type_nsds7DirectoryReplicaArea;
extern const char *type_nsds7CreateNewUsers;
extern const char *type_nsds7CreateNewGroups;
extern const char *type_nsds7DirsyncCookie;
extern const char *type_nsds7WindowsDomain;
extern const char *type_winSyncInterval;
/* To Allow Consumer Initialisation when adding an agreement - */
extern const char *type_nsds5BeginReplicaRefresh;

/* replica related attributes */
extern const char *attr_replicaId;
extern const char *attr_replicaRoot;
extern const char *attr_replicaType;
extern const char *attr_replicaBindDn;
extern const char *attr_state;
extern const char *attr_flags;
extern const char *attr_replicaName;
extern const char *attr_replicaReferral;
extern const char *type_ruvElement;
extern const char *type_replicaPurgeDelay;
extern const char *type_replicaChangeCount;
extern const char *type_replicaTombstonePurgeInterval;
extern const char *type_replicaLegacyConsumer;
extern const char *type_ruvElementUpdatetime;

/* multimaster plugin points */
int multimaster_preop_bind (Slapi_PBlock *pb); 
int multimaster_preop_add (Slapi_PBlock *pb);
int multimaster_preop_delete (Slapi_PBlock *pb);
int multimaster_preop_modify (Slapi_PBlock *pb);
int multimaster_preop_modrdn (Slapi_PBlock *pb);
int multimaster_preop_search (Slapi_PBlock *pb);
int multimaster_preop_compare (Slapi_PBlock *pb);
int multimaster_bepreop_add (Slapi_PBlock *pb);
int multimaster_bepreop_delete (Slapi_PBlock *pb);
int multimaster_bepreop_modify (Slapi_PBlock *pb);
int multimaster_bepreop_modrdn (Slapi_PBlock *pb);
int multimaster_bepostop_modrdn (Slapi_PBlock *pb);
int multimaster_bepostop_delete (Slapi_PBlock *pb);
int multimaster_postop_bind (Slapi_PBlock *pb);
int multimaster_postop_add (Slapi_PBlock *pb);
int multimaster_postop_delete (Slapi_PBlock *pb);
int multimaster_postop_modify (Slapi_PBlock *pb);
int multimaster_postop_modrdn (Slapi_PBlock *pb);

/* In repl5_init.c */
char* get_thread_private_agmtname ();
void  set_thread_private_agmtname (const char *agmtname);
void* get_thread_private_cache ();
void  set_thread_private_cache (void *buf);
char* get_repl_session_id (Slapi_PBlock *pb, char *id, CSN **opcsn);

/* In repl_extop.c */
int multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb);
int multimaster_extop_EndNSDS50ReplicationRequest(Slapi_PBlock *pb);
int extop_noop(Slapi_PBlock *pb);
struct berval *NSDS50StartReplicationRequest_new(const char *protocol_oid,
	const char *repl_root, char **extra_referrals, CSN *csn);
struct berval *NSDS50EndReplicationRequest_new(char *repl_root);
int decode_repl_ext_response(struct berval *bvdata, int *response_code,
	struct berval ***ruv_bervals, char **data_guid, struct berval **data);
struct berval *NSDS90StartReplicationRequest_new(const char *protocol_oid,
        const char *repl_root, char **extra_referrals, CSN *csn,
	const char *data_guid, const struct berval *data);

/* In repl5_total.c */
int multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb);

/* In repl_controls.c */
int create_NSDS50ReplUpdateInfoControl(const char *uuid,
	const char *superior_uuid, const CSN *csn,
	LDAPMod **modify_mods, LDAPControl **ctrlp);
void destroy_NSDS50ReplUpdateInfoControl(LDAPControl **ctrlp);
int decode_NSDS50ReplUpdateInfoControl(LDAPControl **controlsp,
    char **uuid, char **newsuperior_uuid, CSN **csn, LDAPMod ***modrdn_mods);

/* In repl5_replsupplier.c */
typedef struct repl_supplier Repl_Supplier;
Repl_Supplier *replsupplier_init(Slapi_Entry *e);
void replsupplier_configure(Repl_Supplier *rs, Slapi_PBlock *pb);
void replsupplier_start(Repl_Supplier *rs);
void replsupplier_stop(Repl_Supplier *rs);
void replsupplier_destroy(Repl_Supplier **rs);
void replsupplier_notify(Repl_Supplier *rs, PRUint32 eventmask);
PRUint32 replsupplier_get_status(Repl_Supplier *rs);

/* In repl5_plugins.c */
int multimaster_set_local_purl();
const char *multimaster_get_local_purl();
PRBool multimaster_started();

/* In repl5_schedule.c */
typedef struct schedule Schedule;
typedef void (*window_state_change_callback)(void *arg, PRBool opened);
Schedule *schedule_new(window_state_change_callback callback_fn, void *callback_arg, const char *session_id);
void schedule_destroy(Schedule *s);
int schedule_set(Schedule *sch, Slapi_Attr *attr);
char **schedule_get(Schedule *sch);
int schedule_in_window_now(Schedule *sch);
PRTime schedule_next(Schedule *sch);
int schedule_notify(Schedule *sch, Slapi_PBlock *pb);
void schedule_set_priority_attributes(Schedule *sch, char **prio_attrs, int override_schedule);
void schedule_set_startup_delay(Schedule *sch, size_t startup_delay);
void schedule_set_maximum_backlog(Schedule *sch, size_t max_backlog);
void schedule_notify_session(Schedule *sch, PRTime session_end_time, unsigned int flags);
#define REPLICATION_SESSION_SUCCESS	0

/* In repl5_bos.c */
typedef struct repl_bos Repl_Bos;

/* In repl5_agmt.c */
typedef struct repl5agmt Repl_Agmt;
#define TRANSPORT_FLAG_SSL 1
#define TRANSPORT_FLAG_TLS 2
#define BINDMETHOD_SIMPLE_AUTH 1
#define BINDMETHOD_SSL_CLIENTAUTH 2
#define BINDMETHOD_SASL_GSSAPI 3
#define BINDMETHOD_SASL_DIGEST_MD5 4
Repl_Agmt *agmt_new_from_entry(Slapi_Entry *e);
Repl_Agmt *agmt_new_from_pblock(Slapi_PBlock *pb);
void agmt_delete(void **ra);
const Slapi_DN *agmt_get_dn_byref(const Repl_Agmt *ra);
int agmt_get_auto_initialize(const Repl_Agmt *ra);
long agmt_get_timeout(const Repl_Agmt *ra);
long agmt_get_busywaittime(const Repl_Agmt *ra);
long agmt_get_pausetime(const Repl_Agmt *ra);
int agmt_start(Repl_Agmt *ra);
int windows_agmt_start(Repl_Agmt *ra); 
int agmt_stop(Repl_Agmt *ra);
int agmt_replicate_now(Repl_Agmt *ra);
char *agmt_get_hostname(const Repl_Agmt *ra);
int agmt_get_port(const Repl_Agmt *ra);
PRUint32 agmt_get_transport_flags(const Repl_Agmt *ra);
char *agmt_get_binddn(const Repl_Agmt *ra);
struct berval *agmt_get_credentials(const Repl_Agmt *ra);
int agmt_get_bindmethod(const Repl_Agmt *ra);
Slapi_DN *agmt_get_replarea(const Repl_Agmt *ra);
int agmt_is_fractional(const Repl_Agmt *ra);
int agmt_is_fractional_attr(const Repl_Agmt *ra, const char *attrname);
int agmt_is_50_mm_protocol(const Repl_Agmt *ra);
int agmt_matches_name(const Repl_Agmt *ra, const Slapi_DN *name);
int agmt_replarea_matches(const Repl_Agmt *ra, const Slapi_DN *name);
int agmt_schedule_in_window_now(const Repl_Agmt *ra);
int agmt_set_schedule_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_timeout_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_busywaittime_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_pausetime_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_credentials_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_binddn_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_bind_method_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_transportinfo_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
const char *agmt_get_long_name(const Repl_Agmt *ra);
int agmt_initialize_replica(const Repl_Agmt *agmt);
void agmt_replica_init_done (const Repl_Agmt *agmt);
void agmt_notify_change(Repl_Agmt *ra, Slapi_PBlock *pb);
Object* agmt_get_consumer_ruv (Repl_Agmt *ra);
ReplicaId agmt_get_consumer_rid ( Repl_Agmt *ra, void *conn );
int agmt_set_consumer_ruv (Repl_Agmt *ra, RUV *ruv);
void agmt_update_consumer_ruv (Repl_Agmt *ra);
CSN* agmt_get_consumer_schema_csn (Repl_Agmt *ra);
void agmt_set_consumer_schema_csn (Repl_Agmt *ra, CSN *csn);
void agmt_set_last_update_in_progress (Repl_Agmt *ra, PRBool in_progress);
void agmt_set_last_update_start (Repl_Agmt *ra, time_t start_time);
void agmt_set_last_update_end (Repl_Agmt *ra, time_t end_time);
void agmt_set_last_update_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *msg);
void agmt_set_update_in_progress (Repl_Agmt *ra, PRBool in_progress);
void agmt_set_last_init_start (Repl_Agmt *ra, time_t start_time);
void agmt_set_last_init_end (Repl_Agmt *ra, time_t end_time);
void agmt_set_last_init_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *msg);
void agmt_inc_last_update_changecount (Repl_Agmt *ra, ReplicaId rid, int skipped);
void agmt_get_changecount_string (Repl_Agmt *ra, char *buf, int bufsize);
int agmt_set_replicated_attributes_from_entry(Repl_Agmt *ra, const Slapi_Entry *e);
int agmt_set_replicated_attributes_from_attr(Repl_Agmt *ra, Slapi_Attr *sattr);
char **agmt_get_fractional_attrs(const Repl_Agmt *ra);
char **agmt_validate_replicated_attributes(Repl_Agmt *ra);
void* agmt_get_priv (const Repl_Agmt *agmt);
void agmt_set_priv (Repl_Agmt *agmt, void* priv);

int get_agmt_agreement_type ( Repl_Agmt *agmt);
int agmt_has_protocol(Repl_Agmt *agmt);

typedef struct replica Replica;

/* In repl5_agmtlist.c */
int agmtlist_config_init();
void agmtlist_shutdown();
void agmtlist_notify_all(Slapi_PBlock *pb);
Object* agmtlist_get_first_agreement_for_replica (Replica *r);
Object* agmtlist_get_next_agreement_for_replica (Replica *r, Object *prev);


/* In repl5_backoff.c */
typedef struct backoff_timer Backoff_Timer;
#define BACKOFF_FIXED 1
#define BACKOFF_EXPONENTIAL 2
#define BACKOFF_RANDOM 3
Backoff_Timer *backoff_new(int timer_type, int initial_interval, int max_interval);
time_t backoff_reset(Backoff_Timer *bt, slapi_eq_fn_t callback, void *callback_data);
time_t backoff_step(Backoff_Timer *bt);
int backoff_expired(Backoff_Timer *bt, int margin);
void backoff_delete(Backoff_Timer **btp);

/* In repl5_connection.c */
typedef struct repl_connection Repl_Connection;
typedef enum
{   
    CONN_OPERATION_SUCCESS,
	CONN_OPERATION_FAILED,
	CONN_NOT_CONNECTED,
	CONN_SUPPORTS_DS5_REPL,
	CONN_DOES_NOT_SUPPORT_DS5_REPL,
	CONN_SCHEMA_UPDATED,
	CONN_SCHEMA_NO_UPDATE_NEEDED,
	CONN_LOCAL_ERROR,
	CONN_BUSY,
	CONN_SSL_NOT_ENABLED,
	CONN_TIMEOUT,
	CONN_SUPPORTS_DS71_REPL,
	CONN_DOES_NOT_SUPPORT_DS71_REPL,
	CONN_IS_READONLY,
	CONN_IS_NOT_READONLY,
	CONN_SUPPORTS_DIRSYNC,
	CONN_DOES_NOT_SUPPORT_DIRSYNC,
	CONN_IS_WIN2K3,
	CONN_NOT_WIN2K3,
	CONN_SUPPORTS_DS90_REPL,
	CONN_DOES_NOT_SUPPORT_DS90_REPL
} ConnResult;  
Repl_Connection *conn_new(Repl_Agmt *agmt);
ConnResult conn_connect(Repl_Connection *conn);
void conn_disconnect(Repl_Connection *conn);
void conn_delete(Repl_Connection *conn);
void conn_get_error(Repl_Connection *conn, int *operation, int *error);
void conn_get_error_ex(Repl_Connection *conn, int *operation, int *error, char **error_string);
ConnResult conn_send_add(Repl_Connection *conn, const char *dn, LDAPMod **attrs,
	LDAPControl *update_control, int *message_id);
ConnResult conn_send_delete(Repl_Connection *conn, const char *dn,
	LDAPControl *update_control, int *message_id);
ConnResult conn_send_modify(Repl_Connection *conn, const char *dn, LDAPMod **mods,
	LDAPControl *update_control, int *message_id);
ConnResult conn_send_rename(Repl_Connection *conn, const char *dn,
	const char *newrdn, const char *newparent, int deleteoldrdn,
	LDAPControl *update_control, int *message_id);
ConnResult conn_send_extended_operation(Repl_Connection *conn, const char *extop_oid,
	struct berval *payload, LDAPControl *update_control, int *message_id);
const char *conn_get_status(Repl_Connection *conn);
void conn_start_linger(Repl_Connection *conn);
void conn_cancel_linger(Repl_Connection *conn);
ConnResult conn_replica_supports_ds5_repl(Repl_Connection *conn);
ConnResult conn_replica_supports_ds71_repl(Repl_Connection *conn);
ConnResult conn_replica_supports_ds90_repl(Repl_Connection *conn);
ConnResult conn_replica_is_readonly(Repl_Connection *conn);

ConnResult conn_read_entry_attribute(Repl_Connection *conn, const char *dn, char *type,
	struct berval ***returned_bvals);
ConnResult conn_push_schema(Repl_Connection *conn, CSN **remotecsn);
void conn_set_timeout(Repl_Connection *conn, long timeout);
long conn_get_timeout(Repl_Connection *conn);
void conn_set_agmt_changed(Repl_Connection *conn);
ConnResult conn_read_result(Repl_Connection *conn, int *message_id);
ConnResult conn_read_result_ex(Repl_Connection *conn, char **retoidp, struct berval **retdatap, LDAPControl ***returned_controls, int *message_id, int noblock);

/* In repl5_protocol.c */
typedef struct repl_protocol Repl_Protocol;
Repl_Protocol *prot_new(Repl_Agmt *agmt, int protocol_state);
void prot_start(Repl_Protocol *rp);
Repl_Agmt *prot_get_agreement(Repl_Protocol *rp);
/* initiate total protocol */
void prot_initialize_replica(Repl_Protocol *rp);
/* stop protocol session in progress */
void prot_stop(Repl_Protocol *rp);
void prot_delete(Repl_Protocol **rpp);
void prot_free(Repl_Protocol **rpp);
PRBool prot_set_active_protocol (Repl_Protocol *rp, PRBool total);
void prot_clear_active_protocol (Repl_Protocol *rp);
Repl_Connection *prot_get_connection(Repl_Protocol *rp);
void prot_resume(Repl_Protocol *rp, int wakeup_action);
void prot_notify_update(Repl_Protocol *rp);
void prot_notify_agmt_changed(Repl_Protocol *rp, char * agmt_name);
void prot_notify_window_opened (Repl_Protocol *rp);
void prot_notify_window_closed (Repl_Protocol *rp);
Object *prot_get_replica_object(Repl_Protocol *rp);
void prot_replicate_now(Repl_Protocol *rp);

/* In repl5_replica.c */
typedef enum
{   
    REPLICA_TYPE_UNKNOWN,
	REPLICA_TYPE_PRIMARY,
	REPLICA_TYPE_READONLY,
	REPLICA_TYPE_UPDATABLE,
    REPLICA_TYPE_END	
} ReplicaType;  

#define RUV_STORAGE_ENTRY_UNIQUEID "ffffffff-ffffffff-ffffffff-ffffffff"
#define START_ITERATION_ENTRY_UNIQUEID "00000000-00000000-00000000-00000000"
#define START_ITERATION_ENTRY_DN       "cn=start iteration"

typedef int (*FNEnumReplica) (Replica *r, void *arg);

/* this function should be called to construct the replica object
   from the data already in the DIT */
Replica *replica_new(const Slapi_DN *root);
Replica *windows_replica_new(const Slapi_DN *root);
/* this function should be called to construct the replica object
   during addition of the replica over LDAP */
Replica *replica_new_from_entry (Slapi_Entry *e, char *errortext, PRBool is_add_operation);
void replica_destroy(void **arg);
PRBool replica_get_exclusive_access(Replica *r, PRBool *isInc, PRUint64 connid, int opid,
									const char *locking_purl,
									char **current_purl);
void replica_relinquish_exclusive_access(Replica *r, PRUint64 connid, int opid);
PRBool replica_get_tombstone_reap_active(const Replica *r);
const Slapi_DN *replica_get_root(const Replica *r);
const char *replica_get_name(const Replica *r);
ReplicaId replica_get_rid (const Replica *r);
void replica_set_rid (Replica *r, ReplicaId rid);
PRBool replica_is_initialized (const Replica *r);
Object *replica_get_ruv (const Replica *r);
/* replica now owns the RUV */
void replica_set_ruv (Replica *r, RUV *ruv);
Object *replica_get_csngen (const Replica *r);
ReplicaType replica_get_type (const Replica *r);
void replica_set_type (Replica *r, ReplicaType type);
PRBool replica_is_legacy_consumer (const Replica *r);
void replica_set_legacy_consumer (Replica *r, PRBool legacy);
char *replica_get_legacy_purl (const Replica *r);
void replica_set_legacy_purl (Replica *r, const char *purl);
PRBool replica_is_updatedn (const Replica *r, const Slapi_DN *sdn);
void replica_set_updatedn (Replica *r, const Slapi_ValueSet *vs, int mod_op);
char *replica_get_generation (const Replica *r);
/* currently supported flags */
#define REPLICA_LOG_CHANGES 0x1 /* enable change logging */
PRBool replica_is_flag_set (const Replica *r, PRUint32 flag);
void   replica_set_flag (Replica *r, PRUint32 flag, PRBool clear);
void   replica_replace_flags (Replica *r, PRUint32 flags);
void replica_dump(Replica *r);
void replica_set_enabled (Replica *r, PRBool enable);
Object *replica_get_replica_from_dn (const Slapi_DN *dn);
void replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl);
Object *replica_get_replica_for_op (Slapi_PBlock *pb);
/* the functions below manipulate replica hash */
int replica_init_name_hash ();
void replica_destroy_name_hash ();
int replica_add_by_name (const char *name, Object *replica);
int replica_delete_by_name (const char *name);
Object* replica_get_by_name (const char *name);
void replica_flush(Replica *r);
void replica_get_referrals(const Replica *r, char ***referrals);
void replica_set_referrals(Replica *r,const Slapi_ValueSet *vs);
int replica_update_csngen_state (Replica *r, const RUV *ruv);
int replica_update_csngen_state_ext (Replica *r, const RUV *ruv, const CSN *extracsn);
CSN *replica_get_purge_csn(const Replica *r);
int replica_log_ruv_elements (const Replica *r);
void replica_enumerate_replicas (FNEnumReplica fn, void *arg);
int replica_reload_ruv (Replica *r);
int replica_check_for_data_reload (Replica *r, void *arg);
/* the functions below manipulate replica dn hash */
int replica_init_dn_hash ();
void replica_destroy_dn_hash ();
int replica_add_by_dn (const char *dn);
int replica_delete_by_dn (const char *dn);
int replica_is_being_configured (const char *dn);
const CSN * _get_deletion_csn(Slapi_Entry *e);
int legacy_consumer_init_referrals (Replica *r);
void consumer5_set_mapping_tree_state_for_replica(const Replica *r, RUV *supplierRuv);
Object *replica_get_for_backend (const char *be_name);
void replica_set_purge_delay (Replica *r, PRUint32 purge_delay);
void replica_set_tombstone_reap_interval (Replica *r, long interval);
void replica_update_ruv_consumer (Replica *r, RUV *supplier_ruv);
void replica_set_ruv_dirty (Replica *r);
void replica_write_ruv (Replica *r);
/* The functions below handles the state flag */
/* Current internal state flags */
/* The replica can be busy and not other flag, 
 * it means that the protocol has ended, but the work is not done yet.
 * It happens on total protocol, the end protocol has been received, 
 * and the thread waits for import to finish
 */
#define REPLICA_IN_USE	1 /* The replica is busy */
#define REPLICA_INCREMENTAL_IN_PROGRESS 2 /* Set only between start and stop inc */
#define REPLICA_TOTAL_IN_PROGRESS 4 /* Set only between start and stop total */
#define REPLICA_AGREEMENTS_DISABLED 8 /* Replica is offline */
#define REPLICA_TOTAL_EXCL_SEND 16 /* The server is either sending or receiving
                                      the total update.  Introducing it if SEND
                                      is active, RECV should back off. And
                                      vice versa.  But SEND can coexist. */
#define REPLICA_TOTAL_EXCL_RECV 32 /* ditto */

PRBool replica_is_state_flag_set(Replica *r, PRInt32 flag);
void replica_set_state_flag (Replica *r, PRUint32 flag, PRBool clear); 
void replica_set_tombstone_reap_stop(Replica *r, PRBool val);
void replica_enable_replication (Replica *r);
void replica_disable_replication (Replica *r, Object *r_obj);
int replica_start_agreement(Replica *r, Repl_Agmt *ra);
int windows_replica_start_agreement(Replica *r, Repl_Agmt *ra);

CSN* replica_generate_next_csn ( Slapi_PBlock *pb, const CSN *basecsn );
int replica_get_attr ( Slapi_PBlock *pb, const char *type, void *value );

/* mapping tree extensions manipulation */
void multimaster_mtnode_extension_init ();
void multimaster_mtnode_extension_destroy ();
void multimaster_mtnode_construct_replicas ();

void multimaster_be_state_change (void *handle, char *be_name, int old_be_state, int new_be_state);

/* In repl5_replica_config.c */
int replica_config_init();
void replica_config_destroy ();
int get_replica_type(Replica *r);

/* replutil.c */
LDAPControl* create_managedsait_control ();
LDAPControl* create_backend_control(Slapi_DN *sdn);
void repl_set_mtn_state_and_referrals(const Slapi_DN *sdn, const char *mtn_state,
									  const RUV *ruv, char **ruv_referrals,
									  char **other_referrals);
void repl_set_repl_plugin_path(const char *path);

/* repl5_updatedn_list.c */
typedef void *ReplicaUpdateDNList;
typedef int (*FNEnumDN)(Slapi_DN *dn, void *arg);
ReplicaUpdateDNList replica_updatedn_list_new(const Slapi_Entry *entry);
void replica_updatedn_list_free(ReplicaUpdateDNList list);
void replica_updatedn_list_replace(ReplicaUpdateDNList list, const Slapi_ValueSet *vs);
void replica_updatedn_list_delete(ReplicaUpdateDNList list, const Slapi_ValueSet *vs);
void replica_updatedn_list_add(ReplicaUpdateDNList list, const Slapi_ValueSet *vs);
PRBool replica_updatedn_list_ismember(ReplicaUpdateDNList list, const Slapi_DN *dn);
char *replica_updatedn_list_to_string(ReplicaUpdateDNList list, const char *delimiter);
void replica_updatedn_list_enumerate(ReplicaUpdateDNList list, FNEnumDN fn, void *arg);

/* enabling developper traces for MMR to understand the total/inc protocol state machines */
#ifdef DEV_DEBUG
#define SLAPI_LOG_DEV_DEBUG SLAPI_LOG_FATAL
#define dev_debug(a) slapi_log_error(SLAPI_LOG_DEV_DEBUG, "DEV_DEBUG", "%s\n", a)
#else
#define dev_debug(a)
#endif

void repl5_set_debug_timeout(const char *val);
/* temp hack XXX */
ReplicaId agmt_get_consumerRID(Repl_Agmt *ra);


void windows_init_agreement_from_entry(Repl_Agmt *ra, Slapi_Entry *e);
int windows_handle_modify_agreement(Repl_Agmt *ra, const char *type, Slapi_Entry *e);
void windows_agreement_delete(Repl_Agmt *ra);
Repl_Connection *windows_conn_new(Repl_Agmt *agmt);

/* repl_session_plugin.c */
void repl_session_plugin_init();
void repl_session_plugin_call_agmt_init_cb(Repl_Agmt *ra);
int repl_session_plugin_call_pre_acquire_cb(const Repl_Agmt *ra, int is_total,
        char **data_guid, struct berval **data);
int repl_session_plugin_call_post_acquire_cb(const Repl_Agmt *ra, int is_total,
        const char *data_guid, const struct berval *data);
int repl_session_plugin_call_recv_acquire_cb(const char *repl_area, int is_total,
        const char *data_guid, const struct berval *data);
int repl_session_plugin_call_reply_acquire_cb(const char *repl_area, int is_total,
        char **data_guid, struct berval **data);
void repl_session_plugin_call_destroy_agmt_cb(const Repl_Agmt *ra);

#endif /* _REPL5_H_ */