1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1999-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#ifdef HAVE_SYSTEM_INCLUDE_FILES 13#include <tcl.h> 14#endif 15#include "dbinc/tcl_db.h" 16 17#ifdef CONFIG_TEST 18/* 19 * tcl_RepConfig -- 20 * Call DB_ENV->rep_set_config(). 21 * 22 * PUBLIC: int tcl_RepConfig 23 * PUBLIC: __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *)); 24 */ 25int 26tcl_RepConfig(interp, dbenv, list) 27 Tcl_Interp *interp; /* Interpreter */ 28 DB_ENV *dbenv; /* Environment pointer */ 29 Tcl_Obj *list; /* {which on|off} */ 30{ 31 static const char *confwhich[] = { 32 "bulk", 33 "delayclient", 34 "mgr2sitestrict", 35 "noautoinit", 36 "nowait", 37 NULL 38 }; 39 enum confwhich { 40 REPCONF_BULK, 41 REPCONF_DELAYCLIENT, 42 REPCONF_MGR2SITESTRICT, 43 REPCONF_NOAUTOINIT, 44 REPCONF_NOWAIT 45 }; 46 static const char *confonoff[] = { 47 "off", 48 "on", 49 NULL 50 }; 51 enum confonoff { 52 REPCONF_OFF, 53 REPCONF_ON 54 }; 55 Tcl_Obj **myobjv, *onoff, *which; 56 int myobjc, on, optindex, result, ret; 57 u_int32_t wh; 58 59 result = Tcl_ListObjGetElements(interp, list, &myobjc, &myobjv); 60 which = myobjv[0]; 61 onoff = myobjv[1]; 62 if (result != TCL_OK) 63 return (result); 64 if (Tcl_GetIndexFromObj(interp, which, confwhich, "option", 65 TCL_EXACT, &optindex) != TCL_OK) 66 return (IS_HELP(which)); 67 68 switch ((enum confwhich)optindex) { 69 case REPCONF_NOAUTOINIT: 70 wh = DB_REP_CONF_NOAUTOINIT; 71 break; 72 case REPCONF_BULK: 73 wh = DB_REP_CONF_BULK; 74 break; 75 case REPCONF_DELAYCLIENT: 76 wh = DB_REP_CONF_DELAYCLIENT; 77 break; 78 case REPCONF_MGR2SITESTRICT: 79 wh = DB_REPMGR_CONF_2SITE_STRICT; 80 break; 81 case REPCONF_NOWAIT: 82 wh = DB_REP_CONF_NOWAIT; 83 break; 84 default: 85 return (TCL_ERROR); 86 } 87 if (Tcl_GetIndexFromObj(interp, onoff, confonoff, "option", 88 TCL_EXACT, &optindex) != TCL_OK) 89 return (IS_HELP(onoff)); 90 switch ((enum confonoff)optindex) { 91 case REPCONF_OFF: 92 on = 0; 93 break; 94 case REPCONF_ON: 95 on = 1; 96 break; 97 default: 98 return (TCL_ERROR); 99 } 100 ret = dbenv->rep_set_config(dbenv, wh, on); 101 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 102 "env rep_config")); 103} 104 105/* 106 * tcl_RepGetTwo -- 107 * Call replication getters that return 2 values. 108 * 109 * PUBLIC: int tcl_RepGetTwo 110 * PUBLIC: __P((Tcl_Interp *, DB_ENV *, int)); 111 */ 112int 113tcl_RepGetTwo(interp, dbenv, op) 114 Tcl_Interp *interp; /* Interpreter */ 115 DB_ENV *dbenv; /* Environment pointer */ 116 int op; /* which getter */ 117{ 118 Tcl_Obj *myobjv[2], *res; 119 u_int32_t val1, val2; 120 int myobjc, result, ret; 121 122 ret = 0; 123 val1 = val2 = 0; 124 switch (op) { 125 case DBTCL_GETCLOCK: 126 ret = dbenv->rep_get_clockskew(dbenv, &val1, &val2); 127 break; 128 case DBTCL_GETLIMIT: 129 ret = dbenv->rep_get_limit(dbenv, &val1, &val2); 130 break; 131 case DBTCL_GETREQ: 132 ret = dbenv->rep_get_request(dbenv, &val1, &val2); 133 break; 134 default: 135 return (TCL_ERROR); 136 } 137 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 138 "env rep_get")) == TCL_OK) { 139 myobjc = 2; 140 myobjv[0] = Tcl_NewLongObj((long)val1); 141 myobjv[1] = Tcl_NewLongObj((long)val2); 142 res = Tcl_NewListObj(myobjc, myobjv); 143 Tcl_SetObjResult(interp, res); 144 } 145 return (result); 146} 147 148/* 149 * tcl_RepGetConfig -- 150 * 151 * PUBLIC: int tcl_RepGetConfig 152 * PUBLIC: __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *)); 153 */ 154int 155tcl_RepGetConfig(interp, dbenv, which) 156 Tcl_Interp *interp; /* Interpreter */ 157 DB_ENV *dbenv; /* Environment pointer */ 158 Tcl_Obj *which; /* which flag */ 159{ 160 static const char *confwhich[] = { 161 "bulk", 162 "delayclient", 163 "inmem_files", 164 "lease", 165 "mgr2sitestrict", 166 "noautoinit", 167 "nowait", 168 NULL 169 }; 170 enum confwhich { 171 REPGCONF_BULK, 172 REPGCONF_DELAYCLIENT, 173 REPGCONF_INMEM_FILES, 174 REPGCONF_LEASE, 175 REPGCONF_MGR2SITESTRICT, 176 REPGCONF_NOAUTOINIT, 177 REPGCONF_NOWAIT 178 }; 179 Tcl_Obj *res; 180 int on, optindex, result, ret; 181 u_int32_t wh; 182 183 if (Tcl_GetIndexFromObj(interp, which, confwhich, "option", 184 TCL_EXACT, &optindex) != TCL_OK) 185 return (IS_HELP(which)); 186 187 res = NULL; 188 switch ((enum confwhich)optindex) { 189 case REPGCONF_BULK: 190 wh = DB_REP_CONF_BULK; 191 break; 192 case REPGCONF_DELAYCLIENT: 193 wh = DB_REP_CONF_DELAYCLIENT; 194 break; 195 case REPGCONF_INMEM_FILES: 196 wh = DB_REP_CONF_INMEM; 197 break; 198 case REPGCONF_LEASE: 199 wh = DB_REP_CONF_LEASE; 200 break; 201 case REPGCONF_MGR2SITESTRICT: 202 wh = DB_REPMGR_CONF_2SITE_STRICT; 203 break; 204 case REPGCONF_NOAUTOINIT: 205 wh = DB_REP_CONF_NOAUTOINIT; 206 break; 207 case REPGCONF_NOWAIT: 208 wh = DB_REP_CONF_NOWAIT; 209 break; 210 default: 211 return (TCL_ERROR); 212 } 213 ret = dbenv->rep_get_config(dbenv, wh, &on); 214 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 215 "env rep_config")) == TCL_OK) { 216 res = Tcl_NewIntObj(on); 217 Tcl_SetObjResult(interp, res); 218 } 219 return (result); 220} 221 222/* 223 * tcl_RepGetTimeout -- 224 * Get various replication timeout values. 225 * 226 * PUBLIC: int tcl_RepGetTimeout 227 * PUBLIC: __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *)); 228 */ 229int 230tcl_RepGetTimeout(interp, dbenv, which) 231 Tcl_Interp *interp; /* Interpreter */ 232 DB_ENV *dbenv; /* Environment pointer */ 233 Tcl_Obj *which; /* which flag */ 234{ 235 static const char *towhich[] = { 236 "ack", 237 "checkpoint_delay", 238 "connection_retry", 239 "election", 240 "election_retry", 241 "full_election", 242 "heartbeat_monitor", 243 "heartbeat_send", 244 "lease", 245 NULL 246 }; 247 enum towhich { 248 REPGTO_ACK, 249 REPGTO_CKP, 250 REPGTO_CONN, 251 REPGTO_ELECT, 252 REPGTO_ELECT_RETRY, 253 REPGTO_FULL, 254 REPGTO_HB_MON, 255 REPGTO_HB_SEND, 256 REPGTO_LEASE 257 }; 258 Tcl_Obj *res; 259 int optindex, result, ret, wh; 260 u_int32_t to; 261 262 if (Tcl_GetIndexFromObj(interp, which, towhich, "option", 263 TCL_EXACT, &optindex) != TCL_OK) 264 return (IS_HELP(which)); 265 266 res = NULL; 267 switch ((enum towhich)optindex) { 268 case REPGTO_ACK: 269 wh = DB_REP_ACK_TIMEOUT; 270 break; 271 case REPGTO_CKP: 272 wh = DB_REP_CHECKPOINT_DELAY; 273 break; 274 case REPGTO_CONN: 275 wh = DB_REP_CONNECTION_RETRY; 276 break; 277 case REPGTO_ELECT: 278 wh = DB_REP_ELECTION_TIMEOUT; 279 break; 280 case REPGTO_ELECT_RETRY: 281 wh = DB_REP_ELECTION_RETRY; 282 break; 283 case REPGTO_FULL: 284 wh = DB_REP_FULL_ELECTION_TIMEOUT; 285 break; 286 case REPGTO_HB_MON: 287 wh = DB_REP_HEARTBEAT_MONITOR; 288 break; 289 case REPGTO_HB_SEND: 290 wh = DB_REP_HEARTBEAT_SEND; 291 break; 292 case REPGTO_LEASE: 293 wh = DB_REP_LEASE_TIMEOUT; 294 break; 295 default: 296 return (TCL_ERROR); 297 } 298 ret = dbenv->rep_get_timeout(dbenv, wh, &to); 299 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 300 "env rep_config")) == TCL_OK) { 301 res = Tcl_NewLongObj((long)to); 302 Tcl_SetObjResult(interp, res); 303 } 304 return (result); 305} 306#endif 307 308#ifdef CONFIG_TEST 309/* 310 * tcl_RepElect -- 311 * Call DB_ENV->rep_elect(). 312 * 313 * PUBLIC: int tcl_RepElect 314 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 315 */ 316int 317tcl_RepElect(interp, objc, objv, dbenv) 318 Tcl_Interp *interp; /* Interpreter */ 319 int objc; /* How many arguments? */ 320 Tcl_Obj *CONST objv[]; /* The argument objects */ 321 DB_ENV *dbenv; /* Environment pointer */ 322{ 323 int result, ret; 324 u_int32_t full_timeout, nsites, nvotes, pri, timeout; 325 326 if (objc != 6 && objc != 7) { 327 Tcl_WrongNumArgs(interp, 6, objv, 328 "nsites nvotes pri timeout [full_timeout]"); 329 return (TCL_ERROR); 330 } 331 332 if ((result = _GetUInt32(interp, objv[2], &nsites)) != TCL_OK) 333 return (result); 334 if ((result = _GetUInt32(interp, objv[3], &nvotes)) != TCL_OK) 335 return (result); 336 if ((result = _GetUInt32(interp, objv[4], &pri)) != TCL_OK) 337 return (result); 338 if ((result = _GetUInt32(interp, objv[5], &timeout)) != TCL_OK) 339 return (result); 340 full_timeout = 0; 341 if (objc == 7) 342 if ((result = _GetUInt32(interp, objv[6], &full_timeout)) 343 != TCL_OK) 344 return (result); 345 346 _debug_check(); 347 348 if ((ret = dbenv->rep_set_priority(dbenv, pri)) != 0) 349 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 350 "env rep_elect (rep_set_priority)")); 351 if ((ret = dbenv->rep_set_timeout(dbenv, DB_REP_ELECTION_TIMEOUT, 352 timeout)) != 0) 353 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 354 "env rep_elect (rep_set_timeout)")); 355 356 if (full_timeout != 0 && (ret = dbenv->rep_set_timeout(dbenv, 357 DB_REP_FULL_ELECTION_TIMEOUT, full_timeout)) != 0) 358 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 359 "env rep_elect (rep_set_timeout)")); 360 361 ret = dbenv->rep_elect(dbenv, nsites, nvotes, 0); 362 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_elect")); 363} 364#endif 365 366#ifdef CONFIG_TEST 367/* 368 * tcl_RepFlush -- 369 * Call DB_ENV->rep_flush(). 370 * 371 * PUBLIC: int tcl_RepFlush 372 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 373 */ 374int 375tcl_RepFlush(interp, objc, objv, dbenv) 376 Tcl_Interp *interp; 377 int objc; 378 Tcl_Obj *CONST objv[]; 379 DB_ENV *dbenv; 380{ 381 int ret; 382 383 if (objc != 2) { 384 Tcl_WrongNumArgs(interp, 2, objv, ""); 385 return TCL_ERROR; 386 } 387 388 _debug_check(); 389 ret = dbenv->rep_flush(dbenv); 390 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_flush")); 391} 392#endif 393 394#ifdef CONFIG_TEST 395/* 396 * tcl_RepSync -- 397 * Call DB_ENV->rep_sync(). 398 * 399 * PUBLIC: int tcl_RepSync 400 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 401 */ 402int 403tcl_RepSync(interp, objc, objv, dbenv) 404 Tcl_Interp *interp; 405 int objc; 406 Tcl_Obj *CONST objv[]; 407 DB_ENV *dbenv; 408{ 409 int ret; 410 411 if (objc != 2) { 412 Tcl_WrongNumArgs(interp, 2, objv, ""); 413 return TCL_ERROR; 414 } 415 416 _debug_check(); 417 ret = dbenv->rep_sync(dbenv, 0); 418 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_sync")); 419} 420#endif 421 422#ifdef CONFIG_TEST 423/* 424 * tcl_RepLease -- 425 * Call DB_ENV->rep_set_lease(). 426 * 427 * PUBLIC: int tcl_RepLease __P((Tcl_Interp *, int, Tcl_Obj * CONST *, 428 * PUBLIC: DB_ENV *)); 429 */ 430int 431tcl_RepLease(interp, objc, objv, dbenv) 432 Tcl_Interp *interp; /* Interpreter */ 433 int objc; /* How many arguments? */ 434 Tcl_Obj *CONST objv[]; /* The argument objects */ 435 DB_ENV *dbenv; 436{ 437 u_int32_t clock_fast, clock_slow, nsites, timeout; 438 int result, ret; 439 440 COMPQUIET(clock_fast, 0); 441 COMPQUIET(clock_slow, 0); 442 443 if (objc != 4 && objc != 2) { 444 Tcl_WrongNumArgs(interp, 1, objv, "{nsites timeout fast slow}"); 445 return (TCL_ERROR); 446 } 447 448 if ((result = _GetUInt32(interp, objv[0], &nsites)) != TCL_OK) 449 return (result); 450 if ((result = _GetUInt32(interp, objv[1], &timeout)) != TCL_OK) 451 return (result); 452 if (objc == 4) { 453 if ((result = _GetUInt32(interp, objv[2], &clock_fast)) 454 != TCL_OK) 455 return (result); 456 if ((result = _GetUInt32(interp, objv[3], &clock_slow)) 457 != TCL_OK) 458 return (result); 459 } 460 ret = dbenv->rep_set_nsites(dbenv, nsites); 461 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 462 "rep_set_nsites"); 463 if (result != TCL_OK) 464 return (result); 465 ret = dbenv->rep_set_timeout(dbenv, DB_REP_LEASE_TIMEOUT, 466 (db_timeout_t)timeout); 467 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 468 "rep_set_timeout"); 469 ret = dbenv->rep_set_config(dbenv, DB_REP_CONF_LEASE, 1); 470 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 471 "rep_set_config"); 472 if (result != TCL_OK) 473 return (result); 474 if (objc == 4) 475 ret = dbenv->rep_set_clockskew(dbenv, clock_fast, clock_slow); 476 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 477 "env rep_set_lease")); 478} 479#endif 480 481#ifdef CONFIG_TEST 482/* 483 * tcl_RepInmemFiles -- 484 * Set in-memory replication, which must be done before opening 485 * environment. 486 * 487 * PUBLIC: int tcl_RepInmemFiles __P((Tcl_Interp *, DB_ENV *)); 488 */ 489int 490tcl_RepInmemFiles(interp, dbenv) 491 Tcl_Interp *interp; /* Interpreter */ 492 DB_ENV *dbenv; 493{ 494 int ret; 495 496 ret = dbenv->rep_set_config(dbenv, DB_REP_CONF_INMEM, 1); 497 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 498 "rep_set_config")); 499} 500#endif 501 502#ifdef CONFIG_TEST 503/* 504 * tcl_RepLimit -- 505 * Call DB_ENV->rep_set_limit(). 506 * 507 * PUBLIC: int tcl_RepLimit 508 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 509 */ 510int 511tcl_RepLimit(interp, objc, objv, dbenv) 512 Tcl_Interp *interp; /* Interpreter */ 513 int objc; /* How many arguments? */ 514 Tcl_Obj *CONST objv[]; /* The argument objects */ 515 DB_ENV *dbenv; /* Environment pointer */ 516{ 517 int result, ret; 518 u_int32_t bytes, gbytes; 519 520 if (objc != 4) { 521 Tcl_WrongNumArgs(interp, 4, objv, "gbytes bytes"); 522 return (TCL_ERROR); 523 } 524 525 if ((result = _GetUInt32(interp, objv[2], &gbytes)) != TCL_OK) 526 return (result); 527 if ((result = _GetUInt32(interp, objv[3], &bytes)) != TCL_OK) 528 return (result); 529 530 _debug_check(); 531 if ((ret = dbenv->rep_set_limit(dbenv, gbytes, bytes)) != 0) 532 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 533 "env set_rep_limit")); 534 535 return (_ReturnSetup(interp, 536 ret, DB_RETOK_STD(ret), "env set_rep_limit")); 537} 538#endif 539 540#ifdef CONFIG_TEST 541/* 542 * tcl_RepRequest -- 543 * Call DB_ENV->rep_set_request(). 544 * 545 * PUBLIC: int tcl_RepRequest 546 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 547 */ 548int 549tcl_RepRequest(interp, objc, objv, dbenv) 550 Tcl_Interp *interp; /* Interpreter */ 551 int objc; /* How many arguments? */ 552 Tcl_Obj *CONST objv[]; /* The argument objects */ 553 DB_ENV *dbenv; /* Environment pointer */ 554{ 555 int result, ret; 556 long min, max; 557 558 if (objc != 4) { 559 Tcl_WrongNumArgs(interp, 4, objv, "min max"); 560 return (TCL_ERROR); 561 } 562 563 if ((result = Tcl_GetLongFromObj(interp, objv[2], &min)) != TCL_OK) 564 return (result); 565 if ((result = Tcl_GetLongFromObj(interp, objv[3], &max)) != TCL_OK) 566 return (result); 567 568 _debug_check(); 569 if ((ret = dbenv->rep_set_request(dbenv, (db_timeout_t)min, 570 (db_timeout_t)max)) != 0) 571 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 572 "env rep_request")); 573 574 return (_ReturnSetup(interp, 575 ret, DB_RETOK_STD(ret), "env rep_request")); 576} 577#endif 578 579#ifdef CONFIG_TEST 580/* 581 * tcl_RepNoarchiveTimeout -- 582 * Reset the master update timer, to allow immediate log archiving. 583 * 584 * PUBLIC: int tcl_RepNoarchiveTimeout 585 * PUBLIC: __P((Tcl_Interp *, DB_ENV *)); 586 */ 587int 588tcl_RepNoarchiveTimeout(interp, dbenv) 589 Tcl_Interp *interp; /* Interpreter */ 590 DB_ENV *dbenv; /* Environment pointer */ 591{ 592 ENV *env; 593 REGENV *renv; 594 REGINFO *infop; 595 596 env = dbenv->env; 597 598 _debug_check(); 599 infop = env->reginfo; 600 renv = infop->primary; 601 REP_SYSTEM_LOCK(env); 602 F_CLR(renv, DB_REGENV_REPLOCKED); 603 renv->op_timestamp = 0; 604 REP_SYSTEM_UNLOCK(env); 605 606 return (_ReturnSetup(interp, 607 0, DB_RETOK_STD(0), "env test force noarchive_timeout")); 608} 609#endif 610 611#ifdef CONFIG_TEST 612/* 613 * tcl_RepTransport -- 614 * Call DB_ENV->rep_set_transport(). 615 * 616 * PUBLIC: int tcl_RepTransport __P((Tcl_Interp *, int, Tcl_Obj * CONST *, 617 * PUBLIC: DB_ENV *, DBTCL_INFO *)); 618 * 619 * Note that this normally can/should be achieved as an argument to 620 * berkdb env, but we need to test changing the transport function on 621 * the fly. 622 */ 623int 624tcl_RepTransport(interp, objc, objv, dbenv, ip) 625 Tcl_Interp *interp; /* Interpreter */ 626 int objc; /* How many arguments? */ 627 Tcl_Obj *CONST objv[]; /* The argument objects */ 628 DB_ENV *dbenv; 629 DBTCL_INFO *ip; 630{ 631 int intarg, result, ret; 632 633 if (objc != 2) { 634 Tcl_WrongNumArgs(interp, 2, objv, "{id transport_func"); 635 return (TCL_ERROR); 636 } 637 638 /* 639 * Store the objects containing the machine ID 640 * and the procedure name. We don't need to crack 641 * the send procedure out now, but we do convert the 642 * machine ID to an int, since rep_set_transport needs 643 * it. Even so, it'll be easier later to deal with 644 * the Tcl_Obj *, so we save that, not the int. 645 * 646 * Note that we Tcl_IncrRefCount both objects 647 * independently; Tcl is free to discard the list 648 * that they're bundled into. 649 */ 650 651 /* 652 * Check that the machine ID is an int. Note that 653 * we do want to use GetIntFromObj; the machine 654 * ID is explicitly an int, not a u_int32_t. 655 */ 656 if (ip->i_rep_eid != NULL) { 657 Tcl_DecrRefCount(ip->i_rep_eid); 658 } 659 ip->i_rep_eid = objv[0]; 660 Tcl_IncrRefCount(ip->i_rep_eid); 661 result = Tcl_GetIntFromObj(interp, 662 ip->i_rep_eid, &intarg); 663 if (result != TCL_OK) 664 return (result); 665 666 if (ip->i_rep_send != NULL) { 667 Tcl_DecrRefCount(ip->i_rep_send); 668 } 669 ip->i_rep_send = objv[1]; 670 Tcl_IncrRefCount(ip->i_rep_send); 671 _debug_check(); 672 ret = dbenv->rep_set_transport(dbenv, intarg, tcl_rep_send); 673 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 674 "env rep_transport")); 675} 676#endif 677 678#ifdef CONFIG_TEST 679/* 680 * tcl_RepStart -- 681 * Call DB_ENV->rep_start(). 682 * 683 * PUBLIC: int tcl_RepStart 684 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 685 * 686 * Note that this normally can/should be achieved as an argument to 687 * berkdb env, but we need to test forcible upgrading of clients, which 688 * involves calling this on an open environment handle. 689 */ 690int 691tcl_RepStart(interp, objc, objv, dbenv) 692 Tcl_Interp *interp; /* Interpreter */ 693 int objc; /* How many arguments? */ 694 Tcl_Obj *CONST objv[]; /* The argument objects */ 695 DB_ENV *dbenv; 696{ 697 static const char *tclrpstrt[] = { 698 "-client", 699 "-master", 700 NULL 701 }; 702 enum tclrpstrt { 703 TCL_RPSTRT_CLIENT, 704 TCL_RPSTRT_MASTER 705 }; 706 char *arg; 707 int i, optindex, ret; 708 u_int32_t flag; 709 710 flag = 0; 711 712 if (objc != 3) { 713 Tcl_WrongNumArgs(interp, 3, objv, "[-master/-client]"); 714 return (TCL_ERROR); 715 } 716 717 i = 2; 718 while (i < objc) { 719 if (Tcl_GetIndexFromObj(interp, objv[i], tclrpstrt, 720 "option", TCL_EXACT, &optindex) != TCL_OK) { 721 arg = Tcl_GetStringFromObj(objv[i], NULL); 722 if (arg[0] == '-') 723 return (IS_HELP(objv[i])); 724 else 725 Tcl_ResetResult(interp); 726 break; 727 } 728 i++; 729 switch ((enum tclrpstrt)optindex) { 730 case TCL_RPSTRT_CLIENT: 731 flag = DB_REP_CLIENT; 732 break; 733 case TCL_RPSTRT_MASTER: 734 flag = DB_REP_MASTER; 735 break; 736 } 737 } 738 739 _debug_check(); 740 ret = dbenv->rep_start(dbenv, NULL, flag); 741 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_start")); 742} 743#endif 744 745#ifdef CONFIG_TEST 746/* 747 * tcl_RepProcessMessage -- 748 * Call DB_ENV->rep_process_message(). 749 * 750 * PUBLIC: int tcl_RepProcessMessage 751 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 752 */ 753int 754tcl_RepProcessMessage(interp, objc, objv, dbenv) 755 Tcl_Interp *interp; /* Interpreter */ 756 int objc; /* How many arguments? */ 757 Tcl_Obj *CONST objv[]; /* The argument objects */ 758 DB_ENV *dbenv; /* Environment pointer */ 759{ 760 DBT control, rec; 761 DB_LSN permlsn; 762 Tcl_Obj *lsnlist, *myobjv[2], *res; 763 void *ctmp, *rtmp; 764 char *msg; 765 int eid; 766 int freectl, freerec, myobjc, result, ret; 767 768 if (objc != 5) { 769 Tcl_WrongNumArgs(interp, 5, objv, "id control rec"); 770 return (TCL_ERROR); 771 } 772 freectl = freerec = 0; 773 774 memset(&control, 0, sizeof(control)); 775 memset(&rec, 0, sizeof(rec)); 776 777 if ((result = Tcl_GetIntFromObj(interp, objv[2], &eid)) != TCL_OK) 778 return (result); 779 780 ret = _CopyObjBytes(interp, objv[3], &ctmp, 781 &control.size, &freectl); 782 if (ret != 0) { 783 result = _ReturnSetup(interp, ret, 784 DB_RETOK_REPPMSG(ret), "rep_proc_msg"); 785 return (result); 786 } 787 control.data = ctmp; 788 ret = _CopyObjBytes(interp, objv[4], &rtmp, 789 &rec.size, &freerec); 790 if (ret != 0) { 791 result = _ReturnSetup(interp, ret, 792 DB_RETOK_REPPMSG(ret), "rep_proc_msg"); 793 goto out; 794 } 795 rec.data = rtmp; 796 _debug_check(); 797 ret = dbenv->rep_process_message(dbenv, &control, &rec, eid, &permlsn); 798 /* 799 * !!! 800 * The TCL API diverges from the C++/Java APIs here. For us, it 801 * is OK to get DUPMASTER and HOLDELECTION for testing purposes. 802 */ 803 result = _ReturnSetup(interp, ret, 804 DB_RETOK_REPPMSG(ret) || ret == DB_REP_DUPMASTER || 805 ret == DB_REP_HOLDELECTION, 806 "env rep_process_message"); 807 808 if (result != TCL_OK) 809 goto out; 810 811 /* 812 * We have a valid return. We need to return a variety of information. 813 * It will be one of the following: 814 * {0 0} - Make a 0 return a list for consistent return structure. 815 * {DUPMASTER 0} - DUPMASTER, no other info needed. 816 * {HOLDELECTION 0} - HOLDELECTION, no other info needed. 817 * {NEWMASTER #} - NEWMASTER and its ID. 818 * {NEWSITE 0} - NEWSITE, no other info needed. 819 * {IGNORE {LSN list}} - IGNORE and this msg's LSN. 820 * {ISPERM {LSN list}} - ISPERM and the perm LSN. 821 * {NOTPERM {LSN list}} - NOTPERM and this msg's LSN. 822 */ 823 myobjc = 2; 824 switch (ret) { 825 case 0: 826 myobjv[0] = Tcl_NewIntObj(0); 827 myobjv[1] = Tcl_NewIntObj(0); 828 break; 829 case DB_REP_DUPMASTER: 830 myobjv[0] = Tcl_NewByteArrayObj( 831 (u_char *)"DUPMASTER", (int)strlen("DUPMASTER")); 832 myobjv[1] = Tcl_NewIntObj(0); 833 break; 834 case DB_REP_HOLDELECTION: 835 myobjv[0] = Tcl_NewByteArrayObj( 836 (u_char *)"HOLDELECTION", (int)strlen("HOLDELECTION")); 837 myobjv[1] = Tcl_NewIntObj(0); 838 break; 839 case DB_REP_IGNORE: 840 myobjv[0] = Tcl_NewLongObj((long)permlsn.file); 841 myobjv[1] = Tcl_NewLongObj((long)permlsn.offset); 842 lsnlist = Tcl_NewListObj(myobjc, myobjv); 843 myobjv[0] = Tcl_NewByteArrayObj( 844 (u_char *)"IGNORE", (int)strlen("IGNORE")); 845 myobjv[1] = lsnlist; 846 break; 847 case DB_REP_ISPERM: 848 myobjv[0] = Tcl_NewLongObj((long)permlsn.file); 849 myobjv[1] = Tcl_NewLongObj((long)permlsn.offset); 850 lsnlist = Tcl_NewListObj(myobjc, myobjv); 851 myobjv[0] = Tcl_NewByteArrayObj( 852 (u_char *)"ISPERM", (int)strlen("ISPERM")); 853 myobjv[1] = lsnlist; 854 break; 855 case DB_REP_NEWSITE: 856 myobjv[0] = Tcl_NewByteArrayObj( 857 (u_char *)"NEWSITE", (int)strlen("NEWSITE")); 858 myobjv[1] = Tcl_NewIntObj(0); 859 break; 860 case DB_REP_NOTPERM: 861 myobjv[0] = Tcl_NewLongObj((long)permlsn.file); 862 myobjv[1] = Tcl_NewLongObj((long)permlsn.offset); 863 lsnlist = Tcl_NewListObj(myobjc, myobjv); 864 myobjv[0] = Tcl_NewByteArrayObj( 865 (u_char *)"NOTPERM", (int)strlen("NOTPERM")); 866 myobjv[1] = lsnlist; 867 break; 868 default: 869 msg = db_strerror(ret); 870 Tcl_AppendResult(interp, msg, NULL); 871 Tcl_SetErrorCode(interp, "BerkeleyDB", msg, NULL); 872 result = TCL_ERROR; 873 goto out; 874 } 875 res = Tcl_NewListObj(myobjc, myobjv); 876 if (res != NULL) 877 Tcl_SetObjResult(interp, res); 878out: 879 if (freectl) 880 __os_free(NULL, ctmp); 881 if (freerec) 882 __os_free(NULL, rtmp); 883 884 return (result); 885} 886#endif 887 888#ifdef CONFIG_TEST 889/* 890 * tcl_RepStat -- 891 * Call DB_ENV->rep_stat(). 892 * 893 * PUBLIC: int tcl_RepStat 894 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 895 */ 896int 897tcl_RepStat(interp, objc, objv, dbenv) 898 Tcl_Interp *interp; /* Interpreter */ 899 int objc; /* How many arguments? */ 900 Tcl_Obj *CONST objv[]; /* The argument objects */ 901 DB_ENV *dbenv; 902{ 903 DB_REP_STAT *sp; 904 Tcl_Obj *myobjv[2], *res, *thislist, *lsnlist; 905 u_int32_t flag; 906 int myobjc, result, ret; 907 char *arg, *role; 908 909 flag = 0; 910 result = TCL_OK; 911 912 if (objc > 3) { 913 Tcl_WrongNumArgs(interp, 2, objv, NULL); 914 return (TCL_ERROR); 915 } 916 if (objc == 3) { 917 arg = Tcl_GetStringFromObj(objv[2], NULL); 918 if (strcmp(arg, "-clear") == 0) 919 flag = DB_STAT_CLEAR; 920 else { 921 Tcl_SetResult(interp, 922 "db stat: unknown arg", TCL_STATIC); 923 return (TCL_ERROR); 924 } 925 } 926 927 _debug_check(); 928 ret = dbenv->rep_stat(dbenv, &sp, flag); 929 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 930 "rep stat"); 931 if (result == TCL_ERROR) 932 return (result); 933 934 /* 935 * Have our stats, now construct the name value 936 * list pairs and free up the memory. 937 */ 938 res = Tcl_NewObj(); 939#ifdef HAVE_STATISTICS 940 /* 941 * MAKE_STAT_* assumes 'res' and 'error' label. 942 */ 943 if (sp->st_status == DB_REP_MASTER) 944 role = "master"; 945 else if (sp->st_status == DB_REP_CLIENT) 946 role = "client"; 947 else 948 role = "none"; 949 MAKE_STAT_STRLIST("Role", role); 950 951 MAKE_STAT_LSN("Next LSN expected", &sp->st_next_lsn); 952 MAKE_STAT_LSN("First missed LSN", &sp->st_waiting_lsn); 953 MAKE_STAT_LSN("Maximum permanent LSN", &sp->st_max_perm_lsn); 954 MAKE_WSTAT_LIST("Bulk buffer fills", sp->st_bulk_fills); 955 MAKE_WSTAT_LIST("Bulk buffer overflows", sp->st_bulk_overflows); 956 MAKE_WSTAT_LIST("Bulk records stored", sp->st_bulk_records); 957 MAKE_WSTAT_LIST("Bulk buffer transfers", sp->st_bulk_transfers); 958 MAKE_WSTAT_LIST("Client service requests", sp->st_client_svc_req); 959 MAKE_WSTAT_LIST("Client service req misses", sp->st_client_svc_miss); 960 MAKE_WSTAT_LIST("Client rerequests", sp->st_client_rerequests); 961 MAKE_STAT_LIST("Duplicate master conditions", sp->st_dupmasters); 962 MAKE_STAT_LIST("Environment ID", sp->st_env_id); 963 MAKE_STAT_LIST("Environment priority", sp->st_env_priority); 964 MAKE_STAT_LIST("Generation number", sp->st_gen); 965 MAKE_STAT_LIST("Election generation number", sp->st_egen); 966 MAKE_STAT_LIST("Startup complete", sp->st_startup_complete); 967 MAKE_WSTAT_LIST("Duplicate log records received", sp->st_log_duplicated); 968 MAKE_WSTAT_LIST("Current log records queued", sp->st_log_queued); 969 MAKE_WSTAT_LIST("Maximum log records queued", sp->st_log_queued_max); 970 MAKE_WSTAT_LIST("Total log records queued", sp->st_log_queued_total); 971 MAKE_WSTAT_LIST("Log records received", sp->st_log_records); 972 MAKE_WSTAT_LIST("Log records requested", sp->st_log_requested); 973 MAKE_STAT_LIST("Master environment ID", sp->st_master); 974 MAKE_WSTAT_LIST("Master changes", sp->st_master_changes); 975 MAKE_STAT_LIST("Messages with bad generation number", 976 sp->st_msgs_badgen); 977 MAKE_WSTAT_LIST("Messages processed", sp->st_msgs_processed); 978 MAKE_WSTAT_LIST("Messages ignored for recovery", sp->st_msgs_recover); 979 MAKE_WSTAT_LIST("Message send failures", sp->st_msgs_send_failures); 980 MAKE_WSTAT_LIST("Messages sent", sp->st_msgs_sent); 981 MAKE_WSTAT_LIST("New site messages", sp->st_newsites); 982 MAKE_STAT_LIST("Number of sites in replication group", sp->st_nsites); 983 MAKE_WSTAT_LIST("Transmission limited", sp->st_nthrottles); 984 MAKE_WSTAT_LIST("Outdated conditions", sp->st_outdated); 985 MAKE_WSTAT_LIST("Transactions applied", sp->st_txns_applied); 986 MAKE_STAT_LIST("Next page expected", sp->st_next_pg); 987 MAKE_WSTAT_LIST("First missed page", sp->st_waiting_pg); 988 MAKE_WSTAT_LIST("Duplicate pages received", sp->st_pg_duplicated); 989 MAKE_WSTAT_LIST("Pages received", sp->st_pg_records); 990 MAKE_WSTAT_LIST("Pages requested", sp->st_pg_requested); 991 MAKE_WSTAT_LIST("Elections held", sp->st_elections); 992 MAKE_WSTAT_LIST("Elections won", sp->st_elections_won); 993 MAKE_STAT_LIST("Election phase", sp->st_election_status); 994 MAKE_STAT_LIST("Election winner", sp->st_election_cur_winner); 995 MAKE_STAT_LIST("Election generation number", sp->st_election_gen); 996 MAKE_STAT_LSN("Election max LSN", &sp->st_election_lsn); 997 MAKE_STAT_LIST("Election sites", sp->st_election_nsites); 998 MAKE_STAT_LIST("Election nvotes", sp->st_election_nvotes); 999 MAKE_STAT_LIST("Election priority", sp->st_election_priority); 1000 MAKE_STAT_LIST("Election tiebreaker", sp->st_election_tiebreaker); 1001 MAKE_STAT_LIST("Election votes", sp->st_election_votes); 1002 MAKE_STAT_LIST("Election seconds", sp->st_election_sec); 1003 MAKE_STAT_LIST("Election usecs", sp->st_election_usec); 1004 MAKE_STAT_LIST("Start-sync operations delayed", 1005 sp->st_startsync_delayed); 1006 MAKE_STAT_LIST("Maximum lease seconds", sp->st_max_lease_sec); 1007 MAKE_STAT_LIST("Maximum lease usecs", sp->st_max_lease_usec); 1008 MAKE_STAT_LIST("File fail cleanups done", sp->st_filefail_cleanups); 1009#endif 1010 1011 Tcl_SetObjResult(interp, res); 1012error: 1013 __os_ufree(dbenv->env, sp); 1014 return (result); 1015} 1016 1017/* 1018 * tcl_RepMgr -- 1019 * Configure and start the Replication Manager. 1020 * 1021 * PUBLIC: int tcl_RepMgr 1022 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 1023 */ 1024int 1025tcl_RepMgr(interp, objc, objv, dbenv) 1026 Tcl_Interp *interp; /* Interpreter */ 1027 int objc; /* How many arguments? */ 1028 Tcl_Obj *CONST objv[]; /* The argument objects */ 1029 DB_ENV *dbenv; /* Environment pointer */ 1030{ 1031 static const char *rmgr[] = { 1032 "-ack", 1033 "-local", 1034 "-msgth", 1035 "-nsites", 1036 "-pri", 1037 "-remote", 1038 "-start", 1039 "-timeout", 1040 NULL 1041 }; 1042 enum rmgr { 1043 RMGR_ACK, 1044 RMGR_LOCAL, 1045 RMGR_MSGTH, 1046 RMGR_NSITES, 1047 RMGR_PRI, 1048 RMGR_REMOTE, 1049 RMGR_START, 1050 RMGR_TIMEOUT 1051 }; 1052 Tcl_Obj **myobjv; 1053 long to; 1054 int ack, i, myobjc, optindex, result, ret, totype; 1055 u_int32_t msgth, remote_flag, start_flag, uintarg; 1056 char *arg; 1057 1058 result = TCL_OK; 1059 ack = ret = totype = 0; 1060 msgth = 1; 1061 remote_flag = start_flag = 0; 1062 1063 if (objc <= 2) { 1064 Tcl_WrongNumArgs(interp, 2, objv, "?args?"); 1065 return (TCL_ERROR); 1066 } 1067 /* 1068 * Get the command name index from the object based on the bdbcmds 1069 * defined above. 1070 */ 1071 i = 2; 1072 while (i < objc) { 1073 Tcl_ResetResult(interp); 1074 if (Tcl_GetIndexFromObj(interp, objv[i], rmgr, "option", 1075 TCL_EXACT, &optindex) != TCL_OK) { 1076 result = IS_HELP(objv[i]); 1077 goto error; 1078 } 1079 i++; 1080 switch ((enum rmgr)optindex) { 1081 case RMGR_ACK: 1082 if (i >= objc) { 1083 Tcl_WrongNumArgs(interp, 2, objv, 1084 "?-ack policy?"); 1085 result = TCL_ERROR; 1086 break; 1087 } 1088 arg = Tcl_GetStringFromObj(objv[i++], NULL); 1089 if (strcmp(arg, "all") == 0) 1090 ack = DB_REPMGR_ACKS_ALL; 1091 else if (strcmp(arg, "allpeers") == 0) 1092 ack = DB_REPMGR_ACKS_ALL_PEERS; 1093 else if (strcmp(arg, "none") == 0) 1094 ack = DB_REPMGR_ACKS_NONE; 1095 else if (strcmp(arg, "one") == 0) 1096 ack = DB_REPMGR_ACKS_ONE; 1097 else if (strcmp(arg, "onepeer") == 0) 1098 ack = DB_REPMGR_ACKS_ONE_PEER; 1099 else if (strcmp(arg, "quorum") == 0) 1100 ack = DB_REPMGR_ACKS_QUORUM; 1101 else { 1102 Tcl_AddErrorInfo(interp, 1103 "ack: illegal policy"); 1104 result = TCL_ERROR; 1105 break; 1106 } 1107 _debug_check(); 1108 ret = dbenv->repmgr_set_ack_policy(dbenv, ack); 1109 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 1110 "ack"); 1111 break; 1112 case RMGR_LOCAL: 1113 result = Tcl_ListObjGetElements(interp, objv[i], 1114 &myobjc, &myobjv); 1115 if (result == TCL_OK) 1116 i++; 1117 else 1118 break; 1119 if (myobjc != 2) { 1120 Tcl_WrongNumArgs(interp, 2, objv, 1121 "?-local {host port}?"); 1122 result = TCL_ERROR; 1123 break; 1124 } 1125 arg = Tcl_GetStringFromObj(myobjv[0], NULL); 1126 if ((result = _GetUInt32(interp, myobjv[1], &uintarg)) 1127 != TCL_OK) 1128 break; 1129 _debug_check(); 1130 /* 1131 * No flags for now. 1132 */ 1133 ret = dbenv->repmgr_set_local_site(dbenv, 1134 arg, uintarg, 0); 1135 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 1136 "repmgr_set_local_site"); 1137 break; 1138 case RMGR_MSGTH: 1139 if (i >= objc) { 1140 Tcl_WrongNumArgs( 1141 interp, 2, objv, "?-msgth nth?"); 1142 result = TCL_ERROR; 1143 break; 1144 } 1145 result = _GetUInt32(interp, objv[i++], &msgth); 1146 break; 1147 case RMGR_NSITES: 1148 if (i >= objc) { 1149 Tcl_WrongNumArgs(interp, 2, objv, 1150 "?-nsites num_sites?"); 1151 result = TCL_ERROR; 1152 break; 1153 } 1154 result = _GetUInt32(interp, objv[i++], &uintarg); 1155 if (result == TCL_OK) { 1156 _debug_check(); 1157 ret = dbenv-> 1158 rep_set_nsites(dbenv, uintarg); 1159 } 1160 break; 1161 case RMGR_PRI: 1162 if (i >= objc) { 1163 Tcl_WrongNumArgs(interp, 2, objv, 1164 "?-pri priority?"); 1165 result = TCL_ERROR; 1166 break; 1167 } 1168 result = _GetUInt32(interp, objv[i++], &uintarg); 1169 if (result == TCL_OK) { 1170 _debug_check(); 1171 ret = dbenv-> 1172 rep_set_priority(dbenv, uintarg); 1173 } 1174 break; 1175 case RMGR_REMOTE: 1176 result = Tcl_ListObjGetElements(interp, objv[i], 1177 &myobjc, &myobjv); 1178 if (result == TCL_OK) 1179 i++; 1180 else 1181 break; 1182 if (myobjc != 2 && myobjc != 3) { 1183 Tcl_WrongNumArgs(interp, 2, objv, 1184 "?-remote {host port [peer]}?"); 1185 result = TCL_ERROR; 1186 break; 1187 } 1188 /* 1189 * Get the flag first so we can reuse 'arg'. 1190 */ 1191 if (myobjc == 3) { 1192 arg = Tcl_GetStringFromObj(myobjv[2], NULL); 1193 if (strcmp(arg, "peer") == 0) 1194 remote_flag = DB_REPMGR_PEER; 1195 else { 1196 Tcl_AddErrorInfo(interp, 1197 "remote: illegal flag"); 1198 result = TCL_ERROR; 1199 break; 1200 } 1201 } 1202 arg = Tcl_GetStringFromObj(myobjv[0], NULL); 1203 if ((result = _GetUInt32(interp, myobjv[1], &uintarg)) 1204 != TCL_OK) 1205 break; 1206 _debug_check(); 1207 ret = dbenv->repmgr_add_remote_site(dbenv, 1208 arg, uintarg, NULL, remote_flag); 1209 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 1210 "repmgr_add_remote_site"); 1211 break; 1212 case RMGR_START: 1213 if (i >= objc) { 1214 Tcl_WrongNumArgs( 1215 interp, 2, objv, "?-start state?"); 1216 result = TCL_ERROR; 1217 break; 1218 } 1219 arg = Tcl_GetStringFromObj(objv[i++], NULL); 1220 if (strcmp(arg, "master") == 0) 1221 start_flag = DB_REP_MASTER; 1222 else if (strcmp(arg, "client") == 0) 1223 start_flag = DB_REP_CLIENT; 1224 else if (strcmp(arg, "elect") == 0) 1225 start_flag = DB_REP_ELECTION; 1226 else { 1227 Tcl_AddErrorInfo( 1228 interp, "start: illegal state"); 1229 result = TCL_ERROR; 1230 break; 1231 } 1232 /* 1233 * Some config functions need to be called 1234 * before repmgr_start. So finish parsing all 1235 * the args and call repmgr_start at the end. 1236 */ 1237 break; 1238 case RMGR_TIMEOUT: 1239 result = Tcl_ListObjGetElements(interp, objv[i], 1240 &myobjc, &myobjv); 1241 if (result == TCL_OK) 1242 i++; 1243 else 1244 break; 1245 if (myobjc != 2) { 1246 Tcl_WrongNumArgs(interp, 2, objv, 1247 "?-timeout {type to}?"); 1248 result = TCL_ERROR; 1249 break; 1250 } 1251 arg = Tcl_GetStringFromObj(myobjv[0], NULL); 1252 if (strcmp(arg, "ack") == 0) 1253 totype = DB_REP_ACK_TIMEOUT; 1254 else if (strcmp(arg, "conn_retry") == 0) 1255 totype = DB_REP_CONNECTION_RETRY; 1256 else if (strcmp(arg, "elect") == 0) 1257 totype = DB_REP_ELECTION_TIMEOUT; 1258 else if (strcmp(arg, "elect_retry") == 0) 1259 totype = DB_REP_ELECTION_RETRY; 1260 else if (strcmp(arg, "heartbeat_monitor") == 0) 1261 totype = DB_REP_HEARTBEAT_MONITOR; 1262 else if (strcmp(arg, "heartbeat_send") == 0) 1263 totype = DB_REP_HEARTBEAT_SEND; 1264 else { 1265 Tcl_AddErrorInfo(interp, 1266 "timeout: illegal type"); 1267 result = TCL_ERROR; 1268 break; 1269 } 1270 if ((result = Tcl_GetLongFromObj( 1271 interp, myobjv[1], &to)) != TCL_OK) 1272 break; 1273 _debug_check(); 1274 ret = dbenv->rep_set_timeout(dbenv, totype, 1275 (db_timeout_t)to); 1276 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 1277 "rep_set_timeout"); 1278 break; 1279 } 1280 /* 1281 * If, at any time, parsing the args we get an error, 1282 * bail out and return. 1283 */ 1284 if (result != TCL_OK) 1285 goto error; 1286 } 1287 /* 1288 * Only call repmgr_start if needed. The user may use this 1289 * call just to reconfigure, change policy, etc. 1290 */ 1291 if (start_flag != 0 && result == TCL_OK) { 1292 _debug_check(); 1293 ret = dbenv->repmgr_start(dbenv, (int)msgth, start_flag); 1294 result = _ReturnSetup( 1295 interp, ret, DB_RETOK_REPMGR_START(ret), "repmgr_start"); 1296 } 1297error: 1298 return (result); 1299} 1300 1301/* 1302 * tcl_RepMgrSiteList -- 1303 * Call DB_ENV->repmgr_site_list(). 1304 * 1305 * PUBLIC: int tcl_RepMgrSiteList 1306 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 1307 */ 1308int 1309tcl_RepMgrSiteList(interp, objc, objv, dbenv) 1310 Tcl_Interp *interp; /* Interpreter */ 1311 int objc; /* How many arguments? */ 1312 Tcl_Obj *CONST objv[]; /* The argument objects */ 1313 DB_ENV *dbenv; 1314{ 1315 DB_REPMGR_SITE *sp; 1316 Tcl_Obj *myobjv[4], *res, *thislist; 1317 u_int count, i; 1318 char *st; 1319 int myobjc, result, ret; 1320 1321 result = TCL_OK; 1322 1323 if (objc > 2) { 1324 Tcl_WrongNumArgs(interp, 2, objv, NULL); 1325 return (TCL_ERROR); 1326 } 1327 1328 _debug_check(); 1329 ret = dbenv->repmgr_site_list(dbenv, &count, &sp); 1330 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 1331 "repmgr sitelist"); 1332 if (result == TCL_ERROR) 1333 return (result); 1334 1335 /* 1336 * Have our sites, now construct the {eid host port status} 1337 * tuples and free up the memory. 1338 */ 1339 res = Tcl_NewObj(); 1340 1341 for (i = 0; i < count; ++i) { 1342 /* 1343 * MAKE_SITE_LIST assumes 'res' and 'error' label. 1344 */ 1345 if (sp[i].status == DB_REPMGR_CONNECTED) 1346 st = "connected"; 1347 else if (sp[i].status == DB_REPMGR_DISCONNECTED) 1348 st = "disconnected"; 1349 else 1350 st = "unknown"; 1351 MAKE_SITE_LIST(sp[i].eid, sp[i].host, sp[i].port, st); 1352 } 1353 1354 Tcl_SetObjResult(interp, res); 1355error: 1356 __os_ufree(dbenv->env, sp); 1357 return (result); 1358} 1359 1360/* 1361 * tcl_RepMgrStat -- 1362 * Call DB_ENV->repmgr_stat(). 1363 * 1364 * PUBLIC: int tcl_RepMgrStat 1365 * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); 1366 */ 1367int 1368tcl_RepMgrStat(interp, objc, objv, dbenv) 1369 Tcl_Interp *interp; /* Interpreter */ 1370 int objc; /* How many arguments? */ 1371 Tcl_Obj *CONST objv[]; /* The argument objects */ 1372 DB_ENV *dbenv; 1373{ 1374 DB_REPMGR_STAT *sp; 1375 Tcl_Obj *res; 1376 u_int32_t flag; 1377 int result, ret; 1378 char *arg; 1379 1380 flag = 0; 1381 result = TCL_OK; 1382 1383 if (objc > 3) { 1384 Tcl_WrongNumArgs(interp, 2, objv, NULL); 1385 return (TCL_ERROR); 1386 } 1387 if (objc == 3) { 1388 arg = Tcl_GetStringFromObj(objv[2], NULL); 1389 if (strcmp(arg, "-clear") == 0) 1390 flag = DB_STAT_CLEAR; 1391 else { 1392 Tcl_SetResult(interp, 1393 "db stat: unknown arg", TCL_STATIC); 1394 return (TCL_ERROR); 1395 } 1396 } 1397 1398 _debug_check(); 1399 ret = dbenv->repmgr_stat(dbenv, &sp, flag); 1400 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 1401 "repmgr stat"); 1402 if (result == TCL_ERROR) 1403 return (result); 1404 1405 /* 1406 * Have our stats, now construct the name value 1407 * list pairs and free up the memory. 1408 */ 1409 res = Tcl_NewObj(); 1410#ifdef HAVE_STATISTICS 1411 /* 1412 * MAKE_STAT_* assumes 'res' and 'error' label. 1413 */ 1414 MAKE_WSTAT_LIST("Acknowledgement failures", sp->st_perm_failed); 1415 MAKE_WSTAT_LIST("Messages delayed", sp->st_msgs_queued); 1416 MAKE_WSTAT_LIST("Messages discarded", sp->st_msgs_dropped); 1417 MAKE_WSTAT_LIST("Connections dropped", sp->st_connection_drop); 1418 MAKE_WSTAT_LIST("Failed re-connects", sp->st_connect_fail); 1419#endif 1420 1421 Tcl_SetObjResult(interp, res); 1422error: 1423 __os_ufree(dbenv->env, sp); 1424 return (result); 1425} 1426#endif 1427