blob: d6a262c59e9306488a2b9d8ec1fe7b108c8c9cd6 [file] [log] [blame]
/**
*
* 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.bookie;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.apache.bookkeeper.conf.ServerConfiguration;
import org.apache.bookkeeper.conf.TestBKConfiguration;
import org.apache.bookkeeper.discover.RegistrationManager;
import org.apache.bookkeeper.meta.MetadataBookieDriver;
import org.apache.bookkeeper.meta.zk.ZKMetadataBookieDriver;
import org.apache.bookkeeper.stats.NullStatsLogger;
import org.apache.bookkeeper.test.BookKeeperClusterTestCase;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* Testing StateManager cases.
*/
public class StateManagerTest extends BookKeeperClusterTestCase {
@Rule
public final TestName runtime = new TestName();
final ServerConfiguration conf;
MetadataBookieDriver driver;
public StateManagerTest(){
super(0);
String ledgersPath = "/" + "ledgers" + runtime.getMethodName();
baseClientConf.setMetadataServiceUri(zkUtil.getMetadataServiceUri(ledgersPath));
baseConf.setMetadataServiceUri(zkUtil.getMetadataServiceUri(ledgersPath));
conf = TestBKConfiguration.newServerConfiguration();
driver = new ZKMetadataBookieDriver();
}
@Override
public void setUp() throws Exception {
super.setUp();
zkUtil.createBKEnsemble("/" + runtime.getMethodName());
File tmpDir = tmpDirs.createNew("stateManger", "test");
conf.setJournalDirName(tmpDir.getPath())
.setLedgerDirNames(new String[] { tmpDir.getPath() })
.setJournalDirName(tmpDir.toString())
.setMetadataServiceUri(zkUtil.getMetadataServiceUri());
}
@Override
public void tearDown() throws Exception {
super.tearDown();
if (driver != null) {
driver.close();
}
}
/**
* StateManager can transition between writable mode and readOnly mode if it was not created with readOnly mode.
*/
@Test
public void testNormalBookieTransitions() throws Exception {
driver.initialize(conf, NullStatsLogger.INSTANCE);
try (RegistrationManager rm = driver.createRegistrationManager();
BookieStateManager stateManager = new BookieStateManager(conf, rm)) {
rm.addRegistrationListener(() -> {
stateManager.forceToUnregistered();
// schedule a re-register operation
stateManager.registerBookie(false);
});
stateManager.initState();
stateManager.registerBookie(true).get();
assertTrue(stateManager.isRunning());
assertTrue(stateManager.isRegistered());
stateManager.transitionToReadOnlyMode().get();
assertTrue(stateManager.isReadOnly());
stateManager.transitionToWritableMode().get();
assertTrue(stateManager.isRunning());
assertFalse(stateManager.isReadOnly());
stateManager.close();
assertFalse(stateManager.isRunning());
}
}
@Test
public void testReadOnlyDisableBookieTransitions() throws Exception {
conf.setReadOnlyModeEnabled(false);
// readOnly disabled bk stateManager
driver.initialize(
conf,
NullStatsLogger.INSTANCE);
RegistrationManager rm = driver.createRegistrationManager();
BookieStateManager stateManager = new BookieStateManager(conf, rm);
// simulate sync shutdown logic in bookie
stateManager.setShutdownHandler(new StateManager.ShutdownHandler() {
@Override
public void shutdown(int code) {
try {
if (stateManager.isRunning()) {
stateManager.forceToShuttingDown();
stateManager.forceToReadOnly();
}
} finally {
stateManager.close();
}
}
});
rm.addRegistrationListener(() -> {
stateManager.forceToUnregistered();
// schedule a re-register operation
stateManager.registerBookie(false);
});
stateManager.initState();
stateManager.registerBookie(true).get();
assertTrue(stateManager.isRunning());
stateManager.transitionToReadOnlyMode().get();
// stateManager2 will shutdown
assertFalse(stateManager.isRunning());
// different dimension of bookie state: running <--> down, read <--> write, unregistered <--> registered
// bookie2 is set to readOnly when shutdown
assertTrue(stateManager.isReadOnly());
}
@Test
public void testReadOnlyBookieTransitions() throws Exception{
// readOnlybk, which use override stateManager impl
File tmpDir = tmpDirs.createNew("stateManger", "test-readonly");
final ServerConfiguration readOnlyConf = TestBKConfiguration.newServerConfiguration();
readOnlyConf.setJournalDirName(tmpDir.getPath())
.setLedgerDirNames(new String[] { tmpDir.getPath() })
.setJournalDirName(tmpDir.toString())
.setMetadataServiceUri(zkUtil.getMetadataServiceUri())
.setForceReadOnlyBookie(true);
driver.initialize(readOnlyConf, NullStatsLogger.INSTANCE);
ReadOnlyBookie readOnlyBookie = TestBookieImpl.buildReadOnly(
new TestBookieImpl.ResourceBuilder(readOnlyConf)
.withMetadataDriver(driver).build());
readOnlyBookie.start();
assertTrue(readOnlyBookie.isRunning());
assertTrue(readOnlyBookie.isReadOnly());
// transition has no effect if bookie start with readOnly mode
readOnlyBookie.getStateManager().transitionToWritableMode().get();
assertTrue(readOnlyBookie.isRunning());
assertTrue(readOnlyBookie.isReadOnly());
readOnlyBookie.shutdown();
}
/**
* Verify the bookie reg.
*/
@Test
public void testRegistration() throws Exception {
driver.initialize(
conf,
NullStatsLogger.INSTANCE);
RegistrationManager rm = driver.createRegistrationManager();
BookieStateManager stateManager = new BookieStateManager(conf, rm);
rm.addRegistrationListener(() -> {
stateManager.forceToUnregistered();
// schedule a re-register operation
stateManager.registerBookie(false);
});
// simulate sync shutdown logic in bookie
stateManager.setShutdownHandler(new StateManager.ShutdownHandler() {
@Override
public void shutdown(int code) {
try {
if (stateManager.isRunning()) {
stateManager.forceToShuttingDown();
stateManager.forceToReadOnly();
}
} finally {
stateManager.close();
}
}
});
stateManager.initState();
// up
assertTrue(stateManager.isRunning());
// unregistered
assertFalse(stateManager.isRegistered());
stateManager.registerBookie(true).get();
// registered
assertTrue(stateManager.isRegistered());
stateManager.getShutdownHandler().shutdown(ExitCode.OK);
// readOnly
assertTrue(stateManager.isReadOnly());
}
}