Improve concurrency

git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@961484 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Robert Davies 2010-07-07 19:34:09 +00:00
parent 06b41bb759
commit b47da808d7
2 changed files with 112 additions and 29 deletions

View File

@ -389,7 +389,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
// operations... but for now we must // operations... but for now we must
// externally synchronize... // externally synchronize...
Location location; Location location;
synchronized (indexMutex) { indexLock.readLock().lock();
try {
location = pageFile.tx().execute(new Transaction.CallableClosure<Location, IOException>() { location = pageFile.tx().execute(new Transaction.CallableClosure<Location, IOException>() {
public Location execute(Transaction tx) throws IOException { public Location execute(Transaction tx) throws IOException {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
@ -400,6 +401,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
return sd.orderIndex.get(tx, sequence).location; return sd.orderIndex.get(tx, sequence).location;
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
if (location == null) { if (location == null) {
return null; return null;
@ -411,7 +414,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
public int getMessageCount() throws IOException { public int getMessageCount() throws IOException {
try { try {
lockAsyncJobQueue(); lockAsyncJobQueue();
synchronized (indexMutex) { indexLock.readLock().lock();
try {
return pageFile.tx().execute(new Transaction.CallableClosure<Integer, IOException>() { return pageFile.tx().execute(new Transaction.CallableClosure<Integer, IOException>() {
public Integer execute(Transaction tx) throws IOException { public Integer execute(Transaction tx) throws IOException {
// Iterate through all index entries to get a count // Iterate through all index entries to get a count
@ -427,6 +431,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
return rc; return rc;
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
} finally { } finally {
unlockAsyncJobQueue(); unlockAsyncJobQueue();
@ -435,7 +441,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
@Override @Override
public boolean isEmpty() throws IOException { public boolean isEmpty() throws IOException {
synchronized (indexMutex) { indexLock.readLock().lock();
try {
return pageFile.tx().execute(new Transaction.CallableClosure<Boolean, IOException>() { return pageFile.tx().execute(new Transaction.CallableClosure<Boolean, IOException>() {
public Boolean execute(Transaction tx) throws IOException { public Boolean execute(Transaction tx) throws IOException {
// Iterate through all index entries to get a count of // Iterate through all index entries to get a count of
@ -444,11 +451,14 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
return sd.locationIndex.isEmpty(tx); return sd.locationIndex.isEmpty(tx);
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
} }
public void recover(final MessageRecoveryListener listener) throws Exception { public void recover(final MessageRecoveryListener listener) throws Exception {
synchronized (indexMutex) { indexLock.readLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<Exception>() { pageFile.tx().execute(new Transaction.Closure<Exception>() {
public void execute(Transaction tx) throws Exception { public void execute(Transaction tx) throws Exception {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
@ -459,13 +469,16 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
} }
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
} }
long cursorPos = 0; long cursorPos = 0;
public void recoverNextMessages(final int maxReturned, final MessageRecoveryListener listener) throws Exception { public void recoverNextMessages(final int maxReturned, final MessageRecoveryListener listener) throws Exception {
synchronized (indexMutex) { indexLock.readLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<Exception>() { pageFile.tx().execute(new Transaction.Closure<Exception>() {
public void execute(Transaction tx) throws Exception { public void execute(Transaction tx) throws Exception {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
@ -486,6 +499,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
} }
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
} }
@ -503,13 +518,16 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
// operations... but for now we must // operations... but for now we must
// externally synchronize... // externally synchronize...
Long location; Long location;
synchronized (indexMutex) { indexLock.readLock().lock();
try {
location = pageFile.tx().execute(new Transaction.CallableClosure<Long, IOException>() { location = pageFile.tx().execute(new Transaction.CallableClosure<Long, IOException>() {
public Long execute(Transaction tx) throws IOException { public Long execute(Transaction tx) throws IOException {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
return sd.messageIdIndex.get(tx, key); return sd.messageIdIndex.get(tx, key);
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
if (location != null) { if (location != null) {
cursorPos = location + 1; cursorPos = location + 1;
@ -638,7 +656,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
public SubscriptionInfo[] getAllSubscriptions() throws IOException { public SubscriptionInfo[] getAllSubscriptions() throws IOException {
final ArrayList<SubscriptionInfo> subscriptions = new ArrayList<SubscriptionInfo>(); final ArrayList<SubscriptionInfo> subscriptions = new ArrayList<SubscriptionInfo>();
synchronized (indexMutex) { indexLock.readLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
@ -652,6 +671,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
} }
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
SubscriptionInfo[] rc = new SubscriptionInfo[subscriptions.size()]; SubscriptionInfo[] rc = new SubscriptionInfo[subscriptions.size()];
@ -661,7 +682,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
public SubscriptionInfo lookupSubscription(String clientId, String subscriptionName) throws IOException { public SubscriptionInfo lookupSubscription(String clientId, String subscriptionName) throws IOException {
final String subscriptionKey = subscriptionKey(clientId, subscriptionName); final String subscriptionKey = subscriptionKey(clientId, subscriptionName);
synchronized (indexMutex) { indexLock.readLock().lock();
try {
return pageFile.tx().execute(new Transaction.CallableClosure<SubscriptionInfo, IOException>() { return pageFile.tx().execute(new Transaction.CallableClosure<SubscriptionInfo, IOException>() {
public SubscriptionInfo execute(Transaction tx) throws IOException { public SubscriptionInfo execute(Transaction tx) throws IOException {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
@ -673,13 +695,16 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
.getSubscriptionInfo().newInput())); .getSubscriptionInfo().newInput()));
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
} }
public int getMessageCount(String clientId, String subscriptionName) throws IOException { public int getMessageCount(String clientId, String subscriptionName) throws IOException {
final String subscriptionKey = subscriptionKey(clientId, subscriptionName); final String subscriptionKey = subscriptionKey(clientId, subscriptionName);
final SubscriptionInfo info = lookupSubscription(clientId, subscriptionName); final SubscriptionInfo info = lookupSubscription(clientId, subscriptionName);
synchronized (indexMutex) { indexLock.readLock().lock();
try {
return pageFile.tx().execute(new Transaction.CallableClosure<Integer, IOException>() { return pageFile.tx().execute(new Transaction.CallableClosure<Integer, IOException>() {
public Integer execute(Transaction tx) throws IOException { public Integer execute(Transaction tx) throws IOException {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
@ -716,13 +741,16 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
return counter; return counter;
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
} }
public void recoverSubscription(String clientId, String subscriptionName, final MessageRecoveryListener listener) public void recoverSubscription(String clientId, String subscriptionName, final MessageRecoveryListener listener)
throws Exception { throws Exception {
final String subscriptionKey = subscriptionKey(clientId, subscriptionName); final String subscriptionKey = subscriptionKey(clientId, subscriptionName);
synchronized (indexMutex) { indexLock.readLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<Exception>() { pageFile.tx().execute(new Transaction.Closure<Exception>() {
public void execute(Transaction tx) throws Exception { public void execute(Transaction tx) throws Exception {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
@ -736,13 +764,16 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
} }
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
} }
public void recoverNextMessages(String clientId, String subscriptionName, final int maxReturned, public void recoverNextMessages(String clientId, String subscriptionName, final int maxReturned,
final MessageRecoveryListener listener) throws Exception { final MessageRecoveryListener listener) throws Exception {
final String subscriptionKey = subscriptionKey(clientId, subscriptionName); final String subscriptionKey = subscriptionKey(clientId, subscriptionName);
synchronized (indexMutex) { indexLock.readLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<Exception>() { pageFile.tx().execute(new Transaction.Closure<Exception>() {
public void execute(Transaction tx) throws Exception { public void execute(Transaction tx) throws Exception {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
@ -768,19 +799,24 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
} }
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
} }
public void resetBatching(String clientId, String subscriptionName) { public void resetBatching(String clientId, String subscriptionName) {
try { try {
final String subscriptionKey = subscriptionKey(clientId, subscriptionName); final String subscriptionKey = subscriptionKey(clientId, subscriptionName);
synchronized (indexMutex) { indexLock.writeLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
StoredDestination sd = getStoredDestination(dest, tx); StoredDestination sd = getStoredDestination(dest, tx);
sd.subscriptionCursors.remove(subscriptionKey); sd.subscriptionCursors.remove(subscriptionKey);
} }
}); });
}finally {
indexLock.writeLock().unlock();
} }
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -827,7 +863,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
public Set<ActiveMQDestination> getDestinations() { public Set<ActiveMQDestination> getDestinations() {
try { try {
final HashSet<ActiveMQDestination> rc = new HashSet<ActiveMQDestination>(); final HashSet<ActiveMQDestination> rc = new HashSet<ActiveMQDestination>();
synchronized (indexMutex) { indexLock.readLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
for (Iterator<Entry<String, StoredDestination>> iterator = metadata.destinations.iterator(tx); iterator for (Iterator<Entry<String, StoredDestination>> iterator = metadata.destinations.iterator(tx); iterator
@ -852,6 +889,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
return isEmptyTopic; return isEmptyTopic;
} }
}); });
}finally {
indexLock.readLock().unlock();
} }
return rc; return rc;
} catch (IOException e) { } catch (IOException e) {

View File

@ -35,6 +35,9 @@ import java.util.TreeMap;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.activemq.broker.BrokerService; import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.BrokerServiceAware; import org.apache.activemq.broker.BrokerServiceAware;
import org.apache.activemq.command.ConnectionId; import org.apache.activemq.command.ConnectionId;
@ -193,7 +196,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
} }
private void loadPageFile() throws IOException { private void loadPageFile() throws IOException {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
final PageFile pageFile = getPageFile(); final PageFile pageFile = getPageFile();
pageFile.load(); pageFile.load();
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
@ -232,6 +236,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
} }
} }
}); });
}finally {
this.indexLock.writeLock().unlock();
} }
} }
@ -307,7 +313,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
public void load() throws IOException { public void load() throws IOException {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
lock(); lock();
if (deleteAllMessages) { if (deleteAllMessages) {
getJournal().start(); getJournal().start();
@ -321,7 +328,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
open(); open();
store(new KahaTraceCommand().setMessage("LOADED " + new Date())); store(new KahaTraceCommand().setMessage("LOADED " + new Date()));
}finally {
this.indexLock.writeLock().unlock();
} }
} }
@ -329,7 +337,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
public void close() throws IOException, InterruptedException { public void close() throws IOException, InterruptedException {
if( opened.compareAndSet(true, false)) { if( opened.compareAndSet(true, false)) {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
checkpointUpdate(tx, true); checkpointUpdate(tx, true);
@ -337,6 +346,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
}); });
pageFile.unload(); pageFile.unload();
metadata = new Metadata(); metadata = new Metadata();
}finally {
this.indexLock.writeLock().unlock();
} }
journal.close(); journal.close();
checkpointThread.join(); checkpointThread.join();
@ -346,7 +357,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
} }
public void unload() throws IOException, InterruptedException { public void unload() throws IOException, InterruptedException {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
if( pageFile != null && pageFile.isLoaded() ) { if( pageFile != null && pageFile.isLoaded() ) {
metadata.state = CLOSED_STATE; metadata.state = CLOSED_STATE;
metadata.firstInProgressTransactionLocation = getFirstInProgressTxLocation(); metadata.firstInProgressTransactionLocation = getFirstInProgressTxLocation();
@ -357,6 +369,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
} }
}); });
} }
}finally {
this.indexLock.writeLock().unlock();
} }
close(); close();
} }
@ -389,7 +403,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
* @throws IllegalStateException * @throws IllegalStateException
*/ */
private void recover() throws IllegalStateException, IOException { private void recover() throws IllegalStateException, IOException {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Location recoveryPosition = getRecoveryPosition(); Location recoveryPosition = getRecoveryPosition();
@ -413,6 +428,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
recoverIndex(tx); recoverIndex(tx);
} }
}); });
}finally {
this.indexLock.writeLock().unlock();
} }
} }
@ -559,7 +576,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
private Location lastRecoveryPosition; private Location lastRecoveryPosition;
public void incrementalRecover() throws IOException { public void incrementalRecover() throws IOException {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
if( nextRecoveryPosition == null ) { if( nextRecoveryPosition == null ) {
if( lastRecoveryPosition==null ) { if( lastRecoveryPosition==null ) {
nextRecoveryPosition = getRecoveryPosition(); nextRecoveryPosition = getRecoveryPosition();
@ -574,6 +592,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
process(message, lastRecoveryPosition); process(message, lastRecoveryPosition);
nextRecoveryPosition = journal.getNextLocation(lastRecoveryPosition); nextRecoveryPosition = journal.getNextLocation(lastRecoveryPosition);
} }
}finally {
this.indexLock.writeLock().unlock();
} }
} }
@ -600,7 +620,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
protected void checkpointCleanup(final boolean cleanup) throws IOException { protected void checkpointCleanup(final boolean cleanup) throws IOException {
long start; long start;
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
start = System.currentTimeMillis(); start = System.currentTimeMillis();
if( !opened.get() ) { if( !opened.get() ) {
return; return;
@ -610,6 +631,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
checkpointUpdate(tx, cleanup); checkpointUpdate(tx, cleanup);
} }
}); });
}finally {
this.indexLock.writeLock().unlock();
} }
long end = System.currentTimeMillis(); long end = System.currentTimeMillis();
if( LOG_SLOW_ACCESS_TIME>0 && end-start > LOG_SLOW_ACCESS_TIME) { if( LOG_SLOW_ACCESS_TIME>0 && end-start > LOG_SLOW_ACCESS_TIME) {
@ -619,13 +642,16 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
public void checkpoint(Callback closure) throws Exception { public void checkpoint(Callback closure) throws Exception {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
checkpointUpdate(tx, false); checkpointUpdate(tx, false);
} }
}); });
closure.execute(); closure.execute();
}finally {
this.indexLock.writeLock().unlock();
} }
} }
@ -662,8 +688,11 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
LOG.info("Slow KahaDB access: Journal append took: "+(start2-start)+" ms, Index update took "+(end-start2)+" ms"); LOG.info("Slow KahaDB access: Journal append took: "+(start2-start)+" ms, Index update took "+(end-start2)+" ms");
} }
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
metadata.lastUpdate = location; metadata.lastUpdate = location;
}finally {
this.indexLock.writeLock().unlock();
} }
if (!checkpointThread.isAlive()) { if (!checkpointThread.isAlive()) {
LOG.info("KahaDB: Recovering checkpoint thread after exception"); LOG.info("KahaDB: Recovering checkpoint thread after exception");
@ -752,12 +781,15 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
inflightTx.add(new AddOpperation(command, location)); inflightTx.add(new AddOpperation(command, location));
} }
} else { } else {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
upadateIndex(tx, command, location); upadateIndex(tx, command, location);
} }
}); });
}finally {
this.indexLock.writeLock().unlock();
} }
} }
} }
@ -769,34 +801,43 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
inflightTx.add(new RemoveOpperation(command, location)); inflightTx.add(new RemoveOpperation(command, location));
} }
} else { } else {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
updateIndex(tx, command, location); updateIndex(tx, command, location);
} }
}); });
}finally {
this.indexLock.writeLock().unlock();
} }
} }
} }
protected void process(final KahaRemoveDestinationCommand command, final Location location) throws IOException { protected void process(final KahaRemoveDestinationCommand command, final Location location) throws IOException {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
updateIndex(tx, command, location); updateIndex(tx, command, location);
} }
}); });
}finally {
this.indexLock.writeLock().unlock();
} }
} }
protected void process(final KahaSubscriptionCommand command, final Location location) throws IOException { protected void process(final KahaSubscriptionCommand command, final Location location) throws IOException {
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
updateIndex(tx, command, location); updateIndex(tx, command, location);
} }
}); });
}finally {
this.indexLock.writeLock().unlock();
} }
} }
@ -814,7 +855,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
} }
final ArrayList<Operation> messagingTx = inflightTx; final ArrayList<Operation> messagingTx = inflightTx;
synchronized (indexMutex) { this.indexLock.writeLock().lock();
try {
pageFile.tx().execute(new Transaction.Closure<IOException>() { pageFile.tx().execute(new Transaction.Closure<IOException>() {
public void execute(Transaction tx) throws IOException { public void execute(Transaction tx) throws IOException {
for (Operation op : messagingTx) { for (Operation op : messagingTx) {
@ -822,6 +864,8 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
} }
} }
}); });
}finally {
this.indexLock.writeLock().unlock();
} }
} }
@ -849,7 +893,7 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
// These methods do the actual index updates. // These methods do the actual index updates.
// ///////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////
protected final Object indexMutex = new Object(); protected final ReentrantReadWriteLock indexLock = new ReentrantReadWriteLock();
private final HashSet<Integer> journalFilesBeingReplicated = new HashSet<Integer>(); private final HashSet<Integer> journalFilesBeingReplicated = new HashSet<Integer>();
void upadateIndex(Transaction tx, KahaAddMessageCommand command, Location location) throws IOException { void upadateIndex(Transaction tx, KahaAddMessageCommand command, Location location) throws IOException {