This is an automated email from the ASF dual-hosted git repository.

sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new 7ad5849  Migrate command `regenerate-interleaved-storage-index-file`
7ad5849 is described below

commit 7ad5849b1b0d9dbf2274a6fd00ad26f7286f7cff
Author: Yong Zhang <[email protected]>
AuthorDate: Tue Apr 9 20:00:26 2019 +0800

    Migrate command `regenerate-interleaved-storage-index-file`
    
    Descriptions of the changes in this PR:
    
    #2033
    
    ```
    Regenerate an interleaved storage index file, from available entrylogger 
files.
    
    Usage:  bkctl bookie regenerate-interleaved-storage-index-file [flags]
    
    Flags:
    
        -b, --b64password
            The password in base64 encoding, for cases where the password is not
            UTF-8.
    
        -d, --dryrun
            Process the entryLogger, but don't write anthing.
    
        -l, --ledgerids
            Ledger(s) whose index needs to be regenerated. Multiple can be
            specified, comma separated.
    
        -p, --password
            The bookie stores the password in the index file, so we need it to
            regenerate.This must match the value in the ledger metadata.
    
    
        -h, --help
            Display help information
    ```
    
    
    Reviewers: Sijie Guo <[email protected]>
    
    This closes #2035 from zymap/command-RISIF
---
 .../org/apache/bookkeeper/bookie/BookieShell.java  |  29 ++---
 ...generateInterleavedStorageIndexFileCommand.java | 133 +++++++++++++++++++++
 .../tools/cli/commands/BookieCommandGroup.java     |   2 +
 ...rateInterleavedStorageIndexFileCommandTest.java |  85 +++++++++++++
 4 files changed, 232 insertions(+), 17 deletions(-)

diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
index 4446903..4de4aa7 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
@@ -18,7 +18,6 @@
 
 package org.apache.bookkeeper.bookie;
 
-import static java.nio.charset.StandardCharsets.UTF_8;
 import static 
org.apache.bookkeeper.meta.MetadataDrivers.runFunctionWithLedgerManagerFactory;
 import static 
org.apache.bookkeeper.meta.MetadataDrivers.runFunctionWithMetadataBookieDriver;
 import static 
org.apache.bookkeeper.meta.MetadataDrivers.runFunctionWithRegistrationManager;
@@ -39,7 +38,6 @@ import java.nio.file.attribute.BasicFileAttributes;
 import java.nio.file.attribute.FileTime;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Base64;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -48,7 +46,6 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import org.apache.bookkeeper.bookie.BookieException.CookieNotFoundException;
@@ -84,6 +81,7 @@ import 
org.apache.bookkeeper.tools.cli.commands.bookie.ReadJournalCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookie.ReadLedgerCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookie.ReadLogCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookie.ReadLogMetadataCommand;
+import 
org.apache.bookkeeper.tools.cli.commands.bookie.RegenerateInterleavedStorageIndexFileCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookie.SanityTestCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookies.DecommissionCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookies.InfoCommand;
@@ -2173,23 +2171,20 @@ public class BookieShell implements Tool {
 
         @Override
         int runCmd(CommandLine cmdLine) throws Exception {
-            byte[] password;
+            RegenerateInterleavedStorageIndexFileCommand cmd = new 
RegenerateInterleavedStorageIndexFileCommand();
+            RegenerateInterleavedStorageIndexFileCommand.RISIFFlags
+                flags = new 
RegenerateInterleavedStorageIndexFileCommand.RISIFFlags();
+            List<Long> ledgerIds = 
Arrays.stream(cmdLine.getOptionValues("ledgerIds")).map((id) -> 
Long.parseLong(id))
+                                         .collect(Collectors.toList());
+            boolean dryRun = cmdLine.hasOption("dryRun");
+            flags.ledgerIds(ledgerIds);
             if (cmdLine.hasOption("password")) {
-                password = cmdLine.getOptionValue("password").getBytes(UTF_8);
+                flags.password(cmdLine.getOptionValue("password"));
             } else if (cmdLine.hasOption("b64password")) {
-                password = 
Base64.getDecoder().decode(cmdLine.getOptionValue("b64password"));
-            } else {
-                LOG.error("The password must be specified to regenerate the 
index file.");
-                return 1;
+                flags.b64Password(cmdLine.getOptionValue("b64password"));
             }
-            Set<Long> ledgerIds = 
Arrays.stream(cmdLine.getOptionValues("ledgerIds"))
-                .map((id) -> Long.parseLong(id)).collect(Collectors.toSet());
-            boolean dryRun = cmdLine.hasOption("dryRun");
-
-            LOG.info("=== Rebuilding index file for {} ===", ledgerIds);
-            ServerConfiguration conf = new ServerConfiguration(bkConf);
-            new InterleavedStorageRegenerateIndexOp(conf, ledgerIds, 
password).initiate(dryRun);
-            LOG.info("-- Done rebuilding index file for {} --", ledgerIds);
+            flags.dryRun(dryRun);
+            cmd.apply(bkConf, flags);
             return 0;
         }
     }
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/bookie/RegenerateInterleavedStorageIndexFileCommand.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/bookie/RegenerateInterleavedStorageIndexFileCommand.java
new file mode 100644
index 0000000..bbf933f
--- /dev/null
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/bookie/RegenerateInterleavedStorageIndexFileCommand.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bookkeeper.tools.cli.commands.bookie;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.converters.CommaParameterSplitter;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+import org.apache.bookkeeper.bookie.InterleavedStorageRegenerateIndexOp;
+import org.apache.bookkeeper.conf.ServerConfiguration;
+import org.apache.bookkeeper.tools.cli.helpers.BookieCommand;
+import org.apache.bookkeeper.tools.framework.CliFlags;
+import org.apache.bookkeeper.tools.framework.CliSpec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Command to regenerate an index file for interleaved storage.
+ */
+public class RegenerateInterleavedStorageIndexFileCommand
+    extends 
BookieCommand<RegenerateInterleavedStorageIndexFileCommand.RISIFFlags> {
+
+    static final Logger LOG = 
LoggerFactory.getLogger(RegenerateInterleavedStorageIndexFileCommand.class);
+
+    private static final String NAME = 
"regenerate-interleaved-storage-index-file";
+    private static final String DESC =
+        "Regenerate an interleaved storage index file, from available 
entrylogger " + "files.";
+    private static final String DEFAULT = "";
+
+    public RegenerateInterleavedStorageIndexFileCommand() {
+        this(new RISIFFlags());
+    }
+
+    private RegenerateInterleavedStorageIndexFileCommand(RISIFFlags flags) {
+        super(CliSpec.<RISIFFlags>newBuilder()
+                  .withName(NAME)
+                  .withDescription(DESC)
+                  .withFlags(flags)
+                  .build());
+    }
+
+    /**
+     * Flags for regenerate interleaved storage index file command.
+     */
+    @Accessors(fluent = true)
+    @Setter
+    public static class RISIFFlags extends CliFlags {
+
+        @Parameter(names = { "-p", "--password" },
+            description = "The bookie stores the password in the index file, 
so we need it to regenerate."
+                          + "This must match the value in the ledger 
metadata.")
+        private String password = DEFAULT;
+
+        @Parameter(names = { "-b", "--b64password" },
+            description = "The password in base64 encoding, for cases where 
the password is not UTF-8.")
+        private String b64Password = DEFAULT;
+
+        @Parameter(names = { "-d", "--dryrun" }, description = "Process the 
entryLogger, but don't write anthing.")
+        private boolean dryRun;
+
+        @Parameter(names = { "-l", "--ledgerids" },
+            description = "Ledger(s) whose index needs to be regenerated. 
Multiple can be specified, comma separated.",
+            splitter = CommaParameterSplitter.class)
+        private List<Long> ledgerIds;
+
+    }
+
+    @Override
+    public boolean apply(ServerConfiguration conf, RISIFFlags cmdFlags) {
+        try {
+            return generate(conf, cmdFlags);
+        } catch (Exception e) {
+            throw new UncheckedExecutionException(e.getMessage(), e);
+        }
+    }
+
+    private boolean generate(ServerConfiguration conf, RISIFFlags flags) 
throws NoSuchAlgorithmException, IOException {
+        validateFlags(flags);
+        byte[] password;
+        if (!flags.password.equals(DEFAULT)) {
+            password = flags.password.getBytes(StandardCharsets.UTF_8);
+        } else if (!flags.b64Password.equals(DEFAULT)) {
+            password = Base64.getDecoder().decode(flags.b64Password);
+        } else {
+            LOG.error("The password must be specified to regenerate the index 
file");
+            return false;
+        }
+
+        Set<Long> ledgerIds = 
flags.ledgerIds.stream().collect(Collectors.toSet());
+
+        LOG.info("=== Rebuilding index file for {} ===", ledgerIds);
+        ServerConfiguration serverConfiguration = new 
ServerConfiguration(conf);
+        InterleavedStorageRegenerateIndexOp i = new 
InterleavedStorageRegenerateIndexOp(serverConfiguration, ledgerIds,
+                                                                               
         password);
+        i.initiate(flags.dryRun);
+
+        LOG.info("-- Done rebuilding index file for {} --", ledgerIds);
+        return true;
+    }
+
+    private void validateFlags(RISIFFlags flags) {
+        if (flags.password == null) {
+            flags.password = DEFAULT;
+        }
+        if (flags.b64Password == null) {
+            flags.b64Password = DEFAULT;
+        }
+    }
+}
diff --git 
a/tools/ledger/src/main/java/org/apache/bookkeeper/tools/cli/commands/BookieCommandGroup.java
 
b/tools/ledger/src/main/java/org/apache/bookkeeper/tools/cli/commands/BookieCommandGroup.java
index 95cd459..9e94cd2 100644
--- 
a/tools/ledger/src/main/java/org/apache/bookkeeper/tools/cli/commands/BookieCommandGroup.java
+++ 
b/tools/ledger/src/main/java/org/apache/bookkeeper/tools/cli/commands/BookieCommandGroup.java
@@ -34,6 +34,7 @@ import 
org.apache.bookkeeper.tools.cli.commands.bookie.ReadJournalCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookie.ReadLedgerCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookie.ReadLogCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookie.ReadLogMetadataCommand;
+import 
org.apache.bookkeeper.tools.cli.commands.bookie.RegenerateInterleavedStorageIndexFileCommand;
 import org.apache.bookkeeper.tools.cli.commands.bookie.SanityTestCommand;
 import org.apache.bookkeeper.tools.common.BKFlags;
 import org.apache.bookkeeper.tools.framework.CliCommandGroup;
@@ -66,6 +67,7 @@ public class BookieCommandGroup extends 
CliCommandGroup<BKFlags> {
         .addCommand(new ReadLogCommand())
         .addCommand(new ReadLogMetadataCommand())
         .addCommand(new LocalConsistencyCheckCommand())
+        .addCommand(new RegenerateInterleavedStorageIndexFileCommand())
         .build();
 
     public BookieCommandGroup() {
diff --git 
a/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/bookie/RegenerateInterleavedStorageIndexFileCommandTest.java
 
b/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/bookie/RegenerateInterleavedStorageIndexFileCommandTest.java
new file mode 100644
index 0000000..1ade885
--- /dev/null
+++ 
b/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/bookie/RegenerateInterleavedStorageIndexFileCommandTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bookkeeper.tools.cli.commands.bookie;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.bookkeeper.bookie.InterleavedStorageRegenerateIndexOp;
+import org.apache.bookkeeper.conf.ServerConfiguration;
+import org.apache.bookkeeper.tools.cli.helpers.BookieCommandTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ * Unit test for {@link RegenerateInterleavedStorageIndexFileCommand}.
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ RegenerateInterleavedStorageIndexFileCommand.class, 
InterleavedStorageRegenerateIndexOp.class,
+    ServerConfiguration.class })
+public class RegenerateInterleavedStorageIndexFileCommandTest extends 
BookieCommandTestBase {
+
+    @Mock
+    private ServerConfiguration serverConfiguration;
+
+    @Mock
+    private InterleavedStorageRegenerateIndexOp op;
+
+    public RegenerateInterleavedStorageIndexFileCommandTest() {
+        super(3, 0);
+    }
+
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+
+        
PowerMockito.whenNew(ServerConfiguration.class).withNoArguments().thenReturn(conf);
+        
PowerMockito.whenNew(ServerConfiguration.class).withArguments(eq(conf)).thenReturn(serverConfiguration);
+    }
+
+    @Test
+    public void testCommand() throws Exception {
+        String ledgerIds = "1,2,3";
+        String password = "12345";
+        Set<Long> ledgerIdsSet = Arrays.stream(ledgerIds.split(",")).map((id) 
-> Long.parseLong(id))
+                                       .collect(Collectors.toSet());
+        byte[] bytes = password.getBytes();
+        PowerMockito.whenNew(InterleavedStorageRegenerateIndexOp.class)
+                    .withArguments(eq(serverConfiguration), eq(ledgerIdsSet), 
eq(bytes)).thenReturn(op);
+        PowerMockito.doNothing().when(op).initiate(anyBoolean());
+
+        RegenerateInterleavedStorageIndexFileCommand cmd = new 
RegenerateInterleavedStorageIndexFileCommand();
+        Assert.assertTrue(cmd.apply(bkFlags, new String[] { "-p", password, 
"-l", ledgerIds }));
+        PowerMockito.verifyNew(ServerConfiguration.class, 
times(1)).withArguments(eq(conf));
+        PowerMockito.verifyNew(InterleavedStorageRegenerateIndexOp.class, 
times(1))
+                    .withArguments(eq(serverConfiguration), eq(ledgerIdsSet), 
eq(bytes));
+        verify(op, times(1)).initiate(anyBoolean());
+    }
+}
+

Reply via email to