| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088 |
- /** 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) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* repl5_agmt.c */
- /*
- Support for 5.0-style replication agreements.
- Directory Server 5.0 replication agreements contain information about
- replication consumers that we are supplying.
- This module encapsulates the methods available for adding, deleting,
- modifying, and firing replication agreements.
- Methods:
- agmt_new - Create a new replication agreement, in response to a new
- replication agreement being added over LDAP.
- agmt_delete - Destroy an agreement. It is an error to destroy an
- agreement that has not been stopped.
- agmt_getstatus - get the status of this replication agreement.
- agmt_replicate_now - initiate a replication session asap, even if the
- schedule says we shouldn't.
- agmt_start - start replicating, according to schedule. Starts a new
- thread to handle replication.
- agmt_stop - stop replicating asap and end replication thread.
- agmt_notify_change - notify the replication agreement about a change that
- has been logged. The replication agreement will
- decide if it needs to take some action, e.g. start a
- replication session.
- agmt_initialize_replica - start a complete replica refresh.
- agmt_set_schedule_from_entry - (re)set the schedule associated with this
- replication agreement based on a RA entry's contents.
- agmt_set_credentials_from_entry - (re)set the credentials used to bind
- to the remote replica.
- agmt_set_binddn_from_entry - (re)set the DN used to bind
- to the remote replica.
- agmt_set_bind_method_from_entry - (re)set the bind method used to bind
- to the remote replica (SIMPLE or SSLCLIENTAUTH).
- agmt_set_transportinfo_from_entry - (re)set the transport used to bind
- to the remote replica (SSL or not)
-
- */
- #include "repl5.h"
- #include "repl5_prot_private.h"
- #include "cl5_api.h"
- #include "slapi-plugin.h"
- #define DEFAULT_TIMEOUT 600 /* (seconds) default outbound LDAP connection */
- #define STATUS_LEN 1024
- struct changecounter {
- ReplicaId rid;
- PRUint32 num_replayed;
- PRUint32 num_skipped;
- };
- typedef struct repl5agmt {
- char *hostname; /* remote hostname */
- int port; /* port of remote server */
- PRUint32 transport_flags; /* SSL, TLS, etc. */
- char *binddn; /* DN to bind as */
- struct berval *creds; /* Password, or certificate */
- int bindmethod; /* Bind method - simple, SSL */
- Slapi_DN *replarea; /* DN of replicated area */
- char **frac_attrs; /* list of fractional attributes to be replicated */
- char **frac_attrs_total; /* list of fractional attributes to be replicated for total update protocol */
- Schedule *schedule; /* Scheduling information */
- int auto_initialize; /* 1 = automatically re-initialize replica */
- const Slapi_DN *dn; /* DN of replication agreement entry */
- const Slapi_RDN *rdn; /* RDN of replication agreement entry */
- char *long_name; /* Long name (rdn + host, port) of entry, for logging */
- Repl_Protocol *protocol; /* Protocol object - manages protocol */
- struct changecounter *changecounters[MAX_NUM_OF_MASTERS]; /* changes sent/skipped since server start up */
- int num_changecounters;
- time_t last_update_start_time; /* Local start time of last update session */
- time_t last_update_end_time; /* Local end time of last update session */
- char last_update_status[STATUS_LEN]; /* Status of last update. Format = numeric code <space> textual description */
- PRBool update_in_progress;
- PRBool is_enabled;
- time_t last_init_start_time; /* Local start time of last total init */
- time_t last_init_end_time; /* Local end time of last total init */
- char last_init_status[STATUS_LEN]; /* Status of last total init. Format = numeric code <space> textual description */
- PRLock *lock;
- Object *consumerRUV; /* last RUV received from the consumer - used for changelog purging */
- CSN *consumerSchemaCSN; /* last schema CSN received from the consumer */
- ReplicaId consumerRID; /* indicates if the consumer is the originator of a CSN */
- int tmpConsumerRID; /* Indicates the consumer rid was set from the agmt maxcsn - it should be refreshed */
- long timeout; /* timeout (in seconds) for outbound LDAP connections to remote server */
- PRBool stop_in_progress; /* set by agmt_stop when shutting down */
- long busywaittime; /* time in seconds to wait after getting a REPLICA BUSY from the consumer -
- to allow another supplier to finish sending its updates -
- if set to 0, this means to use the default value if we get a busy
- signal from the consumer */
- long pausetime; /* time in seconds to pause after sending updates -
- to allow another supplier to send its updates -
- should be greater than busywaittime -
- if set to 0, this means do not pause */
- void *priv; /* private data, used for windows-specific agreement data
- for sync agreements or for replication session plug-in
- private data for normal replication agreements */
- char **attrs_to_strip; /* for fractional replication, if a "mod" is empty, strip out these attributes:
- * modifiersname, modifytimestamp, internalModifiersname, internalModifyTimestamp, etc */
- int agreement_type;
- PRUint64 protocol_timeout;
- char *maxcsn; /* agmt max csn */
- Slapi_RWLock *attr_lock; /* RW lock for all the stripped attrs */
- } repl5agmt;
- /* Forward declarations */
- void agmt_delete(void **rap);
- static void update_window_state_change_callback (void *arg, PRBool opened);
- static int get_agmt_status(Slapi_PBlock *pb, Slapi_Entry* e,
- Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
- static int agmt_set_bind_method_no_lock(Repl_Agmt *ra, const Slapi_Entry *e);
- static int agmt_set_transportinfo_no_lock(Repl_Agmt *ra, const Slapi_Entry *e);
- static ReplicaId agmt_maxcsn_get_rid(char *maxcsn);
- /*
- Schema for replication agreement:
- cn
- nsds5ReplicaHost - hostname
- nsds5ReplicaPort - port number
- nsds5ReplicaTransportInfo - "SSL", "startTLS", or may be absent;
- nsds5ReplicaBindDN
- nsds5ReplicaCredentials
- nsds5ReplicaBindMethod - "SIMPLE" or "SSLCLIENTAUTH".
- nsds5ReplicaRoot - Replicated suffix
- nsds5ReplicatedAttributeList - Fractional attrs for incremental update protocol (and total if not separately defined)
- nsds5ReplicatedAttributeListTotal - Fractional attrs for total update protocol
- nsds5ReplicaUpdateSchedule
- nsds5ReplicaTimeout - Outbound repl operations timeout
- nsds50ruv - consumer's RUV
- nsds5ReplicaBusyWaitTime - time to wait after getting a REPLICA BUSY from the consumer
- nsds5ReplicaSessionPauseTime - time to pause after sending updates to allow another supplier to send
- */
- /*
- * Validate an agreement, making sure that it's valid.
- * Return 1 if the agreement is valid, 0 otherwise.
- */
- static int
- agmt_is_valid(Repl_Agmt *ra)
- {
- int return_value = 1; /* assume valid, initially */
- PR_ASSERT(NULL != ra);
- PR_ASSERT(NULL != ra->dn);
- if (NULL == ra->hostname)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
- "is malformed: missing host name.\n", slapi_sdn_get_dn(ra->dn));
- return_value = 0;
- }
- if (ra->port <= 0)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
- "is malformed: invalid port number %d.\n", slapi_sdn_get_dn(ra->dn), ra->port);
- return_value = 0;
- }
- if (ra->timeout < 0)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
- "is malformed: invalid timeout %ld.\n", slapi_sdn_get_dn(ra->dn), ra->timeout);
- return_value = 0;
- }
- if (ra->busywaittime < 0)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
- "is malformed: invalid busy wait time %ld.\n", slapi_sdn_get_dn(ra->dn), ra->busywaittime);
- return_value = 0;
- }
- if (ra->pausetime < 0)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
- "is malformed: invalid pausetime %ld.\n", slapi_sdn_get_dn(ra->dn), ra->pausetime);
- return_value = 0;
- }
- if ((0 == ra->transport_flags) && (BINDMETHOD_SSL_CLIENTAUTH == ra->bindmethod)) {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
- " is malformed: cannot use SSLCLIENTAUTH if using plain LDAP - please "
- "change %s to SSL or TLS before changing %s to use SSLCLIENTAUTH\n",
- slapi_sdn_get_dn(ra->dn), type_nsds5TransportInfo, type_nsds5ReplicaBindMethod);
- return_value = 0;
- }
- /*
- * If we are not using GSSAPI or SSL Client Auth, then a bind dn and password must be present
- */
- if(BINDMETHOD_SASL_GSSAPI != ra->bindmethod && BINDMETHOD_SSL_CLIENTAUTH != ra->bindmethod){
- if(strcmp(ra->binddn,"") == 0 || ra->creds->bv_val == NULL){
- char *auth_mech;
- if(ra->bindmethod == BINDMETHOD_SIMPLE_AUTH){
- auth_mech = "SIMPLE";
- } else if (ra->bindmethod == BINDMETHOD_SASL_DIGEST_MD5){
- auth_mech = "SASL/DIGEST-MD5";
- } else {
- auth_mech = "Unknown";
- }
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
- "is malformed: a bind DN and password must be supplied for authentication "
- "method \"%s\"\n", slapi_sdn_get_dn(ra->dn), auth_mech);
- return_value = 0;
- }
- }
- return return_value;
- }
- Repl_Agmt *
- agmt_new_from_entry(Slapi_Entry *e)
- {
- Repl_Agmt *ra;
- Slapi_Attr *sattr;
- char *tmpstr;
- char **denied_attrs = NULL;
- char *auto_initialize = NULL;
- char *val_nsds5BeginReplicaRefresh = "start";
- ra = (Repl_Agmt *)slapi_ch_calloc(1, sizeof(repl5agmt));
- if ((ra->lock = PR_NewLock()) == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Unable to create new lock "
- "for replication agreement \"%s\" - agreement ignored.\n",
- slapi_entry_get_dn_const(e));
- goto loser;
- }
- if ((ra->attr_lock = slapi_new_rwlock()) == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Unable to create new attr lock "
- "for replication agreement \"%s\" - agreement ignored.\n",
- slapi_entry_get_dn_const(e));
- goto loser;
- }
- /* Find all the stuff we need for the agreement */
- /* To Allow Consumer Initialisation when adding an agreement: */
- /*
- Using 'auto_initialize' member of 'repl5agmt' structure to
- store the effect of 'nsds5BeginReplicaRefresh' attribute's value
- in it.
- */
- auto_initialize = slapi_entry_attr_get_charptr(e, type_nsds5BeginReplicaRefresh);
- if ((auto_initialize != NULL) && (strcasecmp(auto_initialize, val_nsds5BeginReplicaRefresh) == 0))
- {
- ra->auto_initialize = STATE_PERFORMING_TOTAL_UPDATE;
- }
- else
- {
- ra->auto_initialize = STATE_PERFORMING_INCREMENTAL_UPDATE;
- }
- if (auto_initialize)
- {
- slapi_ch_free_string (&auto_initialize);
- }
- /* Host name of remote replica */
- ra->hostname = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaHost);
- /* Port number for remote replica instance */
- ra->port = slapi_entry_attr_get_int(e, type_nsds5ReplicaPort);
- /* SSL, TLS, or other transport stuff */
- ra->transport_flags = 0;
- agmt_set_transportinfo_no_lock(ra, e);
- /* DN to use when binding. May be empty if certain SASL auth is to be used e.g. EXTERNAL GSSAPI. */
- ra->binddn = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaBindDN);
- if (NULL == ra->binddn)
- {
- ra->binddn = slapi_ch_strdup("");
- }
- /* Credentials to use when binding. */
- ra->creds = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
- ra->creds->bv_val = NULL;
- ra->creds->bv_len = 0;
- if (slapi_entry_attr_find(e, type_nsds5ReplicaCredentials, &sattr) == 0)
- {
- Slapi_Value *sval;
- if (slapi_attr_first_value(sattr, &sval) == 0)
- {
- const struct berval *bv = slapi_value_get_berval(sval);
- if (NULL != bv)
- {
- slapi_ber_bvcpy(ra->creds, bv);
- }
- }
- }
- /* How to bind */
- (void)agmt_set_bind_method_no_lock(ra, e);
-
- /* timeout. */
- ra->timeout = DEFAULT_TIMEOUT;
- if (slapi_entry_attr_find(e, type_nsds5ReplicaTimeout, &sattr) == 0)
- {
- Slapi_Value *sval;
- if (slapi_attr_first_value(sattr, &sval) == 0)
- {
- ra->timeout = slapi_value_get_long(sval);
- }
- }
- /* DN of entry at root of replicated area */
- tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaRoot);
- if (NULL != tmpstr)
- {
- ra->replarea = slapi_sdn_new_dn_passin(tmpstr);
- /* If this agmt has its own timeout, grab it, otherwise use the replica's protocol timeout */
- ra->protocol_timeout = slapi_entry_attr_get_int(e, type_replicaProtocolTimeout);
- if(ra->protocol_timeout == 0){
- /* grab the replica protocol timeout */
- Object *replobj = replica_get_replica_from_dn(ra->replarea);
- if(replobj){
- Replica *replica =(Replica*)object_get_data (replobj);
- ra->protocol_timeout = replica_get_protocol_timeout(replica);
- } else {
- ra->protocol_timeout = DEFAULT_PROTOCOL_TIMEOUT;
- }
- }
- }
- /* Replica enabled */
- tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaEnabled);
- if (NULL != tmpstr)
- {
- if(strcasecmp(tmpstr, "off") == 0){
- ra->is_enabled = PR_FALSE;
- } else if(strcasecmp(tmpstr, "on") == 0){
- ra->is_enabled = PR_TRUE;
- } else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Warning invalid value "
- "for nsds5ReplicaEnabled (%s), value must be \"on\" or \"off\". Ignoring "
- "this repl agreement.\n",tmpstr);
- slapi_ch_free_string(&tmpstr);
- goto loser;
- }
- slapi_ch_free_string(&tmpstr);
- } else {
- ra->is_enabled = PR_TRUE;
- }
- /* Replication schedule */
- ra->schedule = schedule_new(update_window_state_change_callback, ra, agmt_get_long_name(ra));
- if (slapi_entry_attr_find(e, type_nsds5ReplicaUpdateSchedule, &sattr) == 0)
- {
- schedule_set(ra->schedule, sattr);
- }
- /* busy wait time - time to wait after getting REPLICA BUSY from consumer */
- ra->busywaittime = slapi_entry_attr_get_long(e, type_nsds5ReplicaBusyWaitTime);
- /* pause time - time to pause after a session has ended */
- ra->pausetime = slapi_entry_attr_get_long(e, type_nsds5ReplicaSessionPauseTime);
- /* consumer's RUV */
- if (slapi_entry_attr_find(e, type_ruvElement, &sattr) == 0)
- {
- RUV *ruv;
- if (ruv_init_from_slapi_attr(sattr, &ruv) == 0)
- {
- ra->consumerRUV = object_new (ruv, (FNFree)ruv_destroy);
- }
- }
- ra->consumerRID = 0;
- /* DN and RDN of the replication agreement entry itself */
- ra->dn = slapi_sdn_dup(slapi_entry_get_sdn((Slapi_Entry *)e));
- ra->rdn = slapi_rdn_new_sdn(ra->dn);
- /* Compute long name */
- {
- const char *agmtname = slapi_rdn_get_rdn(ra->rdn);
- char hostname[128];
- char *dot;
- strncpy(hostname, ra->hostname ? ra->hostname : "(unknown)", sizeof(hostname));
- hostname[sizeof(hostname)-1] = '\0';
- dot = strchr(hostname, '.');
- if (dot) {
- *dot = '\0';
- }
- ra->long_name = slapi_ch_smprintf("agmt=\"%s\" (%s:%d)", agmtname, hostname, ra->port);
- }
- /* DBDB: review this code */
- if (slapi_entry_attr_hasvalue(e, "objectclass", "nsDSWindowsReplicationAgreement"))
- {
- ra->agreement_type = REPLICA_TYPE_WINDOWS;
- windows_init_agreement_from_entry(ra,e);
- }
- else
- {
- ra->agreement_type = REPLICA_TYPE_MULTIMASTER;
- repl_session_plugin_call_agmt_init_cb(ra);
- }
-
- /* Initialize status information */
- ra->last_update_start_time = 0UL;
- ra->last_update_end_time = 0UL;
- ra->num_changecounters = 0;
- ra->last_update_status[0] = '\0';
- ra->update_in_progress = PR_FALSE;
- ra->stop_in_progress = PR_FALSE;
- ra->last_init_end_time = 0UL;
- ra->last_init_start_time = 0UL;
- ra->last_init_status[0] = '\0';
-
- /* Fractional attributes */
- slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeList, &sattr);
- /* New set of excluded attributes */
- /* Note: even if sattrs is empty, we have to call this func since there
- * could be a default excluded attr list in cn=plugin default config */
- if (agmt_set_replicated_attributes_from_attr(ra, sattr) != 0)
- {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "agmtlist_add_callback: failed to parse "
- "replicated attributes for agreement %s\n",
- agmt_get_long_name(ra));
- }
- /* Check that there are no verboten attributes in the exclude list */
- denied_attrs = agmt_validate_replicated_attributes(ra, 0 /* incremental */);
- if (denied_attrs)
- {
- /* Report the error to the client */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "WARNING: Attempt to exclude illegal attributes "
- "from a fractional agreement\n");
- /* Free the list */
- slapi_ch_array_free(denied_attrs);
- goto loser;
- }
- /* Total update fractional attributes */
- slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeListTotal, &sattr);
- if (sattr && agmt_set_replicated_attributes_total_from_attr(ra, sattr) != 0)
- {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "agmtlist_add_callback: failed to parse total "
- "update replicated attributes for agreement %s\n",
- agmt_get_long_name(ra));
- }
- /* Check that there are no verboten attributes in the exclude list */
- denied_attrs = agmt_validate_replicated_attributes(ra, 1 /* total */);
- if (denied_attrs)
- {
- /* Report the error to the client */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "WARNING: Attempt to exclude illegal attributes "
- "from a fractional agreement for total update protocol\n");
- /* Free the list */
- slapi_ch_array_free(denied_attrs);
- goto loser;
- }
- /*
- * Extract the attributes to strip for "empty" mods
- */
- ra->attrs_to_strip = NULL;
- tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaStripAttrs);
- if (NULL != tmpstr)
- {
- ra->attrs_to_strip = slapi_str2charray_ext(tmpstr, " ", 0);
- slapi_ch_free_string(&tmpstr);
- }
- if (!agmt_is_valid(ra))
- {
- goto loser;
- }
- /* Now that the agreement is done, just check if changelog is configured */
- if (cl5GetState() != CL5_STATE_OPEN) {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "WARNING: "
- "Replication agreement added but there is no changelog configured. "
- "No change will be replicated until a changelog is configured.\n");
- }
-
- /*
- * Establish a callback for this agreement's entry, so we can
- * adorn it with status information when read.
- */
- slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, slapi_sdn_get_ndn(ra->dn),
- LDAP_SCOPE_BASE, "(objectclass=*)", get_agmt_status, ra);
- return ra;
- loser:
- agmt_delete((void **)&ra);
- return NULL;
- }
- Repl_Agmt *
- agmt_new_from_pblock(Slapi_PBlock *pb)
- {
- Slapi_Entry *e;
- slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
- return agmt_new_from_entry(e);
- }
- /*
- This should never be called directly - only should be called
- as a destructor. XXXggood this is not finished
- */
- void
- agmt_delete(void **rap)
- {
- Repl_Agmt *ra;
- Replica *replica = NULL;
- Object *repl_obj = NULL;
- PR_ASSERT(NULL != rap);
- PR_ASSERT(NULL != *rap);
- ra = (Repl_Agmt *)*rap;
- /* do prot_delete first - we may be doing some processing using this
- replication agreement, and prot_delete will make sure the
- processing is complete - then it should be safe to clean up the
- other fields below
- */
- prot_delete(&ra->protocol);
- /*
- * Remove the callback for this agreement's entry
- */
- slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
- slapi_sdn_get_ndn(ra->dn),
- LDAP_SCOPE_BASE, "(objectclass=*)",
- get_agmt_status);
- /*
- * Call the replication session cleanup callback. We
- * need to do this before we free replarea.
- */
- if (ra->agreement_type != REPLICA_TYPE_WINDOWS) {
- repl_session_plugin_call_destroy_agmt_cb(ra);
- }
- slapi_ch_free_string(&ra->hostname);
- slapi_ch_free_string(&ra->binddn);
- slapi_ch_array_free(ra->frac_attrs);
- slapi_ch_array_free(ra->frac_attrs_total);
- if (NULL != ra->creds)
- {
- ber_bvfree(ra->creds);
- }
- if (NULL != ra->replarea)
- {
- /*
- * Get the replica for this agreement from the repl area
- * so we can decrement the agmt count
- */
- repl_obj = replica_get_replica_from_dn(ra->replarea);
- if (repl_obj) {
- replica = (Replica*)object_get_data (repl_obj);
- replica_decr_agmt_count(replica);
- object_release(repl_obj);
- }
- slapi_sdn_free(&ra->replarea);
- }
- if (NULL != ra->consumerRUV)
- {
- object_release (ra->consumerRUV);
- }
- csn_free (&ra->consumerSchemaCSN);
- while ( --(ra->num_changecounters) >= 0 )
- {
- slapi_ch_free((void **)&ra->changecounters[ra->num_changecounters]);
- }
- if (ra->agreement_type == REPLICA_TYPE_WINDOWS)
- {
- windows_agreement_delete(ra);
- }
- if(ra->attrs_to_strip){
- slapi_ch_array_free(ra->attrs_to_strip);
- }
- if(ra->maxcsn){
- slapi_ch_free_string(&ra->maxcsn);
- }
- schedule_destroy(ra->schedule);
- slapi_ch_free_string(&ra->long_name);
- /* free the locks */
- PR_DestroyLock(ra->lock);
- slapi_destroy_rwlock(ra->attr_lock);
- slapi_ch_free((void **)rap);
- }
- /*
- * Allow replication for this replica to begin. Replication will
- * occur at the next scheduled time. Returns 0 on success, -1 on
- * failure.
- */
- int
- agmt_start(Repl_Agmt *ra)
- {
- Repl_Protocol *prot = NULL;
- int protocol_state;
- /* To Allow Consumer Initialisation when adding an agreement: */
- if (ra->auto_initialize == STATE_PERFORMING_TOTAL_UPDATE)
- {
- protocol_state = STATE_PERFORMING_TOTAL_UPDATE;
- }
- else
- {
- protocol_state = STATE_PERFORMING_INCREMENTAL_UPDATE;
- }
- /* First, create a new protocol object */
- if ((prot = prot_new(ra, protocol_state)) == NULL) {
- return -1;
- }
- /* Now it is safe to own the agreement lock */
- PR_Lock(ra->lock);
- /* Check that replication is not already started */
- if (ra->protocol != NULL) {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "replication already started for agreement \"%s\"\n", agmt_get_long_name(ra));
- PR_Unlock(ra->lock);
- prot_free(&prot);
- return 0;
- }
- ra->protocol = prot;
- /* Start the protocol thread */
- prot_start(ra->protocol);
- agmt_set_maxcsn(ra);
- PR_Unlock(ra->lock);
- return 0;
- }
- /*
- * Allow replication for this replica to begin. Replication will
- * occur at the next scheduled time. Returns 0 on success, -1 on
- * failure.
- */
- int
- windows_agmt_start(Repl_Agmt *ra)
- {
- Repl_Protocol *prot = NULL;
- int protocol_state;
- /* To Allow Consumer Initialisation when adding an agreement: */
- if (ra->auto_initialize == STATE_PERFORMING_TOTAL_UPDATE)
- {
- protocol_state = STATE_PERFORMING_TOTAL_UPDATE;
- }
- else
- {
- protocol_state = STATE_PERFORMING_INCREMENTAL_UPDATE;
- }
- /* First, create a new protocol object */
- if ((prot = prot_new(ra, protocol_state)) == NULL) {
- return -1;
- }
- /* Now it is safe to own the agreement lock */
- PR_Lock(ra->lock);
- /* Check that replication is not already started */
- if (ra->protocol != NULL) {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "replication already started for agreement \"%s\"\n", agmt_get_long_name(ra));
- PR_Unlock(ra->lock);
- prot_free(&prot);
- return 0;
- }
- ra->protocol = prot;
- /* Start the protocol thread */
- prot_start(ra->protocol);
- PR_Unlock(ra->lock);
- return 0;
- }
- /*
- Cease replicating to this replica as soon as possible.
- */
- int
- agmt_stop(Repl_Agmt *ra)
- {
- int return_value = 0;
- Repl_Protocol *rp = NULL;
- PR_Lock(ra->lock);
- if (ra->stop_in_progress)
- {
- PR_Unlock(ra->lock);
- return return_value;
- }
- ra->stop_in_progress = PR_TRUE;
- rp = ra->protocol;
- PR_Unlock(ra->lock);
- if (NULL != rp) /* we use this pointer outside the lock - dangerous? */
- {
- prot_stop(rp);
- }
- PR_Lock(ra->lock);
- ra->stop_in_progress = PR_FALSE;
- /* we do not reuse the protocol object so free it */
- prot_free(&ra->protocol);
- PR_Unlock(ra->lock);
- return return_value;
- }
- /*
- Send any pending updates as soon as possible, ignoring any replication
- schedules.
- */
- int
- agmt_replicate_now(Repl_Agmt *ra)
- {
- int return_value = 0;
- return return_value;
- }
- /*
- * Return a copy of the remote replica's hostname.
- */
- char *
- agmt_get_hostname(const Repl_Agmt *ra)
- {
- char *return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = slapi_ch_strdup(ra->hostname);
- PR_Unlock(ra->lock);
- return return_value;
- }
- /*
- * Return the port number of the remote replica's instance.
- */
- int
- agmt_get_port(const Repl_Agmt *ra)
- {
- int return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = ra->port;
- PR_Unlock(ra->lock);
- return return_value;
- }
- /*
- * Return the transport flags for this agreement.
- */
- PRUint32
- agmt_get_transport_flags(const Repl_Agmt *ra)
- {
- unsigned int return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = ra->transport_flags;
- PR_Unlock(ra->lock);
- return return_value;
- }
- /*
- * Return a copy of the bind dn to be used with this
- * agreement (may return NULL if no binddn is required,
- * e.g. SSL client auth.
- */
- char *
- agmt_get_binddn(const Repl_Agmt *ra)
- {
- char *return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = ra->binddn == NULL ? NULL : slapi_ch_strdup(ra->binddn);
- PR_Unlock(ra->lock);
- return return_value;
- }
- /*
- * Return a copy of the credentials.
- */
- struct berval *
- agmt_get_credentials(const Repl_Agmt *ra)
- {
- struct berval *return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
- return_value->bv_val = (char *)slapi_ch_malloc(ra->creds->bv_len + 1);
- return_value->bv_len = ra->creds->bv_len;
- memcpy(return_value->bv_val, ra->creds->bv_val, ra->creds->bv_len);
- return_value->bv_val[return_value->bv_len] = '\0'; /* just in case */
- PR_Unlock(ra->lock);
- return return_value;
- }
- int
- agmt_get_bindmethod(const Repl_Agmt *ra)
- {
- int return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = ra->bindmethod;
- PR_Unlock(ra->lock);
- return return_value;
- }
- /*
- * Return a copy of the dn at the top of the replicated area.
- */
- Slapi_DN *
- agmt_get_replarea(const Repl_Agmt *ra)
- {
- Slapi_DN *return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = slapi_sdn_new();
- slapi_sdn_copy(ra->replarea, return_value);
- PR_Unlock(ra->lock);
- return return_value;
- }
- int
- agmt_is_fractional(const Repl_Agmt *ra)
- {
- int return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = ra->frac_attrs != NULL;
- PR_Unlock(ra->lock);
- return return_value;
- }
- /* Returns a COPY of the attr list, remember to free it */
- char **
- agmt_get_fractional_attrs(const Repl_Agmt *ra)
- {
- char ** return_value = NULL;
- PR_ASSERT(NULL != ra);
- if (NULL == ra->frac_attrs)
- {
- return NULL;
- }
- slapi_rwlock_rdlock(ra->attr_lock);
- return_value = charray_dup(ra->frac_attrs);
- slapi_rwlock_unlock(ra->attr_lock);
- return return_value;
- }
- /* Returns a COPY of the attr list, remember to free it */
- char **
- agmt_get_fractional_attrs_total(const Repl_Agmt *ra)
- {
- char ** return_value = NULL;
- PR_ASSERT(NULL != ra);
- if (NULL == ra->frac_attrs_total)
- {
- return agmt_get_fractional_attrs(ra);
- }
- PR_Lock(ra->lock);
- return_value = charray_dup(ra->frac_attrs_total);
- PR_Unlock(ra->lock);
- return return_value;
- }
- int
- agmt_is_fractional_attr(const Repl_Agmt *ra, const char *attrname)
- {
- int return_value;
- PR_ASSERT(NULL != ra);
- if (NULL == ra->frac_attrs)
- {
- return 0;
- }
- slapi_rwlock_rdlock(ra->attr_lock);
- /* Scan the list looking for a match */
- return_value = charray_inlist(ra->frac_attrs,(char*)attrname);
- slapi_rwlock_unlock(ra->attr_lock);
- return return_value;
- }
- int agmt_is_fractional_attr_total(const Repl_Agmt *ra, const char *attrname)
- {
- int return_value;
- PR_ASSERT(NULL != ra);
- if (NULL == ra->frac_attrs_total)
- {
- return agmt_is_fractional_attr(ra, attrname);
- }
- PR_Lock(ra->lock);
- /* Scan the list looking for a match */
- return_value = charray_inlist(ra->frac_attrs_total,(char*)attrname);
- PR_Unlock(ra->lock);
- return return_value;
- }
- int
- agmt_get_auto_initialize(const Repl_Agmt *ra)
- {
- int return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = ra->auto_initialize;
- PR_Unlock(ra->lock);
- return return_value;
- }
- long
- agmt_get_timeout(const Repl_Agmt *ra)
- {
- long return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = ra->timeout;
- PR_Unlock(ra->lock);
- return return_value;
- }
- long
- agmt_get_busywaittime(const Repl_Agmt *ra)
- {
- long return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = ra->busywaittime;
- PR_Unlock(ra->lock);
- return return_value;
- }
- long
- agmt_get_pausetime(const Repl_Agmt *ra)
- {
- long return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- return_value = ra->pausetime;
- PR_Unlock(ra->lock);
- return return_value;
- }
- /*
- * Warning - reference to the long name of the agreement is returned.
- * The long name of an agreement is the DN of the agreement entry,
- * followed by the host/port for the replica.
- */
- const char *
- agmt_get_long_name(const Repl_Agmt *ra)
- {
- char *return_value = NULL;
- return_value = ra ? ra->long_name : "";
- return return_value;
- }
- /*
- * Warning - reference to dn is returned. However, since the dn of
- * the replication agreement is its name, it won't change during the
- * lifetime of the replication agreement object.
- */
- const Slapi_DN *
- agmt_get_dn_byref(const Repl_Agmt *ra)
- {
- const Slapi_DN *return_value = NULL;
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- return_value = ra->dn;
- }
- return return_value;
- }
- /* Return 1 if name matches the replication Dn, 0 otherwise */
- int
- agmt_matches_name(const Repl_Agmt *ra, const Slapi_DN *name)
- {
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- PR_Lock(ra->lock);
- if (slapi_sdn_compare(name, ra->dn) == 0)
- {
- return_value = 1;
- }
- PR_Unlock(ra->lock);
- }
- return return_value;
- }
- /* Return 1 if name matches the replication area, 0 otherwise */
- int
- agmt_replarea_matches(const Repl_Agmt *ra, const Slapi_DN *name)
- {
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- PR_Lock(ra->lock);
- if (slapi_sdn_compare(name, ra->replarea) == 0)
- {
- return_value = 1;
- }
- PR_Unlock(ra->lock);
- }
- return return_value;
- }
- int
- agmt_schedule_in_window_now(const Repl_Agmt *ra)
- {
- int return_value;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- if (NULL != ra->schedule && schedule_in_window_now(ra->schedule))
- {
- return_value = 1;
- }
- else
- {
- return_value = 0;
- }
- PR_Unlock(ra->lock);
- return return_value;
- }
- /*
- * Set or reset the credentials used to bind to the remote replica.
- *
- * Returns 0 if credentials set, or -1 if an error occurred.
- */
- int
- agmt_set_credentials_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- Slapi_Attr *sattr = NULL;
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- slapi_entry_attr_find(e, type_nsds5ReplicaCredentials, &sattr);
- PR_Lock(ra->lock);
- slapi_ber_bvdone(ra->creds);
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- const struct berval *bv = slapi_value_get_berval(sval);
- slapi_ber_bvcpy(ra->creds, bv);
- }
- }
- /* If no credentials set, set to zero-length string */
- ra->creds->bv_val = NULL == ra->creds->bv_val ? slapi_ch_strdup("") : ra->creds->bv_val;
- PR_Unlock(ra->lock);
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- return return_value;
- }
-
- /*
- * Set or reset the DN used to bind to the remote replica.
- *
- * Returns 0 if DN set, or -1 if an error occurred.
- */
- int
- agmt_set_binddn_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- Slapi_Attr *sattr = NULL;
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- slapi_entry_attr_find(e, type_nsds5ReplicaBindDN, &sattr);
- PR_Lock(ra->lock);
- slapi_ch_free((void **)&ra->binddn);
- ra->binddn = NULL;
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- const char *val = slapi_value_get_string(sval);
- ra->binddn = slapi_ch_strdup(val);
- }
- }
- /* If no BindDN set, set to zero-length string */
- if (ra->binddn == NULL) {
- ra->binddn = slapi_ch_strdup("");
- }
- PR_Unlock(ra->lock);
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- return return_value;
- }
- /*
- * Reset the port number of the remote replica.
- *
- * Returns 0 if port set, or -1 if an error occurred.
- */
- int
- agmt_set_port_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- Slapi_Attr *sattr = NULL;
- int return_value = -1;
- PR_ASSERT(NULL != ra);
- slapi_entry_attr_find(e, type_nsds5ReplicaPort, &sattr);
- PR_Lock(ra->lock);
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- ra->port = slapi_value_get_int(sval);
- return_value = 0;
- }
- }
- PR_Unlock(ra->lock);
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- return return_value;
- }
- static int
- agmt_parse_excluded_attrs_filter(const char *attr_string, size_t *offset)
- {
- char *filterstring = "(objectclass=*) ";
- size_t filterstringlen = strlen(filterstring);
- int retval = 0;
- if (strncmp(attr_string + *offset,filterstring,filterstringlen) == 0)
- {
- (*offset) += filterstringlen;
- } else
- {
- retval = -1;
- }
- return retval;
- }
- static int
- agmt_parse_excluded_attrs_exclude(const char *attr_string, size_t *offset)
- {
- char *excludestring = "$ EXCLUDE ";
- size_t excludestringlen = strlen(excludestring);
- int retval = 0;
- if (strncmp(attr_string + *offset,excludestring,excludestringlen) == 0)
- {
- (*offset) += excludestringlen;
- } else
- {
- retval = -1;
- }
- return retval;
- }
- static int
- agmt_parse_excluded_attrs_next(const char *attr_string, size_t *offset, char*** attrs)
- {
- int retval = 0;
- char *beginstr = ((char*) attr_string) + *offset;
- char *tmpstr = NULL;
- size_t stringlen = 0;
- char c = 0;
- /* Find the end of the current attribute name, if one is present */
- while (1)
- {
- c = *(beginstr + stringlen);
- if ('\0' == c || ' ' == c)
- {
- break;
- }
- stringlen++;
- }
- if (0 != stringlen)
- {
- tmpstr = slapi_ch_malloc(stringlen + 1);
- strncpy(tmpstr,beginstr,stringlen);
- tmpstr[stringlen] = '\0';
- if (charray_inlist(*attrs, tmpstr)) /* tmpstr is already in attrs */
- {
- slapi_ch_free_string(&tmpstr);
- }
- else
- {
- charray_add(attrs,tmpstr);
- }
- (*offset) += stringlen;
- /* Skip a delimiting space */
- if (c == ' ')
- {
- (*offset)++;
- }
- } else
- {
- retval = -1;
- }
- return retval;
- }
- /* It looks like this:
- * nsDS5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE jpegPhoto telephoneNumber
- * This function could be called multiple times: to set excluded attrs in the
- * plugin default config and to set the ones in the replica agreement.
- * The excluded attrs from replica agreement are added to the ones from
- * default config. (Therefore, *attrs should not be initialized in this
- * function.)
- */
- static int
- agmt_parse_excluded_attrs_config_attr(const char *attr_string, char ***attrs)
- {
- int retval = 0;
- size_t offset = 0;
- char **new_attrs = NULL;
- /* First parse and skip the filter */
- retval = agmt_parse_excluded_attrs_filter(attr_string, &offset);
- if (retval)
- {
- goto error;
- }
- /* Now look for the 'EXCLUDE' keyword */
- retval = agmt_parse_excluded_attrs_exclude(attr_string, &offset);
- if (retval)
- {
- goto error;
- }
- /* Finally walk the list of attrs, storing in our chararray */
- while (!retval)
- {
- retval = agmt_parse_excluded_attrs_next(attr_string, &offset, &new_attrs);
- }
- /* If we got to here, we can't have an error */
- retval = 0;
- if (new_attrs)
- {
- charray_merge_nodup(attrs, new_attrs, 1);
- slapi_ch_array_free(new_attrs);
- }
- error:
- return retval;
- }
- /*
- * _agmt_set_default_fractional_attrs
- * helper function to set nsds5ReplicatedAttributeList value (from cn=plugin
- * default config,cn=config) to frac_attrs in Repl_Agmt.
- * nsds5ReplicatedAttributeList set in each agreement is added to the
- * default list set in this function.
- */
- static int
- _agmt_set_default_fractional_attrs(Repl_Agmt *ra)
- {
- Slapi_PBlock *newpb = NULL;
- Slapi_Entry **entries = NULL;
- int rc = LDAP_SUCCESS;
- char *attrs[2];
- attrs[0] = (char *)type_nsds5ReplicatedAttributeList;
- attrs[1] = NULL;
- newpb = slapi_pblock_new();
- slapi_search_internal_set_pb(newpb,
- SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN */
- LDAP_SCOPE_BASE,
- "(objectclass=*)",
- attrs, /* Attrs */
- 0, /* AttrOnly */
- NULL, /* Controls */
- NULL, /* UniqueID */
- repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
- 0);
- slapi_search_internal_pb(newpb);
- slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- ra->frac_attrs = NULL;
- if (LDAP_SUCCESS == rc && entries && *entries) /* default config entry exists */
- {
- Slapi_Attr *attr;
- Slapi_Value *sval = NULL;
- if (0 == slapi_entry_attr_find(*entries,
- type_nsds5ReplicatedAttributeList, &attr))
- {
- int i;
- const char *val = NULL;
- for (i = slapi_attr_first_value(attr, &sval);
- i >= 0; i = slapi_attr_next_value(attr, i, &sval)) {
- val = slapi_value_get_string(sval);
- rc = agmt_parse_excluded_attrs_config_attr(val,
- &(ra->frac_attrs));
- if (0 != rc) {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_agmt_set_default_fractional_attrs: failed to "
- "parse default config (%s) attribute %s value: %s\n",
- SLAPI_PLUGIN_DEFAULT_CONFIG,
- type_nsds5ReplicatedAttributeList, val);
- }
- }
- }
- }
- slapi_free_search_results_internal(newpb);
- slapi_pblock_destroy(newpb);
- return rc;
- }
- /*
- * Set or reset the set of replicated attributes.
- *
- * Returns 0 if DN set, or -1 if an error occurred.
- */
- int
- agmt_set_replicated_attributes_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- Slapi_Attr *sattr = NULL;
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeList, &sattr);
- slapi_rwlock_wrlock(ra->attr_lock);
- if (ra->frac_attrs)
- {
- slapi_ch_array_free(ra->frac_attrs);
- ra->frac_attrs = NULL;
- }
- _agmt_set_default_fractional_attrs(ra);
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- const char *val = slapi_value_get_string(sval);
- return_value = agmt_parse_excluded_attrs_config_attr(val,&(ra->frac_attrs));
- }
- }
- slapi_rwlock_unlock(ra->attr_lock);
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- return return_value;
- }
- /*
- * Set or reset the set of total update replicated attributes.
- *
- * Returns 0 if DN set, or -1 if an error occurred.
- */
- int
- agmt_set_replicated_attributes_total_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- Slapi_Attr *sattr = NULL;
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeListTotal, &sattr);
- PR_Lock(ra->lock);
- if (ra->frac_attrs_total)
- {
- slapi_ch_array_free(ra->frac_attrs_total);
- ra->frac_attrs_total = NULL;
- }
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- const char *val = slapi_value_get_string(sval);
- return_value = agmt_parse_excluded_attrs_config_attr(val,&(ra->frac_attrs_total));
- }
- }
- PR_Unlock(ra->lock);
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- return return_value;
- }
- /*
- * Set or reset the set of replicated attributes.
- *
- * Returns 0 if DN set, or -1 if an error occurred.
- */
- int
- agmt_set_replicated_attributes_from_attr(Repl_Agmt *ra, Slapi_Attr *sattr)
- {
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- slapi_rwlock_wrlock(ra->attr_lock);
- if (ra->frac_attrs)
- {
- slapi_ch_array_free(ra->frac_attrs);
- ra->frac_attrs = NULL;
- }
- _agmt_set_default_fractional_attrs(ra);
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- const char *val = slapi_value_get_string(sval);
- return_value = agmt_parse_excluded_attrs_config_attr(val,&(ra->frac_attrs));
- }
- }
- slapi_rwlock_unlock(ra->attr_lock);
- return return_value;
- }
- /*
- * Set or reset the set of total update replicated attributes.
- *
- * Returns 0 if DN set, or -1 if an error occurred.
- */
- int
- agmt_set_replicated_attributes_total_from_attr(Repl_Agmt *ra, Slapi_Attr *sattr)
- {
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- if (ra->frac_attrs_total)
- {
- slapi_ch_array_free(ra->frac_attrs_total);
- ra->frac_attrs_total = NULL;
- }
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- const char *val = slapi_value_get_string(sval);
- return_value = agmt_parse_excluded_attrs_config_attr(val,&(ra->frac_attrs_total));
- }
- }
- PR_Unlock(ra->lock);
- return return_value;
- }
- char **
- agmt_validate_replicated_attributes(Repl_Agmt *ra, int total)
- {
-
- static char* verbotten_attrs[] = {
- "nsuniqueid",
- "modifiersname",
- "lastmodifiedtime",
- "dc", "o", "ou", "cn", "objectclass",
- NULL
- };
- char **retval = NULL;
- char **frac_attrs = NULL;
- /* If checking for total update, use the total attr list
- * if it exists. If oen is not set, use the incremental
- * attr list. */
- if (total && ra->frac_attrs_total)
- {
- frac_attrs = ra->frac_attrs_total;
- }
- else
- {
- frac_attrs = ra->frac_attrs;
- }
- /* Iterate over the frac attrs */
- if (frac_attrs)
- {
- char *this_attr = NULL;
- int i = 0;
- for (i = 0; (this_attr = frac_attrs[i]); i++)
- {
- if (charray_inlist(verbotten_attrs,this_attr)) {
- int k = 0;
- charray_add(&retval,this_attr);
- /* Remove this attr from the list */
- for (k = i; frac_attrs[k] ; k++)
- {
- frac_attrs[k] = frac_attrs[k+1];
- }
- i--;
- }
- }
- }
- return retval;
- }
- /*
- * Set or reset the bind method used to bind to the remote replica.
- *
- * Returns 0 if bind method set, or -1 if an error occurred.
- */
- static int
- agmt_set_bind_method_no_lock(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- char *tmpstr = NULL;
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaBindMethod);
- if (NULL == tmpstr || strcasecmp(tmpstr, "SIMPLE") == 0)
- {
- ra->bindmethod = BINDMETHOD_SIMPLE_AUTH;
- }
- else if (strcasecmp(tmpstr, "SSLCLIENTAUTH") == 0)
- {
- ra->bindmethod = BINDMETHOD_SSL_CLIENTAUTH;
- }
- else if (strcasecmp(tmpstr, "SASL/GSSAPI") == 0)
- {
- ra->bindmethod = BINDMETHOD_SASL_GSSAPI;
- }
- else if (strcasecmp(tmpstr, "SASL/DIGEST-MD5") == 0)
- {
- ra->bindmethod = BINDMETHOD_SASL_DIGEST_MD5;
- }
- else
- {
- ra->bindmethod = BINDMETHOD_SIMPLE_AUTH;
- }
- slapi_ch_free((void **)&tmpstr);
- return return_value;
- }
- int
- agmt_set_bind_method_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- if (ra->stop_in_progress)
- {
- PR_Unlock(ra->lock);
- return return_value;
- }
- return_value = agmt_set_bind_method_no_lock(ra, e);
- PR_Unlock(ra->lock);
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- return return_value;
- }
- /*
- * Set or reset the transport used to bind to the remote replica.
- *
- * Returns 0 if transport set, or -1 if an error occurred.
- */
- static int
- agmt_set_transportinfo_no_lock(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- char *tmpstr;
- int rc = 0;
-
- tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5TransportInfo);
- if (!tmpstr || !strcasecmp(tmpstr, "LDAP")) {
- ra->transport_flags = 0;
- } else if (strcasecmp(tmpstr, "SSL") == 0) {
- ra->transport_flags = TRANSPORT_FLAG_SSL;
- } else if (strcasecmp(tmpstr, "TLS") == 0) {
- ra->transport_flags = TRANSPORT_FLAG_TLS;
- }
- /* else do nothing - invalid value is a no-op */
- slapi_ch_free_string(&tmpstr);
- return (rc);
- }
- int
- agmt_set_transportinfo_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- if (ra->stop_in_progress)
- {
- PR_Unlock(ra->lock);
- return return_value;
- }
- return_value = agmt_set_transportinfo_no_lock(ra, e);
- PR_Unlock(ra->lock);
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- return return_value;
- }
-
-
- /*
- * Set or reset the replication schedule. Notify the protocol handler
- * that a change has been made.
- *
- * Returns 0 if schedule was set or -1 if an error occurred.
- */
- int
- agmt_set_schedule_from_entry( Repl_Agmt *ra, const Slapi_Entry *e )
- {
- Slapi_Attr *sattr;
- int return_value = 0;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- if (ra->stop_in_progress)
- {
- PR_Unlock(ra->lock);
- return return_value;
- }
- PR_Unlock(ra->lock);
- if (slapi_entry_attr_find(e, type_nsds5ReplicaUpdateSchedule, &sattr) != 0)
- {
- sattr = NULL; /* no schedule ==> delete any existing one */
- }
- /* make it so */
- return_value = schedule_set(ra->schedule, sattr);
- if ( 0 == return_value ) {
- /* schedule set OK -- spread the news */
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- }
- return return_value;
- }
- /*
- * Set or reset the timeout used to bind to the remote replica.
- *
- * Returns 0 if timeout set, or -1 if an error occurred.
- */
- int
- agmt_set_timeout_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- Slapi_Attr *sattr = NULL;
- int return_value = -1;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- if (ra->stop_in_progress)
- {
- PR_Unlock(ra->lock);
- return return_value;
- }
- slapi_entry_attr_find(e, type_nsds5ReplicaTimeout, &sattr);
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- long tmpval = slapi_value_get_long(sval);
- if (tmpval >= 0) {
- ra->timeout = tmpval;
- return_value = 0; /* success! */
- }
- }
- }
- PR_Unlock(ra->lock);
- if (return_value == 0)
- {
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- }
- return return_value;
- }
- int
- agmt_set_timeout(Repl_Agmt *ra, long timeout)
- {
- PR_Lock(ra->lock);
- if (ra->stop_in_progress){
- PR_Unlock(ra->lock);
- return -1;
- }
- ra->timeout = timeout;
- PR_Unlock(ra->lock);
- return 0;
- }
- /*
- * Set or reset the busywaittime
- *
- * Returns 0 if busywaittime set, or -1 if an error occurred.
- */
- int
- agmt_set_busywaittime_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- Slapi_Attr *sattr = NULL;
- int return_value = -1;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- if (ra->stop_in_progress)
- {
- PR_Unlock(ra->lock);
- return return_value;
- }
- slapi_entry_attr_find(e, type_nsds5ReplicaBusyWaitTime, &sattr);
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- long tmpval = slapi_value_get_long(sval);
- if (tmpval >= 0) {
- ra->busywaittime = tmpval;
- return_value = 0; /* success! */
- }
- }
- }
- PR_Unlock(ra->lock);
- if (return_value == 0)
- {
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- }
- return return_value;
- }
- /*
- * Set or reset the pausetime
- *
- * Returns 0 if pausetime set, or -1 if an error occurred.
- */
- int
- agmt_set_pausetime_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
- {
- Slapi_Attr *sattr = NULL;
- int return_value = -1;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- if (ra->stop_in_progress)
- {
- PR_Unlock(ra->lock);
- return return_value;
- }
- slapi_entry_attr_find(e, type_nsds5ReplicaSessionPauseTime, &sattr);
- if (NULL != sattr)
- {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(sattr, &sval);
- if (NULL != sval)
- {
- long tmpval = slapi_value_get_long(sval);
- if (tmpval >= 0) {
- ra->pausetime = tmpval;
- return_value = 0; /* success! */
- }
- }
- }
- PR_Unlock(ra->lock);
- if (return_value == 0)
- {
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- }
- return return_value;
- }
- /* XXXggood - also make this pass an arg that tells if there was
- * an update to a priority attribute */
- void
- agmt_notify_change(Repl_Agmt *agmt, Slapi_PBlock *pb)
- {
- if (NULL != pb)
- {
- /* Is the entry within our replicated area? */
- Slapi_DN *target_sdn = NULL;
- int change_is_relevant = 0;
- PR_ASSERT(NULL != agmt);
- PR_Lock(agmt->lock);
- if (agmt->stop_in_progress)
- {
- PR_Unlock(agmt->lock);
- return;
- }
- slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn);
- if (NULL == target_sdn) {
- PR_Unlock(agmt->lock);
- return;
- }
- if (slapi_sdn_issuffix(target_sdn, agmt->replarea))
- {
- /*
- * Yep, it's in our replicated area. Is this a fractional
- * replication agreement?
- */
- if (NULL != agmt->frac_attrs)
- {
- /*
- * Yep, it's fractional. See if the change should be
- * tossed because it doesn't affect any of the replicated
- * attributes.
- */
- int optype;
- int affects_non_fractional_attribute = 0;
- slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &optype);
- if (SLAPI_OPERATION_MODIFY == optype)
- {
- LDAPMod **mods;
- int i, j;
- slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
- slapi_rwlock_rdlock(agmt->attr_lock);
- for (i = 0; !affects_non_fractional_attribute && NULL != agmt->frac_attrs[i]; i++)
- {
- for (j = 0; !affects_non_fractional_attribute && NULL != mods[j]; j++)
- {
- if (!slapi_attr_types_equivalent(agmt->frac_attrs[i],
- mods[j]->mod_type))
- {
- affects_non_fractional_attribute = 1;
- }
- }
- }
- slapi_rwlock_unlock(agmt->attr_lock);
- }
- else
- {
- /*
- * Add, delete, and modrdn always cause some sort of
- * operation replay, even if agreement is fractional.
- */
- affects_non_fractional_attribute = 1;
- }
- if (affects_non_fractional_attribute)
- {
- change_is_relevant = 1;
- }
- }
- else
- {
- /* Not a fractional agreement */
- change_is_relevant = 1;
- }
- }
- PR_Unlock(agmt->lock);
- if (change_is_relevant)
- {
- /* Notify the protocol that a change has occurred */
- prot_notify_update(agmt->protocol);
- }
- }
- }
- int
- agmt_is_50_mm_protocol(const Repl_Agmt *agmt)
- {
- return 1; /* XXXggood could support > 1 protocol */
- }
- int
- agmt_initialize_replica(const Repl_Agmt *agmt)
- {
- PR_ASSERT(NULL != agmt);
- PR_Lock(agmt->lock);
- if (agmt->stop_in_progress)
- {
- PR_Unlock(agmt->lock);
- return 0;
- }
- PR_Unlock(agmt->lock);
- /* Call prot_initialize_replica only if the suffix is enabled (agmt->protocol != NULL) */
- if (NULL != agmt->protocol) {
- prot_initialize_replica(agmt->protocol);
- }
- else {
- /* agmt->protocol == NULL --> Suffix is disabled */
- return -1;
- }
- return 0;
- }
- /* delete nsds5BeginReplicaRefresh attribute to indicate to the clients
- that replica initialization have completed */
- void
- agmt_replica_init_done (const Repl_Agmt *agmt)
- {
- int rc;
- Slapi_PBlock *pb = slapi_pblock_new ();
- LDAPMod *mods [2];
- LDAPMod mod;
- mods[0] = &mod;
- mods[1] = NULL;
- mod.mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
- mod.mod_type = (char*)type_nsds5ReplicaInitialize;
- mod.mod_bvalues = NULL;
-
- slapi_modify_internal_set_pb_ext(pb, agmt->dn, mods, NULL/* controls */,
- NULL/* uniqueid */, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0/* flags */);
- slapi_modify_internal_pb (pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmt_replica_init_done: "
- "failed to remove (%s) attribute from (%s) entry; LDAP error - %d\n",
- type_nsds5ReplicaInitialize, slapi_sdn_get_ndn (agmt->dn), rc);
- }
- slapi_pblock_destroy (pb);
- }
- /* Agreement object is acquired on behalf of the caller.
- The caller is responsible for releasing the object
- when it is no longer used */
- Object*
- agmt_get_consumer_ruv (Repl_Agmt *ra)
- {
- Object *rt = NULL;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- if (ra->consumerRUV)
- {
- object_acquire (ra->consumerRUV);
- rt = ra->consumerRUV;
- }
- PR_Unlock(ra->lock);
- return rt;
- }
- int
- agmt_set_consumer_ruv (Repl_Agmt *ra, RUV *ruv)
- {
- if (ra == NULL || ruv == NULL)
- {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmt_set_consumer_ruv: invalid argument"
- " agmt - %p, ruv - %p\n", ra, ruv);
- return -1;
- }
- PR_Lock(ra->lock);
-
- if (ra->consumerRUV)
- {
- object_release (ra->consumerRUV);
- }
- ra->consumerRUV = object_new (ruv_dup (ruv), (FNFree)ruv_destroy);
- PR_Unlock(ra->lock);
- return 0;
- }
- void
- agmt_update_consumer_ruv (Repl_Agmt *ra)
- {
- int rc;
- RUV *ruv;
- Slapi_Mod smod;
- Slapi_Mod smod_last_modified;
- Slapi_PBlock *pb;
- LDAPMod *mods[3];
- PR_ASSERT (ra);
- PR_Lock(ra->lock);
- if (ra->consumerRUV)
- {
- ruv = (RUV*) object_get_data (ra->consumerRUV);
- PR_ASSERT (ruv);
- ruv_to_smod(ruv, &smod);
- ruv_last_modified_to_smod(ruv, &smod_last_modified);
- /* it is ok to release the lock here because we are done with the agreement data.
- we have to do it before issuing the modify operation because it causes
- agmtlist_notify_all to be called which uses the same lock - hence the deadlock */
- PR_Unlock(ra->lock);
- pb = slapi_pblock_new ();
- mods[0] = (LDAPMod *)slapi_mod_get_ldapmod_byref(&smod);
- mods[1] = (LDAPMod *)slapi_mod_get_ldapmod_byref(&smod_last_modified);
- mods[2] = NULL;
- slapi_modify_internal_set_pb_ext (pb, ra->dn, mods, NULL, NULL,
- repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
- slapi_modify_internal_pb (pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "%s: agmt_update_consumer_ruv: "
- "failed to update consumer's RUV; LDAP error - %d\n",
- ra->long_name, rc);
- }
- slapi_mod_done (&smod);
- slapi_mod_done (&smod_last_modified);
- slapi_pblock_destroy (pb);
- }
- else
- PR_Unlock(ra->lock);
- }
- CSN*
- agmt_get_consumer_schema_csn (Repl_Agmt *ra)
- {
- CSN *rt;
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- rt = ra->consumerSchemaCSN;
- PR_Unlock(ra->lock);
- return rt;
- }
- void
- agmt_set_consumer_schema_csn (Repl_Agmt *ra, CSN *csn)
- {
- PR_ASSERT(NULL != ra);
- PR_Lock(ra->lock);
- csn_free(&ra->consumerSchemaCSN);
- ra->consumerSchemaCSN = csn;
- PR_Unlock(ra->lock);
- }
- void
- agmt_set_last_update_start (Repl_Agmt *ra, time_t start_time)
- {
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- ra->last_update_start_time = start_time;
- ra->last_update_end_time = 0UL;
- }
- }
- void
- agmt_set_last_update_end (Repl_Agmt *ra, time_t end_time)
- {
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- ra->last_update_end_time = end_time;
- }
- }
- void
- agmt_set_last_init_start (Repl_Agmt *ra, time_t start_time)
- {
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- ra->last_init_start_time = start_time;
- ra->last_init_end_time = 0UL;
- }
- }
- void
- agmt_set_last_init_end (Repl_Agmt *ra, time_t end_time)
- {
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- ra->last_init_end_time = end_time;
- }
- }
- void
- agmt_set_last_update_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *message)
- {
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- if (replrc == NSDS50_REPL_UPTODATE)
- {
- /* no session started, no status update */
- }
- else if (ldaprc != LDAP_SUCCESS)
- {
- char *replmsg = NULL;
- if ( replrc ) {
- replmsg = protocol_response2string(replrc);
- /* Do not mix the unknown replication error with the known ldap one */
- if ( strcasecmp(replmsg, "unknown error") == 0 ) {
- replmsg = NULL;
- }
- }
- PR_snprintf(ra->last_update_status, STATUS_LEN, "%d %s%sLDAP error: %s%s%s",
- ldaprc, message?message:"",message?"":" - ",
- slapi_err2string(ldaprc), replmsg ? " - " : "", replmsg ? replmsg : "");
- }
- /* ldaprc == LDAP_SUCCESS */
- else if (replrc != 0)
- {
- if (replrc == NSDS50_REPL_REPLICA_BUSY)
- {
- PR_snprintf(ra->last_update_status, STATUS_LEN,
- "%d Can't acquire busy replica", replrc );
- }
- else if (replrc == NSDS50_REPL_REPLICA_RELEASE_SUCCEEDED)
- {
- PR_snprintf(ra->last_update_status, STATUS_LEN, "%d %s",
- ldaprc, "Replication session successful");
- }
- else if (replrc == NSDS50_REPL_DISABLED)
- {
- PR_snprintf(ra->last_update_status, STATUS_LEN, "%d Incremental update aborted: "
- "Replication agreement for %s\n can not be updated while the replica is disabled.\n"
- "(If the suffix is disabled you must enable it then restart the server for replication to take place).",
- replrc, ra->long_name ? ra->long_name : "a replica");
- /* Log into the errors log, as "ra->long_name" is not accessible from the caller */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "Incremental update aborted: Replication agreement for \"%s\" "
- "can not be updated while the replica is disabled\n", ra->long_name ? ra->long_name : "a replica");
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "(If the suffix is disabled you must enable it then restart the server for replication to take place).\n");
- }
- else
- {
- PR_snprintf(ra->last_update_status, STATUS_LEN,
- "%d Replication error acquiring replica: %s%s%s",
- replrc, protocol_response2string(replrc),
- message?" - ":"",message?message:"");
- }
- }
- else if (message != NULL) /* replrc == NSDS50_REPL_REPLICA_READY == 0 */
- {
- PR_snprintf(ra->last_update_status, STATUS_LEN,
- "%d Replica acquired successfully: %s",
- ldaprc, message);
- }
- else
- { /* agmt_set_last_update_status(0,0,NULL) to reset agmt */
- PR_snprintf(ra->last_update_status, STATUS_LEN, "%d", ldaprc);
- }
- }
- }
- void
- agmt_set_last_init_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *message)
- {
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- if (ldaprc != LDAP_SUCCESS)
- {
- char *replmsg = NULL;
- if ( replrc ) {
- replmsg = protocol_response2string(replrc);
- /* Do not mix the unknown replication error with the known ldap one */
- if ( strcasecmp(replmsg, "unknown error") == 0 ) {
- replmsg = NULL;
- }
- }
- PR_snprintf(ra->last_init_status, STATUS_LEN, "%d %s%sLDAP error: %s%s%s",
- ldaprc, message?message:"",message?"":" - ",
- slapi_err2string(ldaprc), replmsg ? " - " : "", replmsg ? replmsg : "");
- }
- /* ldaprc == LDAP_SUCCESS */
- else if (replrc != 0)
- {
- if (replrc == NSDS50_REPL_REPLICA_RELEASE_SUCCEEDED)
- {
- PR_snprintf(ra->last_init_status, STATUS_LEN, "%d %s",
- ldaprc, "Replication session successful");
- }
- else if (replrc == NSDS50_REPL_DISABLED)
- {
- if(agmt_is_enabled(ra)){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Total update aborted: "
- "Replication agreement for \"%s\" can not be updated while the suffix is disabled.\n"
- "You must enable it then restart the server for replication to take place).\n",
- ra->long_name ? ra->long_name : "a replica");
- PR_snprintf(ra->last_init_status, STATUS_LEN, "%d Total update aborted: "
- "Replication agreement for \"%s\" can not be updated while the suffix is disabled.\n"
- "You must enable it then restart the server for replication to take place).",
- replrc, ra->long_name ? ra->long_name : "a replica");
- } else {
- /* You do not need to restart the server after enabling the agreement */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Total update aborted: "
- "Replication agreement for \"%s\" can not be updated while the agreement is disabled\n",
- ra->long_name ? ra->long_name : "a replica");
- PR_snprintf(ra->last_init_status, STATUS_LEN, "%d Total update aborted: "
- "Replication agreement for \"%s\" can not be updated while the agreement is disabled.",
- replrc, ra->long_name ? ra->long_name : "a replica");
- }
- }
- else
- {
- PR_snprintf(ra->last_init_status, STATUS_LEN,
- "%d Replication error acquiring replica: %s%s%s",
- replrc, protocol_response2string(replrc),
- message?" - ":"",message?message:"");
- }
- }
- else if (message != NULL) /* replrc == NSDS50_REPL_REPLICA_READY == 0 */
- {
- PR_snprintf(ra->last_init_status, STATUS_LEN,
- "%d %s",
- ldaprc, message);
- }
- else
- { /* agmt_set_last_init_status(0,0,NULL) to reset agmt */
- PR_snprintf(ra->last_init_status, STATUS_LEN, "%d", ldaprc);
- }
- }
- }
- void
- agmt_set_update_in_progress (Repl_Agmt *ra, PRBool in_progress)
- {
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- ra->update_in_progress = in_progress;
- }
- }
- PRBool
- agmt_get_update_in_progress (const Repl_Agmt *ra)
- {
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- return ra->update_in_progress;
- }
- return PR_FALSE;
- }
- void
- agmt_inc_last_update_changecount (Repl_Agmt *ra, ReplicaId rid, int skipped)
- {
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- int i;
- for ( i = 0; i < ra->num_changecounters; i++ )
- {
- if ( ra->changecounters[i]->rid == rid )
- break;
- }
- if ( i < ra->num_changecounters )
- {
- if ( skipped )
- ra->changecounters[i]->num_skipped ++;
- else
- ra->changecounters[i]->num_replayed ++;
- }
- else
- {
- ra->num_changecounters ++;
- ra->changecounters[i] = (struct changecounter*) slapi_ch_calloc(1, sizeof(struct changecounter));
- ra->changecounters[i]->rid = rid;
- if ( skipped )
- ra->changecounters[i]->num_skipped = 1;
- else
- ra->changecounters[i]->num_replayed = 1;
- }
- }
- }
- void
- agmt_get_changecount_string (Repl_Agmt *ra, char *buf, int bufsize)
- {
- char tmp_buf[32]; /* 5 digit RID, 10 digit each replayed and skipped */
- int i;
- int buflen = 0;
- *buf = '\0';
- if (NULL != ra)
- {
- for ( i = 0; i < ra->num_changecounters; i++ )
- {
- PR_snprintf (tmp_buf, sizeof(tmp_buf), "%u:%u/%u ",
- ra->changecounters[i]->rid,
- ra->changecounters[i]->num_replayed,
- ra->changecounters[i]->num_skipped);
- PR_snprintf (buf+buflen, bufsize-buflen, "%s", tmp_buf);
- buflen += strlen (tmp_buf);
- }
- }
- }
- static int
- get_agmt_status(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
- int *returncode, char *returntext, void *arg)
- {
- char *time_tmp = NULL;
- char changecount_string[BUFSIZ];
- Repl_Agmt *ra = (Repl_Agmt *)arg;
- PR_ASSERT(NULL != ra);
- if (NULL != ra)
- {
- PRBool reapActive = PR_FALSE;
- Slapi_DN *replarea_sdn = NULL;
- Object *repl_obj = NULL;
- replarea_sdn = agmt_get_replarea(ra);
- repl_obj = replica_get_replica_from_dn(replarea_sdn);
- slapi_sdn_free(&replarea_sdn);
- if (repl_obj) {
- Replica *replica = (Replica*)object_get_data (repl_obj);
- reapActive = replica_get_tombstone_reap_active(replica);
- object_release(repl_obj);
- }
- slapi_entry_attr_set_int(e, "nsds5replicaReapActive", (int)reapActive);
- /* these values persist in the dse.ldif file, so we delete them
- here to avoid multi valued attributes */
- slapi_entry_attr_delete(e, "nsds5replicaLastUpdateStart");
- slapi_entry_attr_delete(e, "nsds5replicaLastUpdateEnd");
- slapi_entry_attr_delete(e, "nsds5replicaChangesSentSinceStartup");
- slapi_entry_attr_delete(e, "nsds5replicaLastUpdateStatus");
- slapi_entry_attr_delete(e, "nsds5replicaUpdateInProgress");
- slapi_entry_attr_delete(e, "nsds5replicaLastInitStart");
- slapi_entry_attr_delete(e, "nsds5replicaLastInitStatus");
- slapi_entry_attr_delete(e, "nsds5replicaLastInitEnd");
- /* now, add the real values (singly) */
- if (ra->last_update_start_time == 0)
- {
- slapi_entry_add_string(e, "nsds5replicaLastUpdateStart", "0");
- }
- else
- {
- time_tmp = format_genTime(ra->last_update_start_time);
- slapi_entry_add_string(e, "nsds5replicaLastUpdateStart", time_tmp);
- slapi_ch_free((void **)&time_tmp);
- }
- if (ra->last_update_end_time == 0)
- {
- slapi_entry_add_string(e, "nsds5replicaLastUpdateEnd", "0");
- }
- else
- {
- time_tmp = format_genTime(ra->last_update_end_time);
- slapi_entry_add_string(e, "nsds5replicaLastUpdateEnd", time_tmp);
- slapi_ch_free((void **)&time_tmp);
- }
- agmt_get_changecount_string (ra, changecount_string, sizeof (changecount_string) );
- slapi_entry_add_string(e, "nsds5replicaChangesSentSinceStartup", changecount_string);
- if (ra->last_update_status[0] == '\0')
- {
- slapi_entry_add_string(e, "nsds5replicaLastUpdateStatus", "0 No replication sessions started since server startup");
- }
- else
- {
- slapi_entry_add_string(e, "nsds5replicaLastUpdateStatus", ra->last_update_status);
- }
- slapi_entry_add_string(e, "nsds5replicaUpdateInProgress", ra->update_in_progress ? "TRUE" : "FALSE");
- if (ra->last_init_start_time == 0)
- {
- slapi_entry_add_string(e, "nsds5replicaLastInitStart", "0");
- }
- else
- {
- time_tmp = format_genTime(ra->last_init_start_time);
- slapi_entry_add_string(e, "nsds5replicaLastInitStart", time_tmp);
- slapi_ch_free((void **)&time_tmp);
- }
- if (ra->last_init_end_time == 0)
- {
- slapi_entry_add_string(e, "nsds5replicaLastInitEnd", "0");
- }
- else
- {
- time_tmp = format_genTime(ra->last_init_end_time);
- slapi_entry_add_string(e, "nsds5replicaLastInitEnd", time_tmp);
- slapi_ch_free((void **)&time_tmp);
- }
- if (ra->last_init_status[0] != '\0')
- {
- slapi_entry_add_string(e, "nsds5replicaLastInitStatus", ra->last_init_status);
- }
- }
- return SLAPI_DSE_CALLBACK_OK;
- }
- static void
- update_window_state_change_callback (void *arg, PRBool opened)
- {
- Repl_Agmt *agmt = (Repl_Agmt*)arg;
- PR_ASSERT (agmt);
-
- if (opened)
- {
- prot_notify_window_opened (agmt->protocol);
- }
- else
- {
- prot_notify_window_closed (agmt->protocol);
- }
- }
- ReplicaId
- agmt_get_consumer_rid ( Repl_Agmt *agmt, void *conn )
- {
- if ( agmt->consumerRID <= 0 || agmt->tmpConsumerRID) {
- char *mapping_tree_node = NULL;
- struct berval **bvals = NULL;
- /* This function converts the old style DN to the new one. */
- mapping_tree_node =
- slapi_create_dn_string("cn=replica,cn=\"%s\",cn=mapping tree,cn=config",
- slapi_sdn_get_dn (agmt->replarea) );
- if (NULL == mapping_tree_node) {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "agmt_get_consumer_rid: failed to normalize "
- "replica dn for %s\n",
- slapi_sdn_get_dn (agmt->replarea));
- agmt->consumerRID = 0;
- }
- conn_read_entry_attribute ( conn, mapping_tree_node, "nsDS5ReplicaID", &bvals );
- if ( NULL != bvals && NULL != bvals[0] ) {
- char *ridstr = slapi_ch_malloc( bvals[0]->bv_len + 1 );
- memcpy ( ridstr, bvals[0]->bv_val, bvals[0]->bv_len );
- ridstr[bvals[0]->bv_len] = '\0';
- agmt->consumerRID = atoi (ridstr);
- slapi_ch_free ( (void**) &ridstr );
- ber_bvecfree ( bvals );
- }
- slapi_ch_free_string(&mapping_tree_node);
- }
- agmt->tmpConsumerRID = 0;
- return agmt->consumerRID;
- }
- int
- get_agmt_agreement_type( Repl_Agmt *agmt)
- {
- PR_ASSERT (agmt);
- return agmt->agreement_type;
- }
- void* agmt_get_priv (const Repl_Agmt *agmt)
- {
- PR_ASSERT (agmt);
- return agmt->priv;
- }
- void agmt_set_priv (Repl_Agmt *agmt, void* priv)
- {
- PR_ASSERT (agmt);
- agmt->priv = priv;
- }
- ReplicaId agmt_get_consumerRID(Repl_Agmt *ra)
- {
- return ra->consumerRID;
- }
- void* agmt_get_connection(Repl_Agmt *ra)
- {
- if(ra->protocol){
- return (void *)prot_get_connection(ra->protocol);
- } else {
- return NULL;
- }
- }
- Repl_Protocol *
- agmt_get_protocol(Repl_Agmt *ra)
- {
- if(ra){
- return ra->protocol;
- } else {
- return NULL;
- }
- }
- int
- agmt_has_protocol(Repl_Agmt *agmt)
- {
- if (agmt) {
- return NULL != agmt->protocol;
- }
- return 0;
- }
- PRBool
- agmt_is_enabled(Repl_Agmt *ra)
- {
- PRBool state;
- PR_Lock(ra->lock);
- state = ra->is_enabled;
- PR_Unlock(ra->lock);
- return state;
- }
- int
- agmt_set_enabled_from_entry(Repl_Agmt *ra, Slapi_Entry *e, char *returntext){
- char *attr_val = NULL;
- int rc = 0;
- if(ra == NULL){
- return -1;
- }
- PR_Lock(ra->lock);
- attr_val = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaEnabled);
- if(attr_val){
- PRBool is_enabled = PR_TRUE;
- if(strcasecmp(attr_val,"off") == 0){
- is_enabled = PR_FALSE;
- } else if(strcasecmp(attr_val,"on") == 0){
- is_enabled = PR_TRUE;
- } else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmt_set_enabled_from_entry: invalid "
- "value for nsds5ReplicaEnabled (%s), the value must be \"on\" or \"off\".\n", attr_val);
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid value for nsds5ReplicaEnabled, "
- "the value must be \"on\" or \"off\".\n");
- slapi_ch_free_string(&attr_val);
- PR_Unlock(ra->lock);
- return -1;
- }
- slapi_ch_free_string(&attr_val);
- if(is_enabled){
- if(!ra->is_enabled){
- ra->is_enabled = PR_TRUE;
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmt_set_enabled_from_entry: "
- "agreement is now enabled (%s)\n",ra->long_name);
- PR_Unlock(ra->lock);
- agmt_start(ra);
- return rc;
- }
- } else {
- if(ra->is_enabled){
- ra->is_enabled = PR_FALSE;
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmt_set_enabled_from_entry: "
- "agreement is now disabled (%s)\n",ra->long_name);
- PR_Unlock(ra->lock);
- agmt_stop(ra);
- agmt_update_consumer_ruv(ra);
- agmt_set_last_update_status(ra,0,0,"agreement disabled");
- return rc;
- }
- }
- } else {
- rc = -1;
- }
- PR_Unlock(ra->lock);
- return rc;
- }
- char **
- agmt_get_attrs_to_strip(Repl_Agmt *ra)
- {
- if(ra){
- return ra->attrs_to_strip;
- } else {
- return NULL;
- }
- }
- int
- agmt_set_attrs_to_strip(Repl_Agmt *ra, Slapi_Entry *e)
- {
- char *tmpstr = NULL;
- PR_Lock(ra->lock);
- tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaStripAttrs);
- if (NULL != tmpstr){
- if(ra->attrs_to_strip){
- slapi_ch_array_free(ra->attrs_to_strip);
- }
- ra->attrs_to_strip = slapi_str2charray_ext(tmpstr, " ", 0);
- PR_Unlock(ra->lock);
- prot_notify_agmt_changed(ra->protocol, ra->long_name);
- slapi_ch_free_string(&tmpstr);
- return 0;
- }
- PR_Unlock(ra->lock);
- return -1;
- }
- /* this is called whenever an update (total/incremental)
- is completed */
- void
- agmt_update_done(Repl_Agmt *agmt, int is_total)
- {
- /* we could do a lot of stuff here - consolidate all of the other stuff that gets
- done at the end of an update - setting status, times, etc.
- but for now, all we want to do is "flush" any pending changes made
- during the update into the proper structures so they are in place for the
- next run
- */
- if(get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
- windows_update_done(agmt, is_total);
- }
- }
- int
- agmt_get_protocol_timeout(Repl_Agmt *agmt)
- {
- return (int)agmt->protocol_timeout;
- }
- /*
- * Check if all the mods are being removed by fractional/stripped attributes
- */
- void
- agmt_update_maxcsn(Replica *r, Slapi_DN *sdn, int op, LDAPMod **mods, CSN *csn)
- {
- Object *agmt_obj;
- Repl_Agmt *agmt;
- ReplicaId rid = replica_get_rid(r);
- int mod_count = 0, excluded_count = 0;
- agmt_obj = agmtlist_get_first_agreement_for_replica (r);
- if(agmt_obj == NULL){ /* no agreements */
- return;
- }
- while (agmt_obj){
- agmt = (Repl_Agmt*)object_get_data (agmt_obj);
- if(!agmt_is_enabled(agmt) ||
- !slapi_sdn_issuffix(sdn, agmt->replarea) ||
- get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS)
- {
- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
- continue;
- }
- if(op == SLAPI_OPERATION_MODIFY)
- {
- slapi_rwlock_rdlock(agmt->attr_lock);
- for ( excluded_count = 0, mod_count = 0; NULL != mods[ mod_count ]; mod_count++){
- if(charray_inlist(agmt->frac_attrs, mods[mod_count]->mod_type)){
- excluded_count++;
- } else if(charray_inlist(agmt->attrs_to_strip, mods[mod_count]->mod_type)){
- excluded_count++;
- }
- }
- slapi_rwlock_unlock(agmt->attr_lock);
- }
- if(excluded_count == 0 || excluded_count != mod_count){
- /*
- * This update has not been completely stripped down, update
- * the agmt maxcsn - if the update did not originate from the consumer.
- */
- char maxcsn[CSN_STRSIZE];
- ReplicaId oprid = csn_get_replicaid(csn);
- csn_as_string(csn, PR_FALSE, maxcsn);
- PR_Lock(agmt->lock);
- if(!agmt->consumerRID){
- /*
- * If the RID is 0, that means this is the first update since the
- * agmt was created. Since we have not contacted the consumer yet,
- * we don't know what its rid is. The consumerRID will be set once
- * this update is sent, but until then we don't know it. So for now
- * temporarily mark it as "unavailable".
- */
- slapi_ch_free_string(&agmt->maxcsn);
- agmt->maxcsn = slapi_ch_smprintf("%s;%s;%s;%d;unavailable", slapi_sdn_get_dn(agmt->replarea),
- slapi_rdn_get_value_by_ref(slapi_rdn_get_rdn(agmt->rdn)), agmt->hostname, agmt->port);
- } else if(rid == oprid){
- slapi_ch_free_string(&agmt->maxcsn);
- agmt->maxcsn = slapi_ch_smprintf("%s;%s;%s;%d;%d;%s", slapi_sdn_get_dn(agmt->replarea),
- slapi_rdn_get_value_by_ref(slapi_rdn_get_rdn(agmt->rdn)), agmt->hostname,
- agmt->port, agmt->consumerRID, maxcsn);
- }
- PR_Unlock(agmt->lock);
- }
- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
- }
- }
- /*
- * Returns the in-memory agmt maxcsn's
- */
- void
- add_agmt_maxcsns(Slapi_Entry *e, Replica *r)
- {
- Object *agmt_obj;
- Repl_Agmt *agmt;
- agmt_obj = agmtlist_get_first_agreement_for_replica (r);
- if(agmt_obj == NULL){ /* no agreements */
- return;
- }
- while (agmt_obj){
- agmt = (Repl_Agmt*)object_get_data (agmt_obj);
- if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
- continue;
- }
- PR_Lock(agmt->lock);
- if(agmt->maxcsn){
- slapi_entry_add_string(e, type_agmtMaxCSN, agmt->maxcsn);
- }
- PR_Unlock(agmt->lock);
- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
- }
- }
- /*
- * Create a smod of all the agmt maxcsns to add to the tombstone entry
- */
- int
- agmt_maxcsn_to_smod (Replica *r, Slapi_Mod *smod)
- {
- Object *agmt_obj;
- Repl_Agmt *agmt;
- int rc = 1;
- agmt_obj = agmtlist_get_first_agreement_for_replica (r);
- if(agmt_obj == NULL){ /* no agreements */
- return rc;
- }
- slapi_mod_init (smod, replica_get_agmt_count(r) + 1);
- slapi_mod_set_type (smod, type_agmtMaxCSN);
- slapi_mod_set_operation (smod, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
- while (agmt_obj){
- struct berval val;
- agmt = (Repl_Agmt*)object_get_data (agmt_obj);
- if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
- continue;
- }
- PR_Lock(agmt->lock);
- if(agmt->maxcsn == NULL){
- PR_Unlock(agmt->lock);
- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
- continue;
- }
- val.bv_val = agmt->maxcsn;
- val.bv_len = strlen(val.bv_val);
- slapi_mod_add_value(smod, &val);
- PR_Unlock(agmt->lock);
- rc = 0;
- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
- }
- return rc;
- }
- /*
- * Called when we start a repl agmt
- */
- void
- agmt_set_maxcsn(Repl_Agmt *ra)
- {
- Slapi_PBlock *pb = NULL;
- Slapi_Entry **entries = NULL;
- Replica *r = NULL;
- Object *repl_obj;
- const Slapi_DN *tombstone_sdn = NULL;
- char *attrs[2];
- int rc;
- /* read ruv state from the ruv tombstone entry */
- pb = slapi_pblock_new();
- if (!pb) {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmt_set_maxcsn: Out of memory\n");
- goto done;
- }
- repl_obj = prot_get_replica_object(ra->protocol);
- if(repl_obj){
- r = (Replica *)object_get_data(repl_obj);
- tombstone_sdn = replica_get_root(r);
- }
- ra->maxcsn = NULL;
- attrs[0] = (char*)type_agmtMaxCSN;
- attrs[1] = NULL;
- slapi_search_internal_set_pb_ext(
- pb,
- (Slapi_DN *)tombstone_sdn,
- LDAP_SCOPE_BASE,
- "objectclass=*",
- attrs,
- 0, /* attrsonly */
- NULL, /* controls */
- RUV_STORAGE_ENTRY_UNIQUEID,
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION),
- OP_FLAG_REPLICATED); /* flags */
- slapi_search_internal_pb (pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if (rc == LDAP_SUCCESS){
- Replica *r;
- Object *repl_obj;
- char **maxcsns;
- int i;
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- if (NULL == entries || NULL == entries[0]){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "agmt_set_maxcsn: replica ruv tombstone entry for "
- "replica %s not found\n",
- slapi_sdn_get_dn(ra->replarea));
- goto done;
- }
- maxcsns = slapi_entry_attr_get_charray(entries[0], type_agmtMaxCSN);
- repl_obj = prot_get_replica_object(ra->protocol);
- if(repl_obj && maxcsns){
- r = (Replica *)object_get_data(repl_obj);
- if(r){
- /*
- * Loop over all the agmt maxcsns and find ours
- */
- for(i = 0; maxcsns[i]; i++){
- char buf[BUFSIZ];
- char unavail_buf[BUFSIZ];
- PR_snprintf(buf,BUFSIZ,"%s;%s;%s;%d;",slapi_sdn_get_dn(ra->replarea),
- slapi_rdn_get_value_by_ref(slapi_rdn_get_rdn(ra->rdn)),
- ra->hostname, ra->port);
- PR_snprintf(unavail_buf, BUFSIZ,"%s;%s;%s;%d;unavailable", slapi_sdn_get_dn(ra->replarea),
- slapi_rdn_get_value_by_ref(slapi_rdn_get_rdn(ra->rdn)),
- ra->hostname, ra->port);
- if(strstr(maxcsns[i], buf) || strstr(maxcsns[i], unavail_buf)){
- ra->maxcsn = slapi_ch_strdup(maxcsns[i]);
- ra->consumerRID = agmt_maxcsn_get_rid(maxcsns[i]);
- ra->tmpConsumerRID = 1;
- break;
- }
- }
- }
- }
- slapi_ch_array_free(maxcsns);
- }
- done:
- if (NULL != pb){
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy (pb);
- }
- }
- /*
- * Parse out the consumer replicaID from the agmt maxcsn
- *
- * "repl area;agmt rdn;hostname;port;consumer rid;maxcsn"
- */
- static ReplicaId
- agmt_maxcsn_get_rid(char *maxcsn)
- {
- ReplicaId rid = 0;
- char *token = NULL;
- char *iter;
- char *value = slapi_ch_strdup(maxcsn);
- token = ldap_utf8strtok_r(value, ";", &iter); /* repl area */
- token = ldap_utf8strtok_r(iter, ";", &iter); /* agmt rdn */
- token = ldap_utf8strtok_r(iter, ";", &iter); /* host */
- token = ldap_utf8strtok_r(iter, ";", &iter); /* port */
- token = ldap_utf8strtok_r(iter, ";", &iter); /* rid */
- if(strcmp(token, "Unavailable")){
- rid = atoi(token);
- }
- slapi_ch_free_string(&value);
- return rid;
- }
- /*
- * Agmt being deleted, remove the agmt maxcsn from the local ruv.
- */
- void
- agmt_remove_maxcsn(Repl_Agmt *ra)
- {
- Slapi_PBlock *pb = NULL;
- Slapi_PBlock *modpb = NULL;
- Slapi_Entry **entries = NULL;
- Replica *r = NULL;
- Object *repl_obj;
- const Slapi_DN *tombstone_sdn = NULL;
- char *attrs[2];
- int rc;
- pb = slapi_pblock_new();
- if (!pb) {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmt_set_maxcsn: Out of memory\n");
- goto done;
- }
- ra->maxcsn = NULL;
- repl_obj = prot_get_replica_object(ra->protocol);
- if(repl_obj){
- r = (Replica *)object_get_data(repl_obj);
- tombstone_sdn = replica_get_root(r);
- } else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmt_set_maxcsn: Failed to get repl object.\n");
- goto done;
- }
- attrs[0] = (char*)type_agmtMaxCSN;
- attrs[1] = NULL;
- slapi_search_internal_set_pb_ext(
- pb,
- (Slapi_DN *)tombstone_sdn,
- LDAP_SCOPE_BASE,
- "objectclass=*",
- attrs,
- 0, /* attrsonly */
- NULL, /* controls */
- RUV_STORAGE_ENTRY_UNIQUEID,
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION),
- OP_FLAG_REPLICATED); /* flags */
- slapi_search_internal_pb (pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if (rc == LDAP_SUCCESS){
- /*
- * Ok we have the db tombstone entry, start looking through the agmt maxcsns
- * for a match to this replica agmt.
- */
- Slapi_Mod smod;
- LDAPMod *mods[2];
- char **maxcsns = NULL;
- int i;
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- if (NULL == entries || NULL == entries[0]){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "agmt_set_maxcsn: replica ruv tombstone entry for "
- "replica %s not found\n", slapi_sdn_get_dn(ra->replarea));
- goto done;
- }
- maxcsns = slapi_entry_attr_get_charray(entries[0], type_agmtMaxCSN);
- repl_obj = prot_get_replica_object(ra->protocol);
- if(repl_obj && maxcsns){
- r = (Replica *)object_get_data(repl_obj);
- if(r){
- /*
- * Loop over all the agmt maxcsns and find ours...
- */
- for(i = 0; maxcsns[i]; i++){
- char buf[BUFSIZ];
- char unavail_buf[BUFSIZ];
- struct berval val;
- PR_snprintf(buf, BUFSIZ,"%s;%s;%s;%d;",slapi_sdn_get_dn(ra->replarea),
- slapi_rdn_get_value_by_ref(slapi_rdn_get_rdn(ra->rdn)),
- ra->hostname, ra->port);
- PR_snprintf(unavail_buf, BUFSIZ, "%s;%s;%s;%d;unavailable",
- slapi_sdn_get_dn(ra->replarea),
- slapi_rdn_get_value_by_ref(slapi_rdn_get_rdn(ra->rdn)),
- ra->hostname, ra->port);
- if(strstr(maxcsns[i], buf) || strstr(maxcsns[i], unavail_buf)){
- /*
- * We found the matching agmt maxcsn, now remove agmt maxcsn
- * from the tombstone entry.
- */
- val.bv_val = maxcsns[i];
- val.bv_len = strlen(maxcsns[i]);
- slapi_mod_init (&smod, 2);
- slapi_mod_set_type (&smod, type_agmtMaxCSN);
- slapi_mod_set_operation (&smod, LDAP_MOD_DELETE | LDAP_MOD_BVALUES);
- slapi_mod_add_value(&smod, &val);
- mods [0] = smod.mod;
- mods [1] = NULL;
- modpb = slapi_pblock_new();
- slapi_modify_internal_set_pb_ext(
- modpb,
- tombstone_sdn,
- mods,
- NULL, /* controls */
- RUV_STORAGE_ENTRY_UNIQUEID,
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION),
- /* Add OP_FLAG_TOMBSTONE_ENTRY so that this doesn't get logged in the Retro ChangeLog */
- OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP | OP_FLAG_TOMBSTONE_ENTRY |
- OP_FLAG_REPL_RUV );
- slapi_modify_internal_pb(modpb);
- slapi_pblock_get(modpb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if (rc != LDAP_SUCCESS){
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "agmt_set_maxcsn: failed to remove agmt maxcsn (%s), error(%d)\n",maxcsns[i], rc);
- }
- slapi_mod_done(&smod);
- slapi_pblock_destroy(modpb);
- break;
- }
- }
- }
- }
- slapi_ch_array_free(maxcsns);
- }
- done:
- if (NULL != pb){
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy (pb);
- }
- }
|