001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.tools; 028 029 import org.opends.server.loggers.debug.DebugTracer; 030 import static org.opends.server.loggers.debug.DebugLogger.getTracer; 031 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; 032 import static org.opends.server.util.StaticUtils.*; 033 import org.opends.server.util.args.*; 034 import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH; 035 import org.opends.server.util.StaticUtils; 036 import org.opends.server.util.table.TableBuilder; 037 import org.opends.server.util.table.TextTablePrinter; 038 import org.opends.server.types.*; 039 import static org.opends.messages.ToolMessages.*; 040 import org.opends.messages.Message; 041 import static org.opends.server.tools.ToolConstants.OPTION_SHORT_CONFIG_CLASS; 042 import static org.opends.server.tools.ToolConstants.OPTION_LONG_CONFIG_CLASS; 043 import static org.opends.server.tools.ToolConstants.OPTION_SHORT_HELP; 044 import static org.opends.server.tools.ToolConstants.OPTION_LONG_HELP; 045 import org.opends.server.extensions.ConfigFileHandler; 046 import org.opends.server.core.DirectoryServer; 047 import org.opends.server.core.LockFileManager; 048 import org.opends.server.config.ConfigException; 049 import org.opends.server.api.Backend; 050 import org.opends.server.admin.std.server.BackendCfg; 051 import org.opends.server.admin.std.server.LocalDBBackendCfg; 052 import org.opends.server.backends.jeb.*; 053 import org.opends.server.protocols.asn1.ASN1OctetString; 054 import org.opends.server.protocols.asn1.ASN1Element; 055 056 import java.io.*; 057 import java.util.*; 058 059 import com.sleepycat.je.*; 060 061 /** 062 * This program provides a utility that may be used to debug a JE backend. This 063 * tool provides the ability list various containers in the backend as well as 064 * dump the contents of database containers. This will be 065 * a process that is intended to run separate from Directory Server and not 066 * internally within the server process (e.g., via the tasks interface). 067 */ 068 public class DBTest 069 { 070 /** 071 * The tracer object for the debug logger. 072 */ 073 private static final DebugTracer TRACER = getTracer(); 074 075 // The error stream which this application should use. 076 private final PrintStream err; 077 078 // The output stream which this application should use. 079 private final PrintStream out; 080 081 // Flag indicating whether or not the global arguments have 082 // already been initialized. 083 private boolean globalArgumentsInitialized = false; 084 085 // The command-line argument parser. 086 private final SubCommandArgumentParser parser; 087 088 // The argument which should be used to request usage information. 089 private BooleanArgument showUsageArgument; 090 091 // The argument which should be used to specify the config class. 092 private StringArgument configClass; 093 094 // THe argument which should be used to specify the config file. 095 private StringArgument configFile; 096 097 // Flag indicating whether or not the sub-commands have 098 // already been initialized. 099 private boolean subCommandsInitialized = false; 100 101 102 103 /** 104 * Provides the command-line arguments to the main application for 105 * processing. 106 * 107 * @param args 108 * The set of command-line arguments provided to this 109 * program. 110 */ 111 public static void main(String[] args) { 112 int exitCode = main(args, true, System.out, System.err); 113 if (exitCode != 0) { 114 System.exit(filterExitCode(exitCode)); 115 } 116 } 117 118 119 /** 120 * Provides the command-line arguments to the main application for 121 * processing and returns the exit code as an integer. 122 * 123 * @param args 124 * The set of command-line arguments provided to this 125 * program. 126 * @param initializeServer 127 * Indicates whether to perform basic initialization (which 128 * should not be done if the tool is running in the same 129 * JVM as the server). 130 * @param outStream 131 * The output stream for standard output. 132 * @param errStream 133 * The output stream for standard error. 134 * @return Zero to indicate that the program completed successfully, 135 * or non-zero to indicate that an error occurred. 136 */ 137 public static int main(String[] args, boolean initializeServer, 138 OutputStream outStream, OutputStream errStream) { 139 DBTest app = new DBTest(outStream, errStream); 140 141 // Run the application. 142 return app.run(args, initializeServer); 143 } 144 145 /** 146 * Creates a new dsconfig application instance. 147 * 148 * @param out 149 * The application output stream. 150 * @param err 151 * The application error stream. 152 */ 153 public DBTest(OutputStream out, OutputStream err) 154 { 155 if (out != null) { 156 this.out = new PrintStream(out); 157 } else { 158 this.out = NullOutputStream.printStream(); 159 } 160 161 if (err != null) { 162 this.err = new PrintStream(err); 163 } else { 164 this.err = NullOutputStream.printStream(); 165 } 166 167 Message toolDescription = INFO_DESCRIPTION_DBTEST_TOOL.get(); 168 this.parser = new SubCommandArgumentParser(this.getClass().getName(), 169 toolDescription, false); 170 } 171 172 // Displays the provided message followed by a help usage reference. 173 private void displayMessageAndUsageReference(Message message) { 174 printMessage(message); 175 printMessage(Message.EMPTY); 176 printMessage(parser.getHelpUsageReference()); 177 } 178 179 180 181 /** 182 * Registers the global arguments with the argument parser. 183 * 184 * @throws ArgumentException 185 * If a global argument could not be registered. 186 */ 187 private void initializeGlobalArguments() throws ArgumentException { 188 if (!globalArgumentsInitialized) { 189 configClass = 190 new StringArgument("configclass", OPTION_SHORT_CONFIG_CLASS, 191 OPTION_LONG_CONFIG_CLASS, true, false, 192 true, INFO_CONFIGCLASS_PLACEHOLDER.get(), 193 ConfigFileHandler.class.getName(), null, 194 INFO_DESCRIPTION_CONFIG_CLASS.get()); 195 configClass.setHidden(true); 196 197 configFile = 198 new StringArgument("configfile", 'f', "configFile", true, false, 199 true, INFO_CONFIGFILE_PLACEHOLDER.get(), null, 200 null, 201 INFO_DESCRIPTION_CONFIG_FILE.get()); 202 configFile.setHidden(true); 203 204 205 showUsageArgument = 206 new BooleanArgument("help", OPTION_SHORT_HELP, OPTION_LONG_HELP, 207 INFO_DESCRIPTION_USAGE.get()); 208 209 // Register the global arguments. 210 parser.addGlobalArgument(showUsageArgument); 211 parser.setUsageArgument(showUsageArgument, out); 212 parser.addGlobalArgument(configClass); 213 parser.addGlobalArgument(configFile); 214 215 globalArgumentsInitialized = true; 216 } 217 } 218 219 220 221 /** 222 * Registers the sub-commands with the argument parser. 223 * 224 * @throws ArgumentException 225 * If a sub-command could not be created. 226 */ 227 private void initializeSubCommands() throws ArgumentException { 228 if (!subCommandsInitialized) { 229 StringArgument backendID; 230 StringArgument baseDN; 231 StringArgument databaseName; 232 BooleanArgument skipDecode; 233 StringArgument maxKeyValue; 234 StringArgument minKeyValue; 235 IntegerArgument maxDataSize; 236 IntegerArgument minDataSize; 237 SubCommand sub; 238 239 sub = new SubCommand(parser, "list-root-containers", 240 INFO_DESCRIPTION_DBTEST_SUBCMD_LIST_ROOT_CONTAINERS.get()); 241 242 243 sub = new SubCommand(parser, "list-entry-containers", 244 INFO_DESCRIPTION_DBTEST_SUBCMD_LIST_ENTRY_CONTAINERS.get()); 245 backendID = 246 new StringArgument("backendid", 'n', "backendID", true, false, true, 247 INFO_BACKENDNAME_PLACEHOLDER.get(), null, null, 248 INFO_DESCRIPTION_DBTEST_BACKEND_ID.get()); 249 sub.addArgument(backendID); 250 251 252 sub = new SubCommand(parser, "list-database-containers", 253 INFO_DESCRIPTION_DBTEST_SUBCMD_LIST_DATABASE_CONTAINERS.get()); 254 backendID = 255 new StringArgument("backendid", 'n', "backendID", true, false, true, 256 INFO_BACKENDNAME_PLACEHOLDER.get(), null, null, 257 INFO_DESCRIPTION_DBTEST_BACKEND_ID.get()); 258 sub.addArgument(backendID); 259 baseDN = 260 new StringArgument("basedn", 'b', "baseDN", false, 261 false, true, INFO_BASEDN_PLACEHOLDER.get(), null, 262 null, 263 INFO_DESCRIPTION_DBTEST_BASE_DN.get()); 264 sub.addArgument(baseDN); 265 266 267 sub = new SubCommand(parser, "dump-database-container", 268 INFO_DESCRIPTION_DBTEST_SUBCMD_DUMP_DATABASE_CONTAINER.get()); 269 backendID = 270 new StringArgument("backendid", 'n', "backendID", true, false, true, 271 INFO_BACKENDNAME_PLACEHOLDER.get(), null, null, 272 INFO_DESCRIPTION_DBTEST_BACKEND_ID.get()); 273 sub.addArgument(backendID); 274 baseDN = 275 new StringArgument("basedn", 'b', "baseDN", true, 276 false, true, INFO_BASEDN_PLACEHOLDER.get(), null, 277 null, 278 INFO_DESCRIPTION_DBTEST_BASE_DN.get()); 279 sub.addArgument(baseDN); 280 databaseName = 281 new StringArgument("databasename", 'd', "databaseName", true, 282 false, true, INFO_DATABASE_NAME_PLACEHOLDER.get(), 283 null, null, 284 INFO_DESCRIPTION_DBTEST_DATABASE_NAME.get()); 285 sub.addArgument(databaseName); 286 skipDecode = 287 new BooleanArgument("skipdecode", 'p', "skipDecode", 288 INFO_DESCRIPTION_DBTEST_SKIP_DECODE.get()); 289 sub.addArgument(skipDecode); 290 maxKeyValue = new StringArgument("maxkeyvalue", 'K', "maxKeyValue", false, 291 false, true, 292 INFO_MAX_KEY_VALUE_PLACEHOLDER.get(), 293 null, null, 294 INFO_DESCRIPTION_DBTEST_MAX_KEY_VALUE.get()); 295 sub.addArgument(maxKeyValue); 296 minKeyValue = new StringArgument("minkeyvalue", 'k', "minKeyValue", false, 297 false, true, 298 INFO_MIN_KEY_VALUE_PLACEHOLDER.get(), 299 null, 300 null, 301 INFO_DESCRIPTION_DBTEST_MIN_KEY_VALUE.get()); 302 sub.addArgument(minKeyValue); 303 maxDataSize = new IntegerArgument("maxdatasize", 'S', "maxDataSize", 304 false, false, true, 305 INFO_MAX_DATA_SIZE_PLACEHOLDER.get(), 306 -1, 307 null, 308 INFO_DESCRIPTION_DBTEST_MAX_DATA_SIZE.get()); 309 sub.addArgument(maxDataSize); 310 minDataSize = new IntegerArgument("mindatasize", 's', "minDataSize", 311 false, false, true, 312 INFO_MIN_DATA_SIZE_PLACEHOLDER.get(), 313 -1, 314 null, 315 INFO_DESCRIPTION_DBTEST_MIN_DATA_SIZE.get()); 316 sub.addArgument(minDataSize); 317 318 319 sub = new SubCommand(parser, "list-index-status", 320 INFO_DESCRIPTION_DBTEST_SUBCMD_LIST_INDEX_STATUS.get()); 321 backendID = 322 new StringArgument("backendid", 'n', "backendID", true, false, true, 323 INFO_BACKENDNAME_PLACEHOLDER.get(), null, null, 324 INFO_DESCRIPTION_DBTEST_BACKEND_ID.get()); 325 sub.addArgument(backendID); 326 baseDN = 327 new StringArgument("basedn", 'b', "baseDN", true, 328 true, true, INFO_BASEDN_PLACEHOLDER.get(), null, 329 null, 330 INFO_DESCRIPTION_DBTEST_BASE_DN.get()); 331 sub.addArgument(baseDN); 332 333 subCommandsInitialized = true; 334 } 335 } 336 337 338 /** 339 * Parses the provided command-line arguments and makes the 340 * appropriate changes to the Directory Server configuration. 341 * 342 * @param args 343 * The command-line arguments provided to this program. 344 * @param initializeServer 345 * Indicates whether to perform basic initialization (which 346 * should not be done if the tool is running in the same 347 * JVM as the server). 348 * @return The exit code from the configuration processing. A 349 * nonzero value indicates that there was some kind of 350 * problem during the configuration processing. 351 */ 352 private int run(String[] args, boolean initializeServer) { 353 // Register global arguments and sub-commands. 354 try { 355 initializeGlobalArguments(); 356 initializeSubCommands(); 357 } catch (ArgumentException e) { 358 Message message = ERR_CANNOT_INITIALIZE_ARGS.get(e.getMessage()); 359 printMessage(message); 360 return 1; 361 } 362 363 // Parse the command-line arguments provided to this program. 364 try { 365 parser.parseArguments(args); 366 } catch (ArgumentException ae) { 367 Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage()); 368 displayMessageAndUsageReference(message); 369 return 1; 370 } 371 372 // If the usage/version argument was provided, then we don't need 373 // to do anything else. 374 if (parser.usageOrVersionDisplayed()) { 375 return 0; 376 } 377 378 // Only initialize the server when run as a standalone 379 // application. 380 if (initializeServer) { 381 // Perform the initial bootstrap of the Directory Server and process the 382 // configuration. 383 DirectoryServer directoryServer = DirectoryServer.getInstance(); 384 try 385 { 386 directoryServer.bootstrapClient(); 387 directoryServer.initializeJMX(); 388 } 389 catch (Exception e) 390 { 391 Message message = ERR_SERVER_BOOTSTRAP_ERROR.get( 392 getExceptionMessage(e)); 393 printMessage(message); 394 return 1; 395 } 396 397 try 398 { 399 directoryServer.initializeConfiguration(configClass.getValue(), 400 configFile.getValue()); 401 } 402 catch (InitializationException ie) 403 { 404 Message message = ERR_CANNOT_LOAD_CONFIG.get( 405 ie.getMessage()); 406 printMessage(message); 407 return 1; 408 } 409 catch (Exception e) 410 { 411 Message message = ERR_CANNOT_LOAD_CONFIG.get( 412 getExceptionMessage(e)); 413 printMessage(message); 414 return 1; 415 } 416 417 418 419 // Initialize the Directory Server schema elements. 420 try 421 { 422 directoryServer.initializeSchema(); 423 } 424 catch (ConfigException ce) 425 { 426 Message message = ERR_CANNOT_LOAD_SCHEMA.get( 427 ce.getMessage()); 428 printMessage(message); 429 return 1; 430 } 431 catch (InitializationException ie) 432 { 433 Message message = ERR_CANNOT_LOAD_SCHEMA.get( 434 ie.getMessage()); 435 printMessage(message); 436 return 1; 437 } 438 catch (Exception e) 439 { 440 Message message = ERR_CANNOT_LOAD_SCHEMA.get( 441 getExceptionMessage(e)); 442 printMessage(message); 443 return 1; 444 } 445 } 446 447 // Make sure that we have a sub-command. 448 if (parser.getSubCommand() == null) 449 { 450 Message message = ERR_DBTEST_MISSING_SUBCOMMAND.get(); 451 displayMessageAndUsageReference(message); 452 return 1; 453 } 454 455 // Retrieve the sub-command implementation and run it. 456 SubCommand subCommand = parser.getSubCommand(); 457 try { 458 if(subCommand.getName().equals("list-root-containers")) 459 { 460 return listRootContainers(); 461 } 462 else if(subCommand.getName().equals("list-entry-containers")) 463 { 464 return listEntryContainers(subCommand.getArgument("backendid")); 465 } 466 else if(subCommand.getName().equals("list-database-containers")) 467 { 468 return listDatabaseContainers(subCommand.getArgument("backendid"), 469 subCommand.getArgument("basedn")); 470 } 471 else if(subCommand.getName().equals("dump-database-container")) 472 { 473 return dumpDatabaseContainer(subCommand.getArgument("backendid"), 474 subCommand.getArgument("basedn"), 475 subCommand.getArgument("databasename"), 476 subCommand.getArgument("skipdecode"), 477 subCommand.getArgument("maxkeyvalue"), 478 subCommand.getArgument("minkeyvalue"), 479 subCommand.getArgument("maxdatasize"), 480 subCommand.getArgument("mindatasize")); 481 } 482 else if(subCommand.getName().equals("list-index-status")) 483 { 484 return listIndexStatus(subCommand.getArgument("backendid"), 485 subCommand.getArgument("basedn")); 486 } 487 { 488 return 0; 489 } 490 } catch (Exception e) { 491 if (debugEnabled()) { 492 TRACER.debugCaught(DebugLogLevel.ERROR, e); 493 } 494 printMessage(Message.raw(StaticUtils.stackTraceToString(e))); 495 return 1; 496 } 497 } 498 499 private int listRootContainers() 500 { 501 TreeMap<LocalDBBackendCfg, BackendImpl> jeBackends = getJEBackends(); 502 int count = 0; 503 504 // Create a table of their properties. 505 TableBuilder builder = new TableBuilder(); 506 507 builder.appendHeading(INFO_LABEL_DBTEST_BACKEND_ID.get()); 508 builder.appendHeading(INFO_LABEL_DBTEST_DB_DIRECTORY.get()); 509 510 for(Map.Entry<LocalDBBackendCfg, BackendImpl> backend : 511 jeBackends.entrySet()) 512 { 513 builder.startRow(); 514 builder.appendCell(backend.getValue().getBackendID()); 515 builder.appendCell(backend.getKey().getDBDirectory()); 516 count++; 517 } 518 519 TextTablePrinter printer = new TextTablePrinter(out); 520 builder.print(printer); 521 out.format("%nTotal: %d%n", count); 522 523 return 0; 524 } 525 526 private int listEntryContainers(Argument backendID) 527 { 528 TreeMap<LocalDBBackendCfg, BackendImpl> jeBackends = getJEBackends(); 529 BackendImpl backend = null; 530 531 for(BackendImpl b : jeBackends.values()) 532 { 533 if(b.getBackendID().equalsIgnoreCase(backendID.getValue())) 534 { 535 backend = b; 536 break; 537 } 538 } 539 540 if(backend == null) 541 { 542 printMessage(ERR_DBTEST_NO_BACKENDS_FOR_ID.get(backendID.getValue())); 543 return 1; 544 } 545 546 // Acquire an shared lock for the backend. 547 try 548 { 549 String lockFile = LockFileManager.getBackendLockFileName(backend); 550 StringBuilder failureReason = new StringBuilder(); 551 if (! LockFileManager.acquireSharedLock(lockFile, failureReason)) 552 { 553 Message message = ERR_DBTEST_CANNOT_LOCK_BACKEND.get( 554 backend.getBackendID(), String.valueOf(failureReason)); 555 printMessage(message); 556 return 1; 557 } 558 } 559 catch (Exception e) 560 { 561 Message message = ERR_DBTEST_CANNOT_LOCK_BACKEND.get( 562 backend.getBackendID(), getExceptionMessage(e)); 563 printMessage(message); 564 return 1; 565 } 566 567 RootContainer rc; 568 try 569 { 570 rc = backend.getReadOnlyRootContainer(); 571 } 572 catch(Exception e) 573 { 574 printMessage(ERR_DBTEST_ERROR_INITIALIZING_BACKEND.get( 575 backend.getBackendID(), 576 StaticUtils.stackTraceToSingleLineString(e))); 577 return 1; 578 } 579 580 try 581 { 582 // Create a table of their properties. 583 TableBuilder builder = new TableBuilder(); 584 int count = 0; 585 586 builder.appendHeading(INFO_LABEL_DBTEST_BASE_DN.get()); 587 builder.appendHeading(INFO_LABEL_DBTEST_JE_DATABASE_PREFIX.get()); 588 builder.appendHeading(INFO_LABEL_DBTEST_ENTRY_COUNT.get()); 589 590 for(EntryContainer ec : rc.getEntryContainers()) 591 { 592 builder.startRow(); 593 builder.appendCell(ec.getBaseDN().toNormalizedString()); 594 builder.appendCell(ec.getDatabasePrefix()); 595 builder.appendCell(ec.getEntryCount()); 596 count++; 597 } 598 599 TextTablePrinter printer = new TextTablePrinter(out); 600 builder.print(printer); 601 out.format("%nTotal: %d%n", count); 602 603 return 0; 604 605 606 } 607 catch(DatabaseException de) 608 { 609 printMessage(ERR_DBTEST_ERROR_READING_DATABASE.get( 610 StaticUtils.stackTraceToSingleLineString(de))); 611 return 1; 612 } 613 finally 614 { 615 try 616 { 617 // Close the root container 618 rc.close(); 619 } 620 catch(DatabaseException de) 621 { 622 // Ignore. 623 } 624 625 // Release the shared lock on the backend. 626 try 627 { 628 String lockFile = LockFileManager.getBackendLockFileName(backend); 629 StringBuilder failureReason = new StringBuilder(); 630 if (! LockFileManager.releaseLock(lockFile, failureReason)) 631 { 632 Message message = WARN_DBTEST_CANNOT_UNLOCK_BACKEND.get( 633 backend.getBackendID(), String.valueOf(failureReason)); 634 printMessage(message); 635 } 636 } 637 catch (Exception e) 638 { 639 Message message = WARN_DBTEST_CANNOT_UNLOCK_BACKEND.get( 640 backend.getBackendID(), getExceptionMessage(e)); 641 printMessage(message); 642 } 643 } 644 } 645 646 private int listDatabaseContainers(Argument backendID, 647 Argument baseDN) 648 { 649 TreeMap<LocalDBBackendCfg, BackendImpl> jeBackends = getJEBackends(); 650 BackendImpl backend = null; 651 DN base = null; 652 653 for(BackendImpl b : jeBackends.values()) 654 { 655 if(b.getBackendID().equalsIgnoreCase(backendID.getValue())) 656 { 657 backend = b; 658 break; 659 } 660 } 661 662 if(backend == null) 663 { 664 printMessage(ERR_DBTEST_NO_BACKENDS_FOR_ID.get(backendID.getValue())); 665 return 1; 666 } 667 668 if(baseDN.isPresent()) 669 { 670 try 671 { 672 base = DN.decode(baseDN.getValue()); 673 } 674 catch(DirectoryException de) 675 { 676 printMessage(ERR_DBTEST_DECODE_BASE_DN.get(baseDN.getValue(), 677 getExceptionMessage(de))); 678 return 1; 679 } 680 } 681 682 // Acquire an shared lock for the backend. 683 try 684 { 685 String lockFile = LockFileManager.getBackendLockFileName(backend); 686 StringBuilder failureReason = new StringBuilder(); 687 if (! LockFileManager.acquireSharedLock(lockFile, failureReason)) 688 { 689 Message message = ERR_DBTEST_CANNOT_LOCK_BACKEND.get( 690 backend.getBackendID(), String.valueOf(failureReason)); 691 printMessage(message); 692 return 1; 693 } 694 } 695 catch (Exception e) 696 { 697 Message message = ERR_DBTEST_CANNOT_LOCK_BACKEND.get( 698 backend.getBackendID(), getExceptionMessage(e)); 699 printMessage(message); 700 return 1; 701 } 702 703 RootContainer rc; 704 try 705 { 706 rc = backend.getReadOnlyRootContainer(); 707 } 708 catch(Exception e) 709 { 710 printMessage(ERR_DBTEST_ERROR_INITIALIZING_BACKEND.get( 711 backend.getBackendID(), 712 StaticUtils.stackTraceToSingleLineString(e))); 713 return 1; 714 } 715 716 717 try 718 { 719 // Create a table of their properties. 720 TableBuilder builder = new TableBuilder(); 721 int count = 0; 722 723 builder.appendHeading(INFO_LABEL_DBTEST_DATABASE_NAME.get()); 724 builder.appendHeading(INFO_LABEL_DBTEST_DATABASE_TYPE.get()); 725 builder.appendHeading(INFO_LABEL_DBTEST_JE_DATABASE_NAME.get()); 726 builder.appendHeading(INFO_LABEL_DBTEST_ENTRY_COUNT.get()); 727 728 if(base != null) 729 { 730 EntryContainer ec = rc.getEntryContainer(base); 731 732 if(ec == null) 733 { 734 printMessage(ERR_DBTEST_NO_ENTRY_CONTAINERS_FOR_BASE_DN.get( 735 base.toNormalizedString(), backend.getBackendID())); 736 return 1; 737 } 738 739 ArrayList<DatabaseContainer> databaseContainers = 740 new ArrayList<DatabaseContainer>(); 741 ec.listDatabases(databaseContainers); 742 for(DatabaseContainer dc : databaseContainers) 743 { 744 builder.startRow(); 745 builder.appendCell(dc.getName().replace(ec.getDatabasePrefix()+"_", 746 "")); 747 builder.appendCell(dc.getClass().getSimpleName()); 748 builder.appendCell(dc.getName()); 749 builder.appendCell(dc.getRecordCount()); 750 count++; 751 } 752 } 753 else 754 { 755 for(EntryContainer ec : rc.getEntryContainers()) 756 { 757 builder.startRow(); 758 ArrayList<DatabaseContainer> databaseContainers = 759 new ArrayList<DatabaseContainer>(); 760 ec.listDatabases(databaseContainers); 761 builder.appendCell("Base DN: " + 762 ec.getBaseDN().toNormalizedString()); 763 for(DatabaseContainer dc : databaseContainers) 764 { 765 builder.startRow(); 766 builder.appendCell(dc.getName().replace( 767 ec.getDatabasePrefix()+"_","")); 768 builder.appendCell(dc.getClass().getSimpleName()); 769 builder.appendCell(dc.getName()); 770 builder.appendCell(dc.getRecordCount()); 771 count++; 772 } 773 } 774 } 775 776 TextTablePrinter printer = new TextTablePrinter(out); 777 builder.print(printer); 778 out.format("%nTotal: %d%n", count); 779 return 0; 780 781 } 782 catch(DatabaseException de) 783 { 784 printMessage(ERR_DBTEST_ERROR_READING_DATABASE.get( 785 StaticUtils.stackTraceToSingleLineString(de))); 786 return 1; 787 } 788 finally 789 { 790 try 791 { 792 // Close the root container 793 rc.close(); 794 } 795 catch(DatabaseException de) 796 { 797 // Ignore. 798 } 799 800 // Release the shared lock on the backend. 801 try 802 { 803 String lockFile = LockFileManager.getBackendLockFileName(backend); 804 StringBuilder failureReason = new StringBuilder(); 805 if (! LockFileManager.releaseLock(lockFile, failureReason)) 806 { 807 Message message = WARN_DBTEST_CANNOT_UNLOCK_BACKEND.get( 808 backend.getBackendID(), String.valueOf(failureReason)); 809 printMessage(message); 810 } 811 } 812 catch (Exception e) 813 { 814 Message message = WARN_DBTEST_CANNOT_UNLOCK_BACKEND.get( 815 backend.getBackendID(), getExceptionMessage(e)); 816 printMessage(message); 817 } 818 } 819 } 820 821 private int listIndexStatus(Argument backendID, 822 Argument baseDN) 823 { 824 TreeMap<LocalDBBackendCfg, BackendImpl> jeBackends = getJEBackends(); 825 BackendImpl backend = null; 826 DN base = null; 827 828 for(BackendImpl b : jeBackends.values()) 829 { 830 if(b.getBackendID().equalsIgnoreCase(backendID.getValue())) 831 { 832 backend = b; 833 break; 834 } 835 } 836 837 if(backend == null) 838 { 839 printMessage(ERR_DBTEST_NO_BACKENDS_FOR_ID.get(backendID.getValue())); 840 return 1; 841 } 842 843 if(baseDN.isPresent()) 844 { 845 try 846 { 847 base = DN.decode(baseDN.getValue()); 848 } 849 catch(DirectoryException de) 850 { 851 printMessage(ERR_DBTEST_DECODE_BASE_DN.get(baseDN.getValue(), 852 getExceptionMessage(de))); 853 return 1; 854 } 855 } 856 857 // Acquire an shared lock for the backend. 858 try 859 { 860 String lockFile = LockFileManager.getBackendLockFileName(backend); 861 StringBuilder failureReason = new StringBuilder(); 862 if (! LockFileManager.acquireSharedLock(lockFile, failureReason)) 863 { 864 Message message = ERR_DBTEST_CANNOT_LOCK_BACKEND.get( 865 backend.getBackendID(), String.valueOf(failureReason)); 866 printMessage(message); 867 return 1; 868 } 869 } 870 catch (Exception e) 871 { 872 Message message = ERR_DBTEST_CANNOT_LOCK_BACKEND.get( 873 backend.getBackendID(), getExceptionMessage(e)); 874 printMessage(message); 875 return 1; 876 } 877 878 RootContainer rc; 879 try 880 { 881 rc = backend.getReadOnlyRootContainer(); 882 } 883 catch(Exception e) 884 { 885 printMessage(ERR_DBTEST_ERROR_INITIALIZING_BACKEND.get( 886 backend.getBackendID(), 887 StaticUtils.stackTraceToSingleLineString(e))); 888 return 1; 889 } 890 891 892 try 893 { 894 // Create a table of their properties. 895 TableBuilder builder = new TableBuilder(); 896 int count = 0; 897 898 builder.appendHeading(INFO_LABEL_DBTEST_INDEX_NAME.get()); 899 builder.appendHeading(INFO_LABEL_DBTEST_INDEX_TYPE.get()); 900 builder.appendHeading(INFO_LABEL_DBTEST_JE_DATABASE_NAME.get()); 901 builder.appendHeading(INFO_LABEL_DBTEST_INDEX_STATUS.get()); 902 903 EntryContainer ec = rc.getEntryContainer(base); 904 905 if(ec == null) 906 { 907 printMessage(ERR_DBTEST_NO_ENTRY_CONTAINERS_FOR_BASE_DN.get( 908 base.toNormalizedString(), backend.getBackendID())); 909 return 1; 910 } 911 912 ArrayList<DatabaseContainer> databaseContainers = 913 new ArrayList<DatabaseContainer>(); 914 ec.listDatabases(databaseContainers); 915 for(DatabaseContainer dc : databaseContainers) 916 { 917 if(dc instanceof Index || dc instanceof VLVIndex) 918 { 919 builder.startRow(); 920 builder.appendCell(dc.getName().replace(ec.getDatabasePrefix()+"_", 921 "")); 922 builder.appendCell(dc.getClass().getSimpleName()); 923 builder.appendCell(dc.getName()); 924 if(dc instanceof Index) 925 { 926 builder.appendCell(ec.getState().getIndexTrustState(null, 927 ((Index)dc))); 928 } 929 else if(dc instanceof VLVIndex) 930 { 931 builder.appendCell(ec.getState().getIndexTrustState(null, 932 ((VLVIndex)dc))); 933 } 934 count++; 935 } 936 } 937 938 TextTablePrinter printer = new TextTablePrinter(out); 939 builder.print(printer); 940 out.format("%nTotal: %d%n", count); 941 return 0; 942 } 943 catch(DatabaseException de) 944 { 945 printMessage(ERR_DBTEST_ERROR_READING_DATABASE.get( 946 StaticUtils.stackTraceToSingleLineString(de))); 947 return 1; 948 } 949 finally 950 { 951 try 952 { 953 // Close the root container 954 rc.close(); 955 } 956 catch(DatabaseException de) 957 { 958 // Ignore. 959 } 960 961 // Release the shared lock on the backend. 962 try 963 { 964 String lockFile = LockFileManager.getBackendLockFileName(backend); 965 StringBuilder failureReason = new StringBuilder(); 966 if (! LockFileManager.releaseLock(lockFile, failureReason)) 967 { 968 Message message = WARN_DBTEST_CANNOT_UNLOCK_BACKEND.get( 969 backend.getBackendID(), String.valueOf(failureReason)); 970 printMessage(message); 971 } 972 } 973 catch (Exception e) 974 { 975 Message message = WARN_DBTEST_CANNOT_UNLOCK_BACKEND.get( 976 backend.getBackendID(), getExceptionMessage(e)); 977 printMessage(message); 978 } 979 } 980 } 981 982 private int dumpDatabaseContainer(Argument backendID, Argument baseDN, 983 Argument databaseName, Argument skipDecode, 984 Argument maxKeyValue, Argument minKeyValue, 985 Argument maxDataSize, 986 Argument minDataSize) 987 { 988 TreeMap<LocalDBBackendCfg, BackendImpl> jeBackends = getJEBackends(); 989 BackendImpl backend = null; 990 DN base = null; 991 992 for(BackendImpl b : jeBackends.values()) 993 { 994 if(b.getBackendID().equalsIgnoreCase(backendID.getValue())) 995 { 996 backend = b; 997 break; 998 } 999 } 1000 1001 if(backend == null) 1002 { 1003 printMessage(ERR_DBTEST_NO_BACKENDS_FOR_ID.get(backendID.getValue())); 1004 return 1; 1005 } 1006 1007 try 1008 { 1009 base = DN.decode(baseDN.getValue()); 1010 } 1011 catch(DirectoryException de) 1012 { 1013 printMessage(ERR_DBTEST_DECODE_BASE_DN.get(baseDN.getValue(), 1014 getExceptionMessage(de))); 1015 return 1; 1016 } 1017 1018 // Acquire an shared lock for the backend. 1019 try 1020 { 1021 String lockFile = LockFileManager.getBackendLockFileName(backend); 1022 StringBuilder failureReason = new StringBuilder(); 1023 if (! LockFileManager.acquireSharedLock(lockFile, failureReason)) 1024 { 1025 Message message = ERR_DBTEST_CANNOT_LOCK_BACKEND.get( 1026 backend.getBackendID(), String.valueOf(failureReason)); 1027 printMessage(message); 1028 return 1; 1029 } 1030 } 1031 catch (Exception e) 1032 { 1033 Message message = ERR_DBTEST_CANNOT_LOCK_BACKEND.get( 1034 backend.getBackendID(), getExceptionMessage(e)); 1035 printMessage(message); 1036 return 1; 1037 } 1038 1039 RootContainer rc; 1040 try 1041 { 1042 rc = backend.getReadOnlyRootContainer(); 1043 } 1044 catch(Exception e) 1045 { 1046 printMessage(ERR_DBTEST_ERROR_INITIALIZING_BACKEND.get( 1047 backend.getBackendID(), 1048 StaticUtils.stackTraceToSingleLineString(e))); 1049 return 1; 1050 } 1051 1052 try 1053 { 1054 EntryContainer ec = rc.getEntryContainer(base); 1055 1056 if(ec == null) 1057 { 1058 printMessage(ERR_DBTEST_NO_ENTRY_CONTAINERS_FOR_BASE_DN.get( 1059 base.toNormalizedString(), backend.getBackendID())); 1060 return 1; 1061 } 1062 1063 DatabaseContainer databaseContainer = null; 1064 ArrayList<DatabaseContainer> databaseContainers = 1065 new ArrayList<DatabaseContainer>(); 1066 ec.listDatabases(databaseContainers); 1067 for(DatabaseContainer dc : databaseContainers) 1068 { 1069 if(dc.getName().replace(ec.getDatabasePrefix()+"_",""). 1070 equalsIgnoreCase(databaseName.getValue())) 1071 { 1072 databaseContainer = dc; 1073 break; 1074 } 1075 } 1076 1077 if(databaseContainer == null) 1078 { 1079 printMessage(ERR_DBTEST_NO_DATABASE_CONTAINERS_FOR_NAME.get( 1080 databaseName.getValue(), base.toNormalizedString(), 1081 backend.getBackendID())); 1082 return 1; 1083 } 1084 1085 int count = 0; 1086 long totalKeySize = 0; 1087 long totalDataSize = 0; 1088 int indent = 4; 1089 1090 Cursor cursor = 1091 databaseContainer.openCursor(null, CursorConfig.DEFAULT); 1092 1093 try 1094 { 1095 DatabaseEntry key = new DatabaseEntry(); 1096 DatabaseEntry data = new DatabaseEntry(); 1097 LockMode lockMode = LockMode.DEFAULT; 1098 OperationStatus status; 1099 Comparator<byte[]> defaultComparator = 1100 new AttributeIndex.KeyComparator(); 1101 Comparator<byte[]> dnComparator = 1102 new EntryContainer.KeyReverseComparator(); 1103 byte[] start = null; 1104 byte[] end = null; 1105 int minSize = -1; 1106 int maxSize = -1; 1107 1108 if(maxDataSize.isPresent()) 1109 { 1110 try 1111 { 1112 maxSize = maxDataSize.getIntValue(); 1113 } 1114 catch(Exception e) 1115 { 1116 printMessage(ERR_DBTEST_CANNOT_DECODE_SIZE.get( 1117 maxDataSize.getValue(), getExceptionMessage(e))); 1118 return 1; 1119 } 1120 } 1121 1122 if(minDataSize.isPresent()) 1123 { 1124 try 1125 { 1126 minSize = minDataSize.getIntValue(); 1127 } 1128 catch(Exception e) 1129 { 1130 printMessage(ERR_DBTEST_CANNOT_DECODE_SIZE.get( 1131 minDataSize.getValue(), getExceptionMessage(e))); 1132 return 1; 1133 } 1134 } 1135 1136 // Parse the min value if given 1137 if(minKeyValue.isPresent()) 1138 { 1139 try 1140 { 1141 if(minKeyValue.getValue().startsWith("0x")) 1142 { 1143 start = 1144 StaticUtils.hexStringToByteArray(minKeyValue.getValue(). 1145 substring(2)); 1146 } 1147 else 1148 { 1149 if(databaseContainer instanceof DN2ID || 1150 databaseContainer instanceof DN2URI) 1151 { 1152 // Encode the value as a DN 1153 start = StaticUtils.getBytes( 1154 DN.decode(minKeyValue.getValue()).toNormalizedString()); 1155 } 1156 else if(databaseContainer instanceof ID2Entry) 1157 { 1158 // Encode the value as an entryID 1159 start = JebFormat.entryIDToDatabase( 1160 Long.parseLong(minKeyValue.getValue())); 1161 } 1162 else if(databaseContainer instanceof VLVIndex) 1163 { 1164 // Encode the value as a size/value pair 1165 byte[] vBytes = 1166 new ASN1OctetString(minKeyValue.getValue()).value(); 1167 byte[] vLength = ASN1Element.encodeLength(vBytes.length); 1168 start = new byte[vBytes.length + vLength.length]; 1169 System.arraycopy(vLength, 0, start, 0, vLength.length); 1170 System.arraycopy(vBytes, 0, start, vLength.length, 1171 vBytes.length); 1172 } 1173 else 1174 { 1175 start = new ASN1OctetString(minKeyValue.getValue()).value(); 1176 } 1177 } 1178 } 1179 catch(Exception e) 1180 { 1181 printMessage(ERR_DBTEST_CANNOT_DECODE_KEY.get( 1182 minKeyValue.getValue(), getExceptionMessage(e))); 1183 return 1; 1184 } 1185 } 1186 1187 // Parse the max value if given 1188 if(maxKeyValue.isPresent()) 1189 { 1190 try 1191 { 1192 if(maxKeyValue.getValue().startsWith("0x")) 1193 { 1194 end = 1195 StaticUtils.hexStringToByteArray(maxKeyValue.getValue(). 1196 substring(2)); 1197 } 1198 else 1199 { 1200 if(databaseContainer instanceof DN2ID || 1201 databaseContainer instanceof DN2URI) 1202 { 1203 // Encode the value as a DN 1204 end = StaticUtils.getBytes( 1205 DN.decode(maxKeyValue.getValue()).toNormalizedString()); 1206 } 1207 else if(databaseContainer instanceof ID2Entry) 1208 { 1209 // Encode the value as an entryID 1210 end = JebFormat.entryIDToDatabase( 1211 Long.parseLong(maxKeyValue.getValue())); 1212 } 1213 else if(databaseContainer instanceof VLVIndex) 1214 { 1215 // Encode the value as a size/value pair 1216 byte[] vBytes = 1217 new ASN1OctetString(maxKeyValue.getValue()).value(); 1218 byte[] vLength = ASN1Element.encodeLength(vBytes.length); 1219 end = new byte[vBytes.length + vLength.length]; 1220 System.arraycopy(vLength, 0, end, 0, vLength.length); 1221 System.arraycopy(vBytes, 0, end, vLength.length, 1222 vBytes.length); 1223 } 1224 else 1225 { 1226 end = new ASN1OctetString(maxKeyValue.getValue()).value(); 1227 } 1228 } 1229 } 1230 catch(Exception e) 1231 { 1232 printMessage(ERR_DBTEST_CANNOT_DECODE_KEY.get( 1233 maxKeyValue.getValue(), getExceptionMessage(e))); 1234 return 1; 1235 } 1236 } 1237 1238 1239 if(start != null) 1240 { 1241 key.setData(start); 1242 status = cursor.getSearchKey(key, data, lockMode); 1243 } 1244 else 1245 { 1246 status = cursor.getFirst(key, data, lockMode); 1247 } 1248 1249 while(status == OperationStatus.SUCCESS) 1250 { 1251 // Make sure this record is within the value size params 1252 if((minSize > 0 && data.getSize() < minSize) || 1253 (maxSize > 0 && data.getSize() > maxSize)) 1254 { 1255 status = cursor.getNext(key, data, lockMode); 1256 continue; 1257 } 1258 1259 // Make sure we haven't gone pass the max value yet 1260 if(end != null) 1261 { 1262 if(databaseContainer instanceof DN2ID) 1263 { 1264 if(dnComparator.compare(key.getData(), end) > 0) 1265 { 1266 break; 1267 } 1268 } 1269 else if(databaseContainer instanceof DN2URI) 1270 { 1271 if(dnComparator.compare(key.getData(), end) > 0) 1272 { 1273 break; 1274 } 1275 } 1276 else if(databaseContainer instanceof Index) 1277 { 1278 if(((Index)databaseContainer).indexer.getComparator(). 1279 compare(key.getData(), end) > 0) 1280 { 1281 break; 1282 } 1283 } 1284 else if(databaseContainer instanceof VLVIndex) 1285 { 1286 if(((VLVIndex)databaseContainer).comparator. 1287 compare(key.getData(), end) > 0) 1288 { 1289 break; 1290 } 1291 } 1292 else 1293 { 1294 if(defaultComparator.compare(key.getData(), 1295 end) > 0) 1296 { 1297 break; 1298 } 1299 } 1300 } 1301 1302 Message keyLabel = INFO_LABEL_DBTEST_KEY.get(); 1303 Message dataLabel = INFO_LABEL_DBTEST_DATA.get(); 1304 1305 String formatedKey = null; 1306 String formatedData = null; 1307 1308 if(!skipDecode.isPresent()) 1309 { 1310 if(databaseContainer instanceof DN2ID) 1311 { 1312 try 1313 { 1314 formatedKey = DN.decode(new ASN1OctetString( 1315 key.getData())).toNormalizedString(); 1316 keyLabel = INFO_LABEL_DBTEST_ENTRY_DN.get(); 1317 } 1318 catch(Exception e) 1319 { 1320 Message message = 1321 ERR_DBTEST_DECODE_FAIL.get(getExceptionMessage(e)); 1322 printMessage(message); 1323 } 1324 formatedData = String.valueOf( 1325 JebFormat.entryIDFromDatabase(data.getData())); 1326 dataLabel = INFO_LABEL_DBTEST_ENTRY_ID.get(); 1327 } 1328 else if(databaseContainer instanceof ID2Entry) 1329 { 1330 formatedKey = String.valueOf( 1331 JebFormat.entryIDFromDatabase(key.getData())); 1332 keyLabel = INFO_LABEL_DBTEST_ENTRY_ID.get(); 1333 try 1334 { 1335 formatedData = System.getProperty("line.separator") + 1336 JebFormat.entryFromDatabase(data.getData(), 1337 ec.getRootContainer().getCompressedSchema()). 1338 toLDIFString(); 1339 dataLabel = INFO_LABEL_DBTEST_ENTRY.get(); 1340 } 1341 catch(Exception e) 1342 { 1343 Message message = 1344 ERR_DBTEST_DECODE_FAIL.get(getExceptionMessage(e)); 1345 printMessage(message); 1346 } 1347 } 1348 else if(databaseContainer instanceof DN2URI) 1349 { 1350 try 1351 { 1352 formatedKey = DN.decode(new ASN1OctetString( 1353 key.getData())).toNormalizedString(); 1354 keyLabel = INFO_LABEL_DBTEST_ENTRY_DN.get(); 1355 } 1356 catch(Exception e) 1357 { 1358 Message message = 1359 ERR_DBTEST_DECODE_FAIL.get(getExceptionMessage(e)); 1360 printMessage(message); 1361 } 1362 formatedData = new ASN1OctetString(key.getData()).stringValue(); 1363 dataLabel = INFO_LABEL_DBTEST_URI.get(); 1364 } 1365 else if(databaseContainer instanceof Index) 1366 { 1367 formatedKey = new ASN1OctetString(key.getData()).stringValue(); 1368 keyLabel = INFO_LABEL_DBTEST_INDEX_VALUE.get(); 1369 1370 EntryIDSet idSet = new EntryIDSet(key.getData(), 1371 data.getData()); 1372 if(idSet.isDefined()) 1373 { 1374 int lineCount = 0; 1375 StringBuilder builder = new StringBuilder(); 1376 1377 Iterator<EntryID> i = idSet.iterator(); 1378 while(i.hasNext()) 1379 { 1380 builder.append(i.next()); 1381 if(lineCount == 10) 1382 { 1383 builder.append(System.getProperty("line.separator")); 1384 lineCount = 0; 1385 } 1386 else 1387 { 1388 builder.append(" "); 1389 lineCount++; 1390 } 1391 } 1392 formatedData = builder.toString(); 1393 } 1394 else 1395 { 1396 formatedData = idSet.toString(); 1397 } 1398 dataLabel = INFO_LABEL_DBTEST_INDEX_ENTRY_ID_LIST.get(); 1399 } 1400 else if(databaseContainer instanceof VLVIndex) 1401 { 1402 VLVIndex index = (VLVIndex)databaseContainer; 1403 SortKey[] sortKeys = index.sortOrder.getSortKeys(); 1404 1405 int pos = 0; 1406 byte[] keyBytes = key.getData(); 1407 if(keyBytes.length > 0) 1408 { 1409 StringBuilder builder = new StringBuilder(); 1410 1411 // Decode the attribute values 1412 for(SortKey sortKey : sortKeys) 1413 { 1414 int valueLength = keyBytes[pos] & 0x7F; 1415 if (keyBytes[pos++] != valueLength) 1416 { 1417 int numLengthBytes = valueLength; 1418 valueLength = 0; 1419 for (int k=0; k < numLengthBytes; k++, pos++) 1420 { 1421 valueLength = (valueLength << 8) | 1422 (keyBytes[pos] & 0xFF); 1423 } 1424 } 1425 1426 byte[] valueBytes = new byte[valueLength]; 1427 System.arraycopy(keyBytes, pos, valueBytes, 0, 1428 valueLength); 1429 builder.append(sortKey.getAttributeType().getNameOrOID()); 1430 builder.append(": "); 1431 if(valueBytes.length == 0) 1432 { 1433 builder.append("NULL"); 1434 } 1435 else 1436 { 1437 builder.append( 1438 new ASN1OctetString(valueBytes).stringValue()); 1439 } 1440 builder.append(" "); 1441 pos += valueLength; 1442 } 1443 1444 byte[] entryIDBytes = new byte[8]; 1445 System.arraycopy(keyBytes, pos, entryIDBytes, 0, 1446 entryIDBytes.length); 1447 long entryID = JebFormat.entryIDFromDatabase(entryIDBytes); 1448 1449 formatedKey = System.getProperty("line.separator") + 1450 String.valueOf(entryID) + ": " + builder.toString(); 1451 } 1452 else 1453 { 1454 formatedKey = "UNBOUNDED"; 1455 } 1456 keyLabel = INFO_LABEL_DBTEST_VLV_INDEX_LAST_SORT_KEYS.get(); 1457 1458 try 1459 { 1460 StringBuilder builder = new StringBuilder(); 1461 SortValuesSet svs = new SortValuesSet(key.getData(), 1462 data.getData(), 1463 index); 1464 long[] entryIDs = svs.getEntryIDs(); 1465 for(int i = 0; i < entryIDs.length; i++) 1466 { 1467 builder.append(String.valueOf(entryIDs[i])); 1468 builder.append(": "); 1469 for(int j = 0; j < sortKeys.length; j++) 1470 { 1471 SortKey sortKey = index.sortOrder.getSortKeys()[j]; 1472 byte[] value = svs.getValue(i * sortKeys.length + j); 1473 builder.append(sortKey.getAttributeType().getNameOrOID()); 1474 builder.append(": "); 1475 if(value == null) 1476 { 1477 builder.append("NULL"); 1478 } 1479 else if(value.length == 0) 1480 { 1481 builder.append("SIZE-EXCEEDED"); 1482 } 1483 else 1484 { 1485 builder.append( 1486 new ASN1OctetString(value).stringValue()); 1487 } 1488 builder.append(" "); 1489 } 1490 builder.append(System.getProperty("line.separator")); 1491 } 1492 formatedData = System.getProperty("line.separator") + 1493 builder.toString(); 1494 dataLabel = INFO_LABEL_DBTEST_INDEX_ENTRY_ID_LIST.get(); 1495 } 1496 catch(Exception e) 1497 { 1498 Message message = 1499 ERR_DBTEST_DECODE_FAIL.get(getExceptionMessage(e)); 1500 printMessage(message); 1501 } 1502 } 1503 } 1504 1505 if(formatedKey == null) 1506 { 1507 StringBuilder keyBuilder = new StringBuilder(); 1508 StaticUtils.byteArrayToHexPlusAscii(keyBuilder, key.getData(), 1509 indent); 1510 formatedKey = System.getProperty("line.separator") + 1511 keyBuilder.toString(); 1512 } 1513 if(formatedData == null) 1514 { 1515 StringBuilder dataBuilder = new StringBuilder(); 1516 StaticUtils.byteArrayToHexPlusAscii(dataBuilder, data.getData(), 1517 indent); 1518 formatedData = System.getProperty("line.separator") + 1519 dataBuilder.toString(); 1520 } 1521 1522 out.format("%s (%d bytes): %s%n", keyLabel, 1523 key.getData().length, formatedKey); 1524 out.format("%s (%d bytes): %s%n%n", dataLabel, 1525 data.getData().length, formatedData); 1526 1527 status = cursor.getNext(key, data, lockMode); 1528 count++; 1529 totalKeySize += key.getData().length; 1530 totalDataSize += data.getData().length; 1531 } 1532 } 1533 finally 1534 { 1535 cursor.close(); 1536 } 1537 out.format("%nTotal Records: %d%n", count); 1538 if(count > 0) 1539 { 1540 out.format("Total / Average Key Size: %d bytes / %d bytes%n", 1541 totalKeySize, totalKeySize / count); 1542 out.format("Total / Average Data Size: %d bytes / %d bytes%n", 1543 totalDataSize, totalDataSize / count); 1544 } 1545 return 0; 1546 } 1547 catch(DatabaseException de) 1548 { 1549 printMessage(ERR_DBTEST_ERROR_READING_DATABASE.get( 1550 StaticUtils.stackTraceToSingleLineString(de))); 1551 return 1; 1552 } 1553 finally 1554 { 1555 try 1556 { 1557 // Close the root container 1558 rc.close(); 1559 } 1560 catch(DatabaseException de) 1561 { 1562 // Ignore. 1563 } 1564 1565 // Release the shared lock on the backend. 1566 try 1567 { 1568 String lockFile = LockFileManager.getBackendLockFileName(backend); 1569 StringBuilder failureReason = new StringBuilder(); 1570 if (! LockFileManager.releaseLock(lockFile, failureReason)) 1571 { 1572 Message message = WARN_DBTEST_CANNOT_UNLOCK_BACKEND.get( 1573 backend.getBackendID(), String.valueOf(failureReason)); 1574 printMessage(message); 1575 } 1576 } 1577 catch (Exception e) 1578 { 1579 Message message = WARN_DBTEST_CANNOT_UNLOCK_BACKEND.get( 1580 backend.getBackendID(), getExceptionMessage(e)); 1581 printMessage(message); 1582 } 1583 } 1584 } 1585 1586 private TreeMap<LocalDBBackendCfg, BackendImpl> getJEBackends() 1587 { 1588 ArrayList<Backend> backendList = new ArrayList<Backend>(); 1589 ArrayList<BackendCfg> entryList = new ArrayList<BackendCfg>(); 1590 ArrayList<List<DN>> dnList = new ArrayList<List<DN>>(); 1591 int code = BackendToolUtils.getBackends(backendList, entryList, dnList); 1592 // TODO: Throw error if return code is not 0 1593 1594 TreeMap<LocalDBBackendCfg, BackendImpl> jeBackends = 1595 new TreeMap<LocalDBBackendCfg, BackendImpl>(); 1596 for(int i = 0; i < backendList.size(); i++) 1597 { 1598 Backend backend = backendList.get(i); 1599 if(backend instanceof BackendImpl) 1600 { 1601 jeBackends.put((LocalDBBackendCfg)entryList.get(i), 1602 (BackendImpl)backend); 1603 } 1604 } 1605 1606 return jeBackends; 1607 } 1608 1609 /** 1610 * Displays a message to the error stream. 1611 * 1612 * @param msg 1613 * The message. 1614 */ 1615 public final void printMessage(Message msg) { 1616 err.println(wrapText(msg.toString(), MAX_LINE_WIDTH)); 1617 } 1618 }