opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendStat.java
@@ -314,6 +314,7 @@ */ public static int main(String[] args, OutputStream outStream, OutputStream errStream) { JDKLogging.disableLogging(); BackendStat app = new BackendStat(outStream, errStream); return app.run(args); } @@ -328,7 +329,6 @@ { this.out = NullOutputStream.wrapOrNullStream(out); this.err = NullOutputStream.wrapOrNullStream(err); JDKLogging.disableLogging(); LocalizableMessage toolDescription = INFO_DESCRIPTION_BACKEND_TOOL.get(); this.parser = new SubCommandArgumentParser(getClass().getName(), toolDescription, false); @@ -1022,10 +1022,40 @@ try { EntryContainer ec = rc.getEntryContainer(base); if (ec == null) { return printEntryContainerError(backend, base); } // Create a table of their properties. TableBuilder builder = new TableBuilder(); int count = 0; Map<Index, StringBuilder> undefinedKeys = new HashMap<>(); int count = appendIndexStatusTable(builder, ec, undefinedKeys); builder.print(new TextTablePrinter(out)); out.print(INFO_LABEL_BACKEND_TOOL_TOTAL.get(count).toString()); for (Map.Entry<Index, StringBuilder> e : undefinedKeys.entrySet()) { out.print(INFO_LABEL_BACKEND_TOOL_INDEX.get(e.getKey().getName()).toString()); out.print(INFO_LABEL_BACKEND_TOOL_OVER_INDEX_LIMIT_KEYS.get(e.getValue()).toString()); } return 0; } catch (StorageRuntimeException de) { printWrappedText(err, ERR_BACKEND_TOOL_ERROR_READING_TREE.get(stackTraceToSingleLineString(de))); return 1; } } /** * Fills the table {@code show-index-status} prints for the indexes of an entry container, a row * per index, and returns the number of its rows. The keys of an index that are over its entry * limit are collected into {@code undefinedKeys}. */ int appendIndexStatusTable(TableBuilder builder, EntryContainer ec, Map<Index, StringBuilder> undefinedKeys) { builder.appendHeading(INFO_LABEL_BACKEND_DEBUG_INDEX_NAME.get()); builder.appendHeading(INFO_LABEL_BACKEND_TOOL_RAW_DB_NAME.get()); builder.appendHeading(INFO_LABEL_BACKEND_DEBUG_INDEX_STATUS.get()); @@ -1036,13 +1066,7 @@ builder.appendHeading(LocalizableMessage.raw("90%")); builder.appendHeading(LocalizableMessage.raw("85%")); EntryContainer ec = rc.getEntryContainer(base); if (ec == null) { return printEntryContainerError(backend, base); } Map<Index, StringBuilder> undefinedKeys = new HashMap<>(); int count = 0; for (AttributeIndex attrIndex : ec.getAttributeIndexes()) { for (AttributeIndex.MatchingRuleIndex index : attrIndex.getNameToIndexes().values()) @@ -1070,25 +1094,13 @@ builder.appendCell(vlvIndex.getName().getIndexId()); builder.appendCell(vlvIndex.getName()); builder.appendCell(vlvIndex.isTrusted()); // A VLV index has no confidentiality setting, but its row still needs the cell of that column appendStatsNoData(builder, 1); builder.appendCell(getTreeRecordCount(ec, vlvIndex)); appendStatsNoData(builder, 4); count++; } builder.print(new TextTablePrinter(out)); out.print(INFO_LABEL_BACKEND_TOOL_TOTAL.get(count).toString()); for (Map.Entry<Index, StringBuilder> e : undefinedKeys.entrySet()) { out.print(INFO_LABEL_BACKEND_TOOL_INDEX.get(e.getKey().getName()).toString()); out.print(INFO_LABEL_BACKEND_TOOL_OVER_INDEX_LIMIT_KEYS.get(e.getValue()).toString()); } return 0; } catch (StorageRuntimeException de) { printWrappedText(err, ERR_BACKEND_TOOL_ERROR_READING_TREE.get(stackTraceToSingleLineString(de))); return 1; } return count; } private void appendStatsNoData(TableBuilder builder, int columns) opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
@@ -18,6 +18,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.forgerock.opendj.ldap.ModificationType.*; import static org.opends.messages.ToolMessages.INFO_LABEL_BACKEND_DEBUG_INDEX_CONFIDENTIAL; import static org.opends.messages.ToolMessages.INFO_LABEL_BACKEND_DEBUG_RECORD_COUNT; import static org.mockito.Mockito.*; import static org.opends.server.protocols.internal.InternalClientConnection.getRootConnection; import static org.opends.server.protocols.internal.Requests.newSearchRequest; @@ -39,6 +41,9 @@ import java.util.concurrent.atomic.AtomicBoolean; import com.google.common.io.Resources; import com.forgerock.opendj.cli.TableBuilder; import com.forgerock.opendj.cli.TablePrinter; import com.forgerock.opendj.cli.TableSerializer; import org.forgerock.opendj.ldap.*; import org.forgerock.opendj.ldap.schema.AttributeType; import org.forgerock.opendj.ldap.schema.CoreSchema; @@ -1178,6 +1183,88 @@ assertThat(backend.verifyBackend(config)).isEqualTo(0); } /** * Every row {@code backendstat show-index-status} prints has a cell under each of its headings. * A VLV index, which has no confidentiality, shows {@code -} under Confidential, so that its * record count lands under Record Count; the key counts that follow are {@code -} as well. */ @Test public void testShowIndexStatusPutsEachCellOfAVlvRowUnderItsHeading() throws Exception { final EntryContainer ec = backend.getRootContainer().getEntryContainer(testBaseDN); final VLVIndex vlvIndex = ec.getVLVIndexes().iterator().next(); final long recordCount = backend.getRootContainer().getStorage().read(new ReadOperation<Long>() { @Override public Long run(ReadableTransaction txn) throws Exception { return vlvIndex.getRecordCount(txn); } }); final ByteArrayOutputStream err = new ByteArrayOutputStream(); final TableBuilder builder = new TableBuilder(); final int count = new BackendStat(null, err).appendIndexStatusTable(builder, ec, new HashMap<Index, StringBuilder>()); final CapturedTable table = new CapturedTable(); builder.print(table); assertThat(err.toString()).as("errors").isEmpty(); assertThat(table.rows).hasSize(count); for (List<String> row : table.rows) { assertThat(row).as("the cells of " + row.get(0) + " under " + table.headings).doesNotContain(""); } List<String> vlvRow = null; for (List<String> row : table.rows) { if (row.get(0).equals(vlvIndex.getName().getIndexId())) { vlvRow = row; } } assertThat(vlvRow).as("the row of " + vlvIndex.getName()).isNotNull(); final int confidential = table.headings.indexOf(INFO_LABEL_BACKEND_DEBUG_INDEX_CONFIDENTIAL.get().toString()); final int recordCountColumn = table.headings.indexOf(INFO_LABEL_BACKEND_DEBUG_RECORD_COUNT.get().toString()); assertThat(vlvRow.get(confidential)).as(table.headings.get(confidential)).isEqualTo("-"); assertThat(vlvRow.get(recordCountColumn)).as(table.headings.get(recordCountColumn)) .isEqualTo(String.valueOf(recordCount)); assertThat(vlvRow.subList(recordCountColumn + 1, vlvRow.size())).containsExactly("-", "-", "-", "-"); } /** The headings and the cells of a table, as a table printer is handed them. */ private static final class CapturedTable extends TablePrinter { private final List<String> headings = new ArrayList<>(); private final List<List<String>> rows = new ArrayList<>(); @Override protected TableSerializer getSerializer() { return new TableSerializer() { @Override public void addHeading(String s) { headings.add(s); } @Override public void startRow() { rows.add(new ArrayList<String>()); } @Override public void addCell(String s) { rows.get(rows.size() - 1).add(s); } }; } } @Test public void testRebuildDegradedIndex() throws Exception {