ArvinDevel commented on a change in pull request #873: Issue280: Turn bookie 
into readonly when sortedLedgerStorage failed to flush data
URL: https://github.com/apache/bookkeeper/pull/873#discussion_r157965203
 
 

 ##########
 File path: 
bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
 ##########
 @@ -1446,6 +1304,153 @@ public LedgerStorage getLedgerStorage() {
         return ledgerStorage;
     }
 
+    /**
+     * A implementation of StateManager.
+     */
+    public class BookieStateManager implements StateManager{
+        // use an executor to execute the state changes task
+        final ExecutorService stateService = Executors.newSingleThreadExecutor(
+                new 
ThreadFactoryBuilder().setNameFormat("BookieStateManagerService-%d").build());
+        final BookieStatus bookieStatus;
+        RegistrationManager registrationManager;
+        public BookieStateManager(BookieStatus bookieStatus, 
RegistrationManager registrationManager){
+            this.bookieStatus = bookieStatus;
+            this.registrationManager = registrationManager;
+        }
+
+          @Override
+        public void close() {
+            stateService.shutdown();
+        }
+
+        @Override
+        public Future<Void> registerBookie(final boolean throwException) {
+            return stateService.submit(new Callable<Void>() {
+                @Override
+                public Void call() throws IOException {
+                    try {
+                        doRegisterBookie();
+                    } catch (IOException ioe) {
+                        if (throwException) {
+                            throw ioe;
+                        } else {
+                            LOG.error("Couldn't register bookie with 
zookeeper, shutting down : ", ioe);
+                            triggerBookieShutdown(ExitCode.ZK_REG_FAIL);
+                        }
+                    }
+                    return (Void) null;
+                }
+            });
+        }
+
+        @Override
+        public void transitionToWritableMode() {
+            stateService.execute(() -> doTransitionToWritableMode());
+        }
+
+        @Override
+        public void transitionToReadOnlyMode() {
+            stateService.execute(() -> doTransitionToReadOnlyMode());
+        }
+
+        void doRegisterBookie() throws IOException {
+            doRegisterBookie(forceReadOnly.get() || 
bookieStatus.isInReadOnlyMode());
+        }
+
+        private void doRegisterBookie(boolean isReadOnly) throws IOException {
+            if (null == registrationManager || ((ZKRegistrationManager) 
this.registrationManager).getZk() == null) {
+                // registration manager is null, means not register itself to 
zk.
+                // ZooKeeper is null existing only for testing.
+                LOG.info("null zk while do register");
+                return;
+            }
+
+            rmRegistered.set(false);
+            try {
+                registrationManager.registerBookie(bookieId, isReadOnly);
+                rmRegistered.set(true);
+            } catch (BookieException e) {
+                throw new IOException(e);
+            }
+        }
+
+        @VisibleForTesting
+        public void doTransitionToWritableMode() {
+            if (shuttingdown || forceReadOnly.get()) {
+                return;
+            }
+
+            if (!bookieStatus.setToWritableMode()) {
+                // do nothing if already in writable mode
+                return;
+            }
+            LOG.info("Transitioning Bookie to Writable mode and will serve 
read/write requests.");
+            if (conf.isPersistBookieStatusEnabled()) {
+                
bookieStatus.writeToDirectories(ledgerDirsManager.getAllLedgerDirs());
+            }
+            // change zookeeper state only when using zookeeper
+            if (null == registrationManager) {
+                return;
+            }
+            try {
+                doRegisterBookie(false);
+            } catch (IOException e) {
+                LOG.warn("Error in transitioning back to writable mode : ", e);
+                transitionToReadOnlyMode();
+                return;
+            }
+            // clear the readonly state
+            try {
+                registrationManager.unregisterBookie(bookieId, true);
+            } catch (BookieException e) {
+                // if we failed when deleting the readonly flag in zookeeper, 
it is OK since client would
+                // already see the bookie in writable list. so just log the 
exception
+                LOG.warn("Failed to delete bookie readonly state in zookeeper 
: ", e);
+                return;
+            }
+        }
+        @VisibleForTesting
+        public void doTransitionToReadOnlyMode() {
+            if (shuttingdown) {
+                return;
+            }
+            if (!bookieStatus.setToReadOnlyMode()) {
+                return;
+            }
+            if (!conf.isReadOnlyModeEnabled()) {
+                LOG.warn("ReadOnly mode is not enabled. "
+                        + "Can be enabled by configuring "
+                        + "'readOnlyModeEnabled=true' in configuration."
+                        + "Shutting down bookie");
+                triggerBookieShutdown(ExitCode.BOOKIE_EXCEPTION);
+                return;
+            }
+            LOG.info("Transitioning Bookie to ReadOnly mode,"
+                    + " and will serve only read requests from clients!");
+            // persist the bookie status if we enable this
+            if (conf.isPersistBookieStatusEnabled()) {
+                
this.bookieStatus.writeToDirectories(ledgerDirsManager.getAllLedgerDirs());
+            }
+            // change zookeeper state only when using zookeeper
+            if (null == registrationManager) {
+                return;
+            }
+            try {
+                registrationManager.registerBookie(bookieId, true);
+            } catch (BookieException e) {
+                LOG.error("Error in transition to ReadOnly Mode."
+                        + " Shutting down", e);
+                triggerBookieShutdown(ExitCode.BOOKIE_EXCEPTION);
+                return;
+            }
+        }
+
+    }
+
+    @VisibleForTesting
+    public StateManager getStateManager() {
 
 Review comment:
   because tests in `org.apache.bookkeeper.test` may use stateManager, for 
example ReadOnlyBookieTest, so `getStateManager ` should use public

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to