You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by iv...@apache.org on 2011/11/04 11:46:45 UTC
svn commit: r1197495 - in /zookeeper/bookkeeper/trunk: ./
bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/
bookkeeper-server/src/test/java/org/apache/bookkeeper/test/
Author: ivank
Date: Fri Nov 4 10:46:44 2011
New Revision: 1197495
URL: http://svn.apache.org/viewvc?rev=1197495&view=rev
Log:
BOOKKEEPER-50: NullPointException at LedgerDescriptor#cmpMasterKey (Sijie Guo via ivank)
Modified:
zookeeper/bookkeeper/trunk/CHANGES.txt
zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/FileInfo.java
zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/BaseTestCase.java
Modified: zookeeper/bookkeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/CHANGES.txt?rev=1197495&r1=1197494&r2=1197495&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/CHANGES.txt (original)
+++ zookeeper/bookkeeper/trunk/CHANGES.txt Fri Nov 4 10:46:44 2011
@@ -60,6 +60,8 @@ BUGFIXES:
BOOKKEEPER-103: ledgerId and entryId is parsed wrong when addEntry (Sijie Guo via ivank)
+ BOOKKEEPER-50: NullPointException at LedgerDescriptor#cmpMasterKey (Sijie Guo via ivank)
+
hedwig-server/
BOOKKEEPER-43: NullPointException when releasing topic (Sijie Guo via breed)
Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java?rev=1197495&r1=1197494&r2=1197495&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java Fri Nov 4 10:46:44 2011
@@ -193,7 +193,6 @@ public class Bookie extends Thread {
}
recBuff.flip();
long ledgerId = recBuff.getLong();
- // XXX we net to make sure we set the master keys appropriately!
LedgerDescriptor handle = getHandle(ledgerId, false);
try {
recBuff.rewind();
@@ -317,12 +316,29 @@ public class Bookie extends Thread {
synchronized (ledgers) {
handle = ledgers.get(ledgerId);
if (handle == null) {
- if (readonly) {
- throw new NoLedgerException(ledgerId);
+ FileInfo fi = null;
+ try {
+ // get file info will throw NoLedgerException
+ fi = ledgerCache.getFileInfo(ledgerId, !readonly);
+
+ // if an existed ledger index file, we can get its master key
+ // if an new created ledger index file, we will get a null master key
+ byte[] existingMasterKey = fi.readMasterKey();
+ ByteBuffer masterKeyToSet = ByteBuffer.wrap(masterKey);
+ if (existingMasterKey == null) {
+ // no master key set before
+ fi.writeMasterKey(masterKey);
+ } else if (!masterKeyToSet.equals(ByteBuffer.wrap(existingMasterKey))) {
+ throw new IOException("Wrong master key for ledger " + ledgerId);
+ }
+ handle = createHandle(ledgerId, readonly);
+ ledgers.put(ledgerId, handle);
+ handle.setMasterKey(masterKeyToSet);
+ } finally {
+ if (fi != null) {
+ fi.release();
+ }
}
- handle = createHandle(ledgerId, readonly);
- ledgers.put(ledgerId, handle);
- handle.setMasterKey(ByteBuffer.wrap(masterKey));
}
handle.incRef();
}
@@ -334,11 +350,26 @@ public class Bookie extends Thread {
synchronized (ledgers) {
handle = ledgers.get(ledgerId);
if (handle == null) {
- if (readonly) {
- throw new NoLedgerException(ledgerId);
+ FileInfo fi = null;
+ try {
+ // get file info will throw NoLedgerException
+ fi = ledgerCache.getFileInfo(ledgerId, !readonly);
+
+ // if an existed ledger index file, we can get its master key
+ // if an new created ledger index file, we will get a null master key
+ byte[] existingMasterKey = fi.readMasterKey();
+ if (existingMasterKey == null) {
+ throw new IOException("Weird! No master key found in ledger " + ledgerId);
+ }
+
+ handle = createHandle(ledgerId, readonly);
+ ledgers.put(ledgerId, handle);
+ handle.setMasterKey(ByteBuffer.wrap(existingMasterKey));
+ } finally {
+ if (fi != null) {
+ fi.release();
+ }
}
- handle = createHandle(ledgerId, readonly);
- ledgers.put(ledgerId, handle);
}
handle.incRef();
}
Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/FileInfo.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/FileInfo.java?rev=1197495&r1=1197494&r2=1197495&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/FileInfo.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/FileInfo.java Fri Nov 4 10:46:44 2011
@@ -32,10 +32,25 @@ import org.apache.log4j.Logger;
/**
* This is the file handle for a ledger's index file that maps entry ids to location.
* It is used by LedgerCache.
+ *
+ * <p>
+ * Ledger index file is made of a header and several fixed-length index pages, which records the offsets of data stored in entry loggers
+ * <pre><header><index pages></pre>
+ * <b>Header</b> is formated as below:
+ * <pre><magic bytes><len of master key><master key></pre>
+ * <ul>
+ * <li>magic bytes: 8 bytes, 'BKLE\0\0\0\0'
+ * <li>len of master key: indicates length of master key. -1 means no master key stored in header.
+ * <li>master key: master key
+ * </ul>
+ * <b>Index page</b> is a fixed-length page, which contains serveral entries which point to the offsets of data stored in entry loggers.
+ * </p>
*/
class FileInfo {
static Logger LOG = Logger.getLogger(FileInfo.class);
+ static final int NO_MASTER_KEY = -1;
+
private FileChannel fc;
private final File lf;
/**
@@ -52,7 +67,61 @@ class FileInfo {
size = fc.size();
if (size == 0) {
fc.write(ByteBuffer.wrap(header));
+ // write NO_MASTER_KEY, which means there is no master key
+ ByteBuffer buf = ByteBuffer.allocate(4);
+ buf.putInt(NO_MASTER_KEY);
+ buf.flip();
+ fc.write(buf);
+ }
+ }
+
+ /**
+ * Write master key to index file header
+ *
+ * @param masterKey master key to store
+ * @return void
+ * @throws IOException
+ */
+ synchronized public void writeMasterKey(byte[] masterKey) throws IOException {
+ // write master key
+ if (masterKey == null ||
+ masterKey.length + 4 + header.length > START_OF_DATA) {
+ throw new IOException("master key is more than " + (START_OF_DATA - 4 - header.length));
+ }
+
+ int len = masterKey.length;
+ ByteBuffer lenBuf = ByteBuffer.allocate(4);
+ lenBuf.putInt(len);
+ lenBuf.flip();
+ fc.position(header.length);
+ fc.write(lenBuf);
+ fc.write(ByteBuffer.wrap(masterKey));
+ }
+
+ /**
+ * Read master key
+ *
+ * @return master key. null means no master key stored in index header
+ * @throws IOException
+ */
+ synchronized public byte[] readMasterKey() throws IOException {
+ ByteBuffer lenBuf = ByteBuffer.allocate(4);
+ int total = readAbsolute(lenBuf, header.length);
+ if (total != 4) {
+ throw new IOException("Short read during reading master key length");
+ }
+ lenBuf.rewind();
+ int len = lenBuf.getInt();
+ if (len == NO_MASTER_KEY) {
+ return null;
+ }
+
+ byte[] masterKey = new byte[len];
+ total = readAbsolute(ByteBuffer.wrap(masterKey), header.length + 4);
+ if (total != len) {
+ throw new IOException("Short read during reading master key");
}
+ return masterKey;
}
synchronized public long size() {
@@ -64,13 +133,19 @@ class FileInfo {
}
synchronized public int read(ByteBuffer bb, long position) throws IOException {
+ return readAbsolute(bb, position + START_OF_DATA);
+ }
+
+ private int readAbsolute(ByteBuffer bb, long start) throws IOException {
int total = 0;
while(bb.remaining() > 0) {
- int rc = fc.read(bb, position+START_OF_DATA);
+ int rc = fc.read(bb, start);
if (rc <= 0) {
throw new IOException("Short read");
}
total += rc;
+ // should move read position
+ start += rc;
}
return total;
}
Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/BaseTestCase.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/BaseTestCase.java?rev=1197495&r1=1197494&r2=1197495&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/BaseTestCase.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/BaseTestCase.java Fri Nov 4 10:46:44 2011
@@ -21,6 +21,7 @@
package org.apache.bookkeeper.test;
+import java.io.IOException;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.ArrayList;
@@ -124,6 +125,29 @@ public abstract class BaseTestCase exten
}
}
+ /**
+ * Restart bookie servers
+ *
+ * @throws InterruptedException
+ * @throws IOException
+ */
+ protected void restartBookies() throws InterruptedException, IOException {
+ // shut down bookie server
+ for (BookieServer server : bs) {
+ server.shutdown();
+ }
+ bs.clear();
+ Thread.sleep(1000);
+ // restart them to ensure we can't
+ int j = 0;
+ for (File f : tmpDirs) {
+ BookieServer server = new BookieServer(initialPort + j, HOSTPORT, f, new File[] { f });
+ server.start();
+ bs.add(server);
+ j++;
+ }
+ }
+
@After
@Override
public void tearDown() throws Exception {