ARTEMIS-3271 Improve Critical Analyzer to use AutoCloseable on the API
This commit is contained in:
parent
a3295c9873
commit
d2676e77f8
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* 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.activemq.artemis.utils;
|
||||||
|
|
||||||
|
public interface ArtemisCloseable extends AutoCloseable {
|
||||||
|
|
||||||
|
/** The main purpose of this interface is to hide the exception since it is not needed. */
|
||||||
|
@Override
|
||||||
|
void close();
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
* 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.activemq.artemis.utils.critical;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
|
|
||||||
|
public interface CriticalCloseable extends ArtemisCloseable {
|
||||||
|
|
||||||
|
|
||||||
|
/** This will set something to be called right before closing.
|
||||||
|
*
|
||||||
|
* The use case that drove this call was a ReadWriteLock on the journal.
|
||||||
|
* Imagine that you need to call enterCritical, readWrite.lock() and then unlock and leaveCritical.
|
||||||
|
* By using this call I could reuse the same instance on the readWriteLock. */
|
||||||
|
void beforeClose(ArtemisCloseable otherCloseable);
|
||||||
|
}
|
|
@ -16,7 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.artemis.utils.critical;
|
package org.apache.activemq.artemis.utils.critical;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Critical component enters and leaves a critical state.
|
* A Critical component enters and leaves a critical state.
|
||||||
* You update a long every time you enter a critical path
|
* You update a long every time you enter a critical path
|
||||||
|
@ -27,26 +26,9 @@ package org.apache.activemq.artemis.utils.critical;
|
||||||
*/
|
*/
|
||||||
public interface CriticalComponent {
|
public interface CriticalComponent {
|
||||||
|
|
||||||
default CriticalAnalyzer getCriticalAnalyzer() {
|
CriticalAnalyzer getCriticalAnalyzer();
|
||||||
return null;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* please save the time you entered here.
|
|
||||||
* Use volatile variables.
|
|
||||||
* No locks through anywhere.
|
|
||||||
*/
|
|
||||||
default void enterCritical(int path) {
|
|
||||||
// I'm providing a default as some components may chose to calculate it themselves
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
CriticalCloseable measureCritical(int path);
|
||||||
* please save the time you entered here
|
|
||||||
* Use volatile variables.
|
|
||||||
* No locks through anywhere.
|
|
||||||
*/
|
|
||||||
default void leaveCritical(int path) {
|
|
||||||
// I'm providing a default as some components may chose to calculate it themselves
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the component is expired at a given timeout.. on any of its paths.
|
* Check if the component is expired at a given timeout.. on any of its paths.
|
||||||
|
|
|
@ -47,17 +47,11 @@ public class CriticalComponentImpl implements CriticalComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enterCritical(int path) {
|
public CriticalCloseable measureCritical(int path) {
|
||||||
if (analyzer.isMeasuring()) {
|
if (!analyzer.isMeasuring()) {
|
||||||
measures[path].enterCritical();
|
return CriticalMeasure.dummyCloseable;
|
||||||
}
|
} else {
|
||||||
|
return measures[path].measure();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void leaveCritical(int path) {
|
|
||||||
if (analyzer.isMeasuring()) {
|
|
||||||
measures[path].leaveCritical();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,24 +17,58 @@
|
||||||
|
|
||||||
package org.apache.activemq.artemis.utils.critical;
|
package org.apache.activemq.artemis.utils.critical;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
public class CriticalMeasure {
|
public class CriticalMeasure {
|
||||||
|
|
||||||
|
public static boolean isDummy(ArtemisCloseable closeable) {
|
||||||
|
return closeable == dummyCloseable;
|
||||||
|
}
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(CriticalMeasure.class);
|
private static final Logger logger = Logger.getLogger(CriticalMeasure.class);
|
||||||
|
|
||||||
// this is used on enterCritical, if the logger is in trace mode
|
// this is used on enterCritical, if the logger is in trace mode
|
||||||
private volatile Exception traceEnter;
|
private volatile Exception traceEnter;
|
||||||
|
static final AtomicIntegerFieldUpdater<CriticalMeasure> CURRENT_MEASURING = AtomicIntegerFieldUpdater.newUpdater(CriticalMeasure.class, "measuring");
|
||||||
|
|
||||||
static final AtomicReferenceFieldUpdater<CriticalMeasure, Thread> CURRENT_THREAD_UDPATER = AtomicReferenceFieldUpdater.newUpdater(CriticalMeasure.class, Thread.class, "currentThread");
|
private final CriticalCloseable autoCloseable = new CriticalCloseable() {
|
||||||
|
ArtemisCloseable beforeClose;
|
||||||
|
|
||||||
// While resetting the leaveMethod, I want to make sure no enter call would reset the value.
|
@Override
|
||||||
// so I set the Current Thread to this Ghost Thread, to then set it back to null
|
public void beforeClose(ArtemisCloseable closeable) {
|
||||||
private static final Thread GHOST_THREAD = new Thread();
|
beforeClose = closeable;
|
||||||
|
}
|
||||||
|
|
||||||
private volatile Thread currentThread;
|
@Override
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
if (beforeClose != null) {
|
||||||
|
beforeClose.close();
|
||||||
|
beforeClose = null;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
leaveCritical();
|
||||||
|
CURRENT_MEASURING.set(CriticalMeasure.this, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected static final CriticalCloseable dummyCloseable = new CriticalCloseable() {
|
||||||
|
@Override
|
||||||
|
public void beforeClose(ArtemisCloseable runnable) {
|
||||||
|
throw new IllegalStateException("The dummy closeable does not support beforeClose. Check before CriticalMeasure.isDummy(closeable) before you call beforeClose(runnable)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// this is working like a boolean, although using AtomicIntegerFieldUpdater instead
|
||||||
|
protected volatile int measuring;
|
||||||
protected volatile long timeEnter;
|
protected volatile long timeEnter;
|
||||||
|
|
||||||
private final int id;
|
private final int id;
|
||||||
|
@ -46,45 +80,43 @@ public class CriticalMeasure {
|
||||||
this.timeEnter = 0;
|
this.timeEnter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enterCritical() {
|
public CriticalCloseable measure() {
|
||||||
|
// I could have chosen to simply store the time on this value, however I would be calling nanoTime a lot of times
|
||||||
// a sampling of a single thread at a time will be sufficient for the analyser,
|
// to just waste the value
|
||||||
// typically what causes one thread to stall will repeat on another
|
// So, I keep a measuring atomic to protect the thread sampling,
|
||||||
if (CURRENT_THREAD_UDPATER.compareAndSet(this, null, Thread.currentThread())) {
|
// and I will still do the set using a single thread.
|
||||||
timeEnter = System.nanoTime();
|
if (CURRENT_MEASURING.compareAndSet(this, 0, 1)) {
|
||||||
|
enterCritical();
|
||||||
if (logger.isTraceEnabled()) {
|
return autoCloseable;
|
||||||
traceEnter = new Exception("entered");
|
} else {
|
||||||
}
|
return dummyCloseable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void leaveCritical() {
|
protected void enterCritical() {
|
||||||
|
timeEnter = System.nanoTime();
|
||||||
|
|
||||||
if (CURRENT_THREAD_UDPATER.compareAndSet(this, Thread.currentThread(), GHOST_THREAD)) {
|
if (logger.isTraceEnabled()) {
|
||||||
// NULL_THREAD here represents a state where I would be ignoring any call to enterCritical or leaveCritical, while I reset the Time Enter Update
|
traceEnter = new Exception("entered");
|
||||||
// This is to avoid replacing time Enter by a new Value, right after current Thread is set to Null.
|
|
||||||
// So we set to this ghost value while we are setting
|
|
||||||
|
|
||||||
if (logger.isTraceEnabled()) {
|
|
||||||
|
|
||||||
CriticalAnalyzer analyzer = component != null ? component.getCriticalAnalyzer() : null;
|
|
||||||
if (analyzer != null) {
|
|
||||||
long nanoTimeout = analyzer.getTimeoutNanoSeconds();
|
|
||||||
if (checkExpiration(nanoTimeout, false)) {
|
|
||||||
logger.trace("Path " + id + " on component " + getComponentName() + " is taking too long, leaving at", new Exception("left"));
|
|
||||||
logger.trace("Path " + id + " on component " + getComponentName() + " is taking too long, entered at", traceEnter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
traceEnter = null;
|
|
||||||
}
|
|
||||||
this.timeEnter = 0;
|
|
||||||
|
|
||||||
// I am pretty sure this is single threaded by now.. I don't need compareAndSet here
|
|
||||||
CURRENT_THREAD_UDPATER.set(this, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void leaveCritical() {
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
|
||||||
|
CriticalAnalyzer analyzer = component != null ? component.getCriticalAnalyzer() : null;
|
||||||
|
if (analyzer != null) {
|
||||||
|
long nanoTimeout = analyzer.getTimeoutNanoSeconds();
|
||||||
|
if (checkExpiration(nanoTimeout, false)) {
|
||||||
|
logger.trace("Path " + id + " on component " + getComponentName() + " is taking too long, leaving at", new Exception("left"));
|
||||||
|
logger.trace("Path " + id + " on component " + getComponentName() + " is taking too long, entered at", traceEnter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
traceEnter = null;
|
||||||
|
}
|
||||||
|
timeEnter = 0L;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getComponentName() {
|
protected String getComponentName() {
|
||||||
if (component == null) {
|
if (component == null) {
|
||||||
return "null";
|
return "null";
|
||||||
|
@ -94,8 +126,8 @@ public class CriticalMeasure {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkExpiration(long timeout, boolean reset) {
|
public boolean checkExpiration(long timeout, boolean reset) {
|
||||||
final long timeEnter = this.timeEnter;
|
final long thisTimeEnter = this.timeEnter;
|
||||||
if (timeEnter != 0L) {
|
if (thisTimeEnter != 0L) {
|
||||||
long time = System.nanoTime();
|
long time = System.nanoTime();
|
||||||
boolean expired = time - timeEnter > timeout;
|
boolean expired = time - timeEnter > timeout;
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,9 @@ package org.apache.activemq.artemis.utils.critical;
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch;
|
import org.apache.activemq.artemis.utils.ReusableLatch;
|
||||||
import org.apache.activemq.artemis.utils.ThreadLeakCheckRule;
|
import org.apache.activemq.artemis.utils.ThreadLeakCheckRule;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
@ -41,10 +43,75 @@ public class CriticalAnalyzerTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDummy() {
|
||||||
|
|
||||||
|
analyzer = new CriticalAnalyzerImpl().setTimeout(100, TimeUnit.MILLISECONDS).setCheckTime(50, TimeUnit.MILLISECONDS);
|
||||||
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
|
||||||
|
analyzer.add(component);
|
||||||
|
|
||||||
|
CriticalCloseable closeable1 = component.measureCritical(0);
|
||||||
|
|
||||||
|
Assert.assertFalse(CriticalMeasure.isDummy(closeable1));
|
||||||
|
|
||||||
|
ArtemisCloseable closeable2 = component.measureCritical(0);
|
||||||
|
|
||||||
|
Assert.assertTrue(CriticalMeasure.isDummy(closeable2));
|
||||||
|
|
||||||
|
closeable1.close();
|
||||||
|
|
||||||
|
closeable2 = component.measureCritical(0);
|
||||||
|
|
||||||
|
Assert.assertFalse(CriticalMeasure.isDummy(closeable2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCall() {
|
||||||
|
|
||||||
|
analyzer = new CriticalAnalyzerImpl().setTimeout(100, TimeUnit.MILLISECONDS).setCheckTime(50, TimeUnit.MILLISECONDS);
|
||||||
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
|
||||||
|
analyzer.add(component);
|
||||||
|
|
||||||
|
CriticalCloseable closeable = component.measureCritical(0);
|
||||||
|
Assert.assertFalse(CriticalMeasure.isDummy(closeable));
|
||||||
|
|
||||||
|
CriticalCloseable dummy = component.measureCritical(0);
|
||||||
|
|
||||||
|
boolean exception = false;
|
||||||
|
try {
|
||||||
|
dummy.beforeClose(() -> System.out.println("never hapening"));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
exception = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertTrue(exception);
|
||||||
|
|
||||||
|
AtomicInteger value = new AtomicInteger(0);
|
||||||
|
|
||||||
|
closeable.beforeClose(() -> value.set(1000));
|
||||||
|
|
||||||
|
Assert.assertEquals(0, value.get());
|
||||||
|
|
||||||
|
closeable.close();
|
||||||
|
|
||||||
|
Assert.assertEquals(1000, value.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAction() throws Exception {
|
public void testAction() throws Exception {
|
||||||
analyzer = new CriticalAnalyzerImpl().setTimeout(100, TimeUnit.MILLISECONDS).setCheckTime(50, TimeUnit.MILLISECONDS);
|
analyzer = new CriticalAnalyzerImpl().setTimeout(100, TimeUnit.MILLISECONDS).setCheckTime(50, TimeUnit.MILLISECONDS);
|
||||||
analyzer.add(new CriticalComponent() {
|
analyzer.add(new CriticalComponent() {
|
||||||
|
@Override
|
||||||
|
public CriticalAnalyzer getCriticalAnalyzer() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CriticalCloseable measureCritical(int path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkExpiration(long timeout, boolean reset) {
|
public boolean checkExpiration(long timeout, boolean reset) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -77,9 +144,8 @@ public class CriticalAnalyzerTest {
|
||||||
CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
|
||||||
analyzer.add(component);
|
analyzer.add(component);
|
||||||
|
|
||||||
component.enterCritical(0);
|
component.measureCritical(0).close();
|
||||||
component.leaveCritical(0);
|
component.measureCritical(1);
|
||||||
component.enterCritical(1);
|
|
||||||
|
|
||||||
|
|
||||||
analyzer.start();
|
analyzer.start();
|
||||||
|
@ -93,7 +159,7 @@ public class CriticalAnalyzerTest {
|
||||||
public void testEnterNoLeaveNoExpire() throws Exception {
|
public void testEnterNoLeaveNoExpire() throws Exception {
|
||||||
analyzer = new CriticalAnalyzerImpl().setTimeout(10, TimeUnit.MILLISECONDS).setCheckTime(5, TimeUnit.MILLISECONDS);
|
analyzer = new CriticalAnalyzerImpl().setTimeout(10, TimeUnit.MILLISECONDS).setCheckTime(5, TimeUnit.MILLISECONDS);
|
||||||
CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
|
||||||
component.enterCritical(0);
|
component.measureCritical(0);
|
||||||
Assert.assertFalse(component.checkExpiration(TimeUnit.MINUTES.toNanos(1), false));
|
Assert.assertFalse(component.checkExpiration(TimeUnit.MINUTES.toNanos(1), false));
|
||||||
analyzer.stop();
|
analyzer.stop();
|
||||||
|
|
||||||
|
@ -103,7 +169,7 @@ public class CriticalAnalyzerTest {
|
||||||
public void testEnterNoLeaveExpire() throws Exception {
|
public void testEnterNoLeaveExpire() throws Exception {
|
||||||
analyzer = new CriticalAnalyzerImpl().setTimeout(10, TimeUnit.MILLISECONDS).setCheckTime(5, TimeUnit.MILLISECONDS);
|
analyzer = new CriticalAnalyzerImpl().setTimeout(10, TimeUnit.MILLISECONDS).setCheckTime(5, TimeUnit.MILLISECONDS);
|
||||||
CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
|
||||||
component.enterCritical(0);
|
component.measureCritical(0);
|
||||||
Thread.sleep(50);
|
Thread.sleep(50);
|
||||||
Assert.assertTrue(component.checkExpiration(0, false));
|
Assert.assertTrue(component.checkExpiration(0, false));
|
||||||
analyzer.stop();
|
analyzer.stop();
|
||||||
|
@ -123,8 +189,7 @@ public class CriticalAnalyzerTest {
|
||||||
CriticalComponent component = new CriticalComponentImpl(analyzer, 1);
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 1);
|
||||||
analyzer.add(component);
|
analyzer.add(component);
|
||||||
|
|
||||||
component.enterCritical(0);
|
component.measureCritical(0).close();
|
||||||
component.leaveCritical(0);
|
|
||||||
|
|
||||||
analyzer.start();
|
analyzer.start();
|
||||||
|
|
||||||
|
@ -146,14 +211,14 @@ public class CriticalAnalyzerTest {
|
||||||
CriticalComponent component = new CriticalComponentImpl(analyzer, 1);
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 1);
|
||||||
analyzer.add(component);
|
analyzer.add(component);
|
||||||
|
|
||||||
component.enterCritical(0);
|
AutoCloseable measure = component.measureCritical(0);
|
||||||
Thread.sleep(50);
|
Thread.sleep(50);
|
||||||
|
|
||||||
analyzer.start();
|
analyzer.start();
|
||||||
|
|
||||||
Assert.assertTrue(latch.await(100, TimeUnit.MILLISECONDS));
|
Assert.assertTrue(latch.await(100, TimeUnit.MILLISECONDS));
|
||||||
|
|
||||||
component.leaveCritical(0);
|
measure.close();
|
||||||
|
|
||||||
latch.setCount(1);
|
latch.setCount(1);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package org.apache.activemq.artemis.utils.critical;
|
package org.apache.activemq.artemis.utils.critical;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.LockSupport;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -38,7 +39,7 @@ public class CriticalMeasureTest {
|
||||||
CriticalComponent component = new CriticalComponentImpl(analyzer, 5);
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 5);
|
||||||
CriticalMeasure measure = new CriticalMeasure(component, 1);
|
CriticalMeasure measure = new CriticalMeasure(component, 1);
|
||||||
long time = System.nanoTime();
|
long time = System.nanoTime();
|
||||||
CriticalMeasure.CURRENT_THREAD_UDPATER.set(measure, Thread.currentThread());
|
measure.enterCritical();
|
||||||
measure.timeEnter = time - TimeUnit.MINUTES.toNanos(30);
|
measure.timeEnter = time - TimeUnit.MINUTES.toNanos(30);
|
||||||
measure.leaveCritical();
|
measure.leaveCritical();
|
||||||
Assert.assertFalse(measure.checkExpiration(TimeUnit.SECONDS.toNanos(30), false));
|
Assert.assertFalse(measure.checkExpiration(TimeUnit.SECONDS.toNanos(30), false));
|
||||||
|
@ -50,13 +51,26 @@ public class CriticalMeasureTest {
|
||||||
CriticalComponent component = new CriticalComponentImpl(analyzer, 5);
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 5);
|
||||||
CriticalMeasure measure = new CriticalMeasure(component, 1);
|
CriticalMeasure measure = new CriticalMeasure(component, 1);
|
||||||
long time = System.nanoTime();
|
long time = System.nanoTime();
|
||||||
measure.enterCritical();
|
AutoCloseable closeable = measure.measure();
|
||||||
measure.timeEnter = time - TimeUnit.MINUTES.toNanos(5);
|
measure.timeEnter = time - TimeUnit.MINUTES.toNanos(5);
|
||||||
Assert.assertTrue(measure.checkExpiration(TimeUnit.SECONDS.toNanos(30), false));
|
Assert.assertTrue(measure.checkExpiration(TimeUnit.SECONDS.toNanos(30), false)); // on this call we should had a reset before
|
||||||
// subsequent call without reset should still fail
|
// subsequent call without reset should still fail
|
||||||
Assert.assertTrue(measure.checkExpiration(TimeUnit.SECONDS.toNanos(30), true));
|
Assert.assertTrue(measure.checkExpiration(TimeUnit.SECONDS.toNanos(30), true));
|
||||||
// previous reset should have cleared it
|
// previous reset should have cleared it
|
||||||
Assert.assertFalse(measure.checkExpiration(TimeUnit.SECONDS.toNanos(30), false));
|
Assert.assertFalse(measure.checkExpiration(TimeUnit.SECONDS.toNanos(30), false));
|
||||||
measure.leaveCritical();
|
closeable.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithCloseable() throws Exception {
|
||||||
|
CriticalAnalyzer analyzer = new CriticalAnalyzerImpl();
|
||||||
|
CriticalComponent component = new CriticalComponentImpl(analyzer, 5);
|
||||||
|
CriticalMeasure measure = new CriticalMeasure(component, 1);
|
||||||
|
long time = System.nanoTime();
|
||||||
|
try (AutoCloseable theMeasure = component.measureCritical(0)) {
|
||||||
|
LockSupport.parkNanos(1000);
|
||||||
|
Assert.assertTrue(component.checkExpiration(100, false));
|
||||||
|
}
|
||||||
|
Assert.assertFalse(component.checkExpiration(100, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class MultiThreadCriticalMeasureTest {
|
||||||
ReusableLatch latch = new ReusableLatch(0);
|
ReusableLatch latch = new ReusableLatch(0);
|
||||||
ReusableLatch latchOnMeasure = new ReusableLatch(0);
|
ReusableLatch latchOnMeasure = new ReusableLatch(0);
|
||||||
try {
|
try {
|
||||||
CriticalMeasure measure = new CriticalMeasure((t, r) -> false, 0);
|
CriticalMeasure measure = new CriticalMeasure(null, 0);
|
||||||
|
|
||||||
CyclicBarrier barrier = new CyclicBarrier(THREADS + 1);
|
CyclicBarrier barrier = new CyclicBarrier(THREADS + 1);
|
||||||
|
|
||||||
|
@ -56,9 +56,9 @@ public class MultiThreadCriticalMeasureTest {
|
||||||
latch.await();
|
latch.await();
|
||||||
}
|
}
|
||||||
|
|
||||||
measure.enterCritical();
|
try (AutoCloseable closeable = measure.measure()) {
|
||||||
latchOnMeasure.await();
|
latchOnMeasure.await();
|
||||||
measure.leaveCritical();
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.apache.activemq.artemis.core.buffers.impl.ChannelBufferWrapper;
|
||||||
import org.apache.activemq.artemis.core.io.IOCallback;
|
import org.apache.activemq.artemis.core.io.IOCallback;
|
||||||
import org.apache.activemq.artemis.core.journal.EncodingSupport;
|
import org.apache.activemq.artemis.core.journal.EncodingSupport;
|
||||||
import org.apache.activemq.artemis.journal.ActiveMQJournalLogger;
|
import org.apache.activemq.artemis.journal.ActiveMQJournalLogger;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzer;
|
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzer;
|
||||||
import org.apache.activemq.artemis.utils.critical.CriticalComponentImpl;
|
import org.apache.activemq.artemis.utils.critical.CriticalComponentImpl;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
@ -56,46 +57,30 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
private static final int MAX_CHECKS_ON_SLEEP = 20;
|
private static final int MAX_CHECKS_ON_SLEEP = 20;
|
||||||
|
|
||||||
// Attributes ----------------------------------------------------
|
// Attributes ----------------------------------------------------
|
||||||
|
|
||||||
private TimedBufferObserver bufferObserver;
|
|
||||||
|
|
||||||
// If the TimedBuffer is idle - i.e. no records are being added, then it's pointless the timer flush thread
|
// If the TimedBuffer is idle - i.e. no records are being added, then it's pointless the timer flush thread
|
||||||
// in spinning and checking the time - and using up CPU in the process - this semaphore is used to
|
// in spinning and checking the time - and using up CPU in the process - this semaphore is used to
|
||||||
// prevent that
|
// prevent that
|
||||||
private final Semaphore spinLimiter = new Semaphore(1);
|
private final Semaphore spinLimiter = new Semaphore(1);
|
||||||
|
|
||||||
private CheckTimer timerRunnable;
|
|
||||||
|
|
||||||
private final int bufferSize;
|
private final int bufferSize;
|
||||||
|
|
||||||
private final ActiveMQBuffer buffer;
|
private final ActiveMQBuffer buffer;
|
||||||
|
|
||||||
private int bufferLimit = 0;
|
|
||||||
|
|
||||||
private List<IOCallback> callbacks;
|
|
||||||
|
|
||||||
private final int timeout;
|
private final int timeout;
|
||||||
|
private final boolean logRates;
|
||||||
|
private final AtomicLong bytesFlushed = new AtomicLong(0);
|
||||||
|
private final AtomicLong flushesDone = new AtomicLong(0);
|
||||||
|
private TimedBufferObserver bufferObserver;
|
||||||
|
private CheckTimer timerRunnable;
|
||||||
|
private int bufferLimit = 0;
|
||||||
|
private List<IOCallback> callbacks;
|
||||||
// used to measure sync requests. When a sync is requested, it shouldn't take more than timeout to happen
|
// used to measure sync requests. When a sync is requested, it shouldn't take more than timeout to happen
|
||||||
private volatile boolean pendingSync = false;
|
private volatile boolean pendingSync = false;
|
||||||
|
|
||||||
|
// for logging write rates
|
||||||
private Thread timerThread;
|
private Thread timerThread;
|
||||||
|
|
||||||
private volatile boolean started;
|
private volatile boolean started;
|
||||||
|
|
||||||
// We use this flag to prevent flush occurring between calling checkSize and addBytes
|
// We use this flag to prevent flush occurring between calling checkSize and addBytes
|
||||||
// CheckSize must always be followed by it's corresponding addBytes otherwise the buffer
|
// CheckSize must always be followed by it's corresponding addBytes otherwise the buffer
|
||||||
// can get in an inconsistent state
|
// can get in an inconsistent state
|
||||||
private boolean delayFlush;
|
private boolean delayFlush;
|
||||||
|
|
||||||
// for logging write rates
|
|
||||||
|
|
||||||
private final boolean logRates;
|
|
||||||
|
|
||||||
private final AtomicLong bytesFlushed = new AtomicLong(0);
|
|
||||||
|
|
||||||
private final AtomicLong flushesDone = new AtomicLong(0);
|
|
||||||
|
|
||||||
private Timer logRatesTimer;
|
private Timer logRatesTimer;
|
||||||
|
|
||||||
private TimerTask logRatesTimerTask;
|
private TimerTask logRatesTimerTask;
|
||||||
|
@ -135,8 +120,7 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
enterCritical(CRITICAL_PATH_START);
|
try (ArtemisCloseable critical = measureCritical(CRITICAL_PATH_START)) {
|
||||||
try {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (started) {
|
if (started) {
|
||||||
return;
|
return;
|
||||||
|
@ -163,15 +147,12 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
|
|
||||||
started = true;
|
started = true;
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_START);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
enterCritical(CRITICAL_PATH_STOP);
|
|
||||||
Thread localTimer = null;
|
Thread localTimer = null;
|
||||||
try {
|
try (ArtemisCloseable measure = measureCritical(CRITICAL_PATH_STOP)) {
|
||||||
// add critical analyzer here.... <<<<
|
// add critical analyzer here.... <<<<
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
try {
|
try {
|
||||||
|
@ -210,14 +191,11 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_STOP);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setObserver(final TimedBufferObserver observer) {
|
public void setObserver(final TimedBufferObserver observer) {
|
||||||
enterCritical(CRITICAL_PATH_SET_OBSERVER);
|
try (AutoCloseable measure = measureCritical(CRITICAL_PATH_SET_OBSERVER)) {
|
||||||
try {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (bufferObserver != null) {
|
if (bufferObserver != null) {
|
||||||
flush();
|
flush();
|
||||||
|
@ -225,8 +203,8 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
|
|
||||||
bufferObserver = observer;
|
bufferObserver = observer;
|
||||||
}
|
}
|
||||||
} finally {
|
} catch (Exception shouldNotHappen) {
|
||||||
leaveCritical(CRITICAL_PATH_SET_OBSERVER);
|
logger.debug(shouldNotHappen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,8 +214,7 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
* @param sizeChecked
|
* @param sizeChecked
|
||||||
*/
|
*/
|
||||||
public boolean checkSize(final int sizeChecked) {
|
public boolean checkSize(final int sizeChecked) {
|
||||||
enterCritical(CRITICAL_PATH_CHECK_SIZE);
|
try (ArtemisCloseable measure = measureCritical(CRITICAL_PATH_CHECK_SIZE)) {
|
||||||
try {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
throw new IllegalStateException("TimedBuffer is not started");
|
throw new IllegalStateException("TimedBuffer is not started");
|
||||||
|
@ -274,14 +251,11 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_CHECK_SIZE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBytes(final ActiveMQBuffer bytes, final boolean sync, final IOCallback callback) {
|
public void addBytes(final ActiveMQBuffer bytes, final boolean sync, final IOCallback callback) {
|
||||||
enterCritical(CRITICAL_PATH_ADD_BYTES);
|
try (ArtemisCloseable measure = measureCritical(CRITICAL_PATH_ADD_BYTES)) {
|
||||||
try {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
throw new IllegalStateException("TimedBuffer is not started");
|
throw new IllegalStateException("TimedBuffer is not started");
|
||||||
|
@ -303,14 +277,11 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
startSpin();
|
startSpin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_ADD_BYTES);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBytes(final EncodingSupport bytes, final boolean sync, final IOCallback callback) {
|
public void addBytes(final EncodingSupport bytes, final boolean sync, final IOCallback callback) {
|
||||||
enterCritical(CRITICAL_PATH_ADD_BYTES);
|
try (ArtemisCloseable measure = measureCritical(CRITICAL_PATH_ADD_BYTES)) {
|
||||||
try {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
throw new IllegalStateException("TimedBuffer is not started");
|
throw new IllegalStateException("TimedBuffer is not started");
|
||||||
|
@ -328,10 +299,7 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
startSpin();
|
startSpin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_ADD_BYTES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() {
|
public void flush() {
|
||||||
|
@ -344,8 +312,7 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
* @return {@code true} when are flushed any bytes, {@code false} otherwise
|
* @return {@code true} when are flushed any bytes, {@code false} otherwise
|
||||||
*/
|
*/
|
||||||
public boolean flushBatch() {
|
public boolean flushBatch() {
|
||||||
enterCritical(CRITICAL_PATH_FLUSH);
|
try (ArtemisCloseable measure = measureCritical(CRITICAL_PATH_FLUSH)) {
|
||||||
try {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
throw new IllegalStateException("TimedBuffer is not started");
|
throw new IllegalStateException("TimedBuffer is not started");
|
||||||
|
@ -378,8 +345,6 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_FLUSH);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,6 +356,43 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
|
|
||||||
// Inner classes -------------------------------------------------
|
// Inner classes -------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub classes (tests basically) can use this to override how the sleep is being done
|
||||||
|
*
|
||||||
|
* @param sleepNanos
|
||||||
|
*/
|
||||||
|
protected void sleep(long sleepNanos) {
|
||||||
|
LockSupport.parkNanos(sleepNanos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub classes (tests basically) can use this to override disabling spinning
|
||||||
|
*/
|
||||||
|
protected void stopSpin() {
|
||||||
|
if (spinning) {
|
||||||
|
try {
|
||||||
|
// We acquire the spinLimiter semaphore - this prevents the timer flush thread unnecessarily spinning
|
||||||
|
// when the buffer is inactive
|
||||||
|
spinLimiter.acquire();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new ActiveMQInterruptedException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
spinning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub classes (tests basically) can use this to override disabling spinning
|
||||||
|
*/
|
||||||
|
protected void startSpin() {
|
||||||
|
if (!spinning) {
|
||||||
|
spinLimiter.release();
|
||||||
|
|
||||||
|
spinning = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class LogRatesTimerTask extends TimerTask {
|
private class LogRatesTimerTask extends TimerTask {
|
||||||
|
|
||||||
private boolean closed;
|
private boolean closed;
|
||||||
|
@ -434,10 +436,9 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
|
|
||||||
private class CheckTimer implements Runnable {
|
private class CheckTimer implements Runnable {
|
||||||
|
|
||||||
private volatile boolean closed = false;
|
|
||||||
|
|
||||||
int checks = 0;
|
int checks = 0;
|
||||||
int failedChecks = 0;
|
int failedChecks = 0;
|
||||||
|
private volatile boolean closed = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -523,41 +524,4 @@ public final class TimedBuffer extends CriticalComponentImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sub classes (tests basically) can use this to override how the sleep is being done
|
|
||||||
*
|
|
||||||
* @param sleepNanos
|
|
||||||
*/
|
|
||||||
protected void sleep(long sleepNanos) {
|
|
||||||
LockSupport.parkNanos(sleepNanos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sub classes (tests basically) can use this to override disabling spinning
|
|
||||||
*/
|
|
||||||
protected void stopSpin() {
|
|
||||||
if (spinning) {
|
|
||||||
try {
|
|
||||||
// We acquire the spinLimiter semaphore - this prevents the timer flush thread unnecessarily spinning
|
|
||||||
// when the buffer is inactive
|
|
||||||
spinLimiter.acquire();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new ActiveMQInterruptedException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
spinning = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sub classes (tests basically) can use this to override disabling spinning
|
|
||||||
*/
|
|
||||||
protected void startSpin() {
|
|
||||||
if (!spinning) {
|
|
||||||
spinLimiter.release();
|
|
||||||
|
|
||||||
spinning = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -42,6 +42,7 @@ import org.apache.activemq.artemis.core.persistence.StorageManager;
|
||||||
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
|
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
|
||||||
import org.apache.activemq.artemis.core.transaction.Transaction;
|
import org.apache.activemq.artemis.core.transaction.Transaction;
|
||||||
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
|
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.apache.activemq.artemis.utils.SoftValueLongObjectHashMap;
|
import org.apache.activemq.artemis.utils.SoftValueLongObjectHashMap;
|
||||||
import org.apache.activemq.artemis.utils.ThreadDumpUtil;
|
import org.apache.activemq.artemis.utils.ThreadDumpUtil;
|
||||||
import org.apache.activemq.artemis.utils.actors.ArtemisExecutor;
|
import org.apache.activemq.artemis.utils.actors.ArtemisExecutor;
|
||||||
|
@ -438,80 +439,76 @@ public class PageCursorProviderImpl implements PageCursorProvider {
|
||||||
//
|
//
|
||||||
// I tried to simplify the locks but each PageStore has its own lock, so this was the best option
|
// I tried to simplify the locks but each PageStore has its own lock, so this was the best option
|
||||||
// I found in order to fix https://issues.apache.org/jira/browse/ARTEMIS-3054
|
// I found in order to fix https://issues.apache.org/jira/browse/ARTEMIS-3054
|
||||||
storageManager.readLock();
|
try (ArtemisCloseable readLock = storageManager.closeableReadLock()) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (pagingStore.lock(100)) {
|
if (pagingStore.lock(100)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
if (!pagingStore.isStarted())
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (!pagingStore.isStarted())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.tracef("%s locked", this);
|
logger.tracef("%s locked", this);
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
try {
|
|
||||||
if (!pagingStore.isStarted()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pagingStore.getNumberOfPages() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<PageSubscription> cursorList = cloneSubscriptions();
|
|
||||||
|
|
||||||
long minPage = checkMinPage(cursorList);
|
|
||||||
deliverIfNecessary(cursorList, minPage);
|
|
||||||
|
|
||||||
logger.debugf("Asserting cleanup for address %s, firstPage=%d", pagingStore.getAddress(), minPage);
|
|
||||||
|
|
||||||
// if the current page is being written...
|
|
||||||
// on that case we need to move to verify it in a different way
|
|
||||||
if (minPage == pagingStore.getCurrentWritingPage() && pagingStore.getCurrentPage().getNumberOfMessages() > 0) {
|
|
||||||
boolean complete = checkPageCompletion(cursorList, minPage);
|
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
try {
|
||||||
if (!pagingStore.isStarted()) {
|
if (!pagingStore.isStarted()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All the pages on the cursor are complete.. so we will cleanup everything and store a bookmark
|
if (pagingStore.getNumberOfPages() == 0) {
|
||||||
if (complete) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cleanupComplete(cursorList);
|
ArrayList<PageSubscription> cursorList = cloneSubscriptions();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (long i = pagingStore.getFirstPage(); i <= minPage; i++) {
|
long minPage = checkMinPage(cursorList);
|
||||||
if (!checkPageCompletion(cursorList, i)) {
|
deliverIfNecessary(cursorList, minPage);
|
||||||
break;
|
|
||||||
}
|
|
||||||
Page page = pagingStore.depage();
|
|
||||||
if (page == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
depagedPages.add(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pagingStore.getNumberOfPages() == 0 || pagingStore.getNumberOfPages() == 1 && pagingStore.getCurrentPage().getNumberOfMessages() == 0) {
|
logger.debugf("Asserting cleanup for address %s, firstPage=%d", pagingStore.getAddress(), minPage);
|
||||||
pagingStore.stopPaging();
|
|
||||||
} else {
|
// if the current page is being written...
|
||||||
if (logger.isTraceEnabled()) {
|
// on that case we need to move to verify it in a different way
|
||||||
logger.trace("Couldn't cleanup page on address " + this.pagingStore.getAddress() +
|
if (minPage == pagingStore.getCurrentWritingPage() && pagingStore.getCurrentPage().getNumberOfMessages() > 0) {
|
||||||
" as numberOfPages == " +
|
boolean complete = checkPageCompletion(cursorList, minPage);
|
||||||
pagingStore.getNumberOfPages() +
|
|
||||||
" and currentPage.numberOfMessages = " +
|
if (!pagingStore.isStarted()) {
|
||||||
pagingStore.getCurrentPage().getNumberOfMessages());
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the pages on the cursor are complete.. so we will cleanup everything and store a bookmark
|
||||||
|
if (complete) {
|
||||||
|
|
||||||
|
cleanupComplete(cursorList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (long i = pagingStore.getFirstPage(); i <= minPage; i++) {
|
||||||
|
if (!checkPageCompletion(cursorList, i)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Page page = pagingStore.depage();
|
||||||
|
if (page == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
depagedPages.add(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagingStore.getNumberOfPages() == 0 || pagingStore.getNumberOfPages() == 1 && pagingStore.getCurrentPage().getNumberOfMessages() == 0) {
|
||||||
|
pagingStore.stopPaging();
|
||||||
|
} else {
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Couldn't cleanup page on address " + this.pagingStore.getAddress() + " as numberOfPages == " + pagingStore.getNumberOfPages() + " and currentPage.numberOfMessages = " + pagingStore.getCurrentPage().getNumberOfMessages());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ActiveMQServerLogger.LOGGER.problemCleaningPageAddress(ex, pagingStore.getAddress());
|
||||||
|
logger.warn(ex.getMessage(), ex);
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
pagingStore.unlock();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
|
||||||
ActiveMQServerLogger.LOGGER.problemCleaningPageAddress(ex, pagingStore.getAddress());
|
|
||||||
logger.warn(ex.getMessage(), ex);
|
|
||||||
return;
|
|
||||||
} finally {
|
|
||||||
pagingStore.unlock();
|
|
||||||
storageManager.readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finishCleanup(depagedPages);
|
finishCleanup(depagedPages);
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.apache.activemq.artemis.core.transaction.TransactionOperation;
|
||||||
import org.apache.activemq.artemis.core.transaction.TransactionOperationAbstract;
|
import org.apache.activemq.artemis.core.transaction.TransactionOperationAbstract;
|
||||||
import org.apache.activemq.artemis.core.transaction.TransactionPropertyIndexes;
|
import org.apache.activemq.artemis.core.transaction.TransactionPropertyIndexes;
|
||||||
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
|
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,8 +255,7 @@ public class PageSubscriptionCounterImpl implements PageSubscriptionCounter {
|
||||||
@Override
|
@Override
|
||||||
public void delete(Transaction tx) throws Exception {
|
public void delete(Transaction tx) throws Exception {
|
||||||
// always lock the StorageManager first.
|
// always lock the StorageManager first.
|
||||||
storage.readLock();
|
try (ArtemisCloseable lock = storage.closeableReadLock()) {
|
||||||
try {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
for (Long record : incrementRecords) {
|
for (Long record : incrementRecords) {
|
||||||
storage.deleteIncrementRecord(tx.getID(), record.longValue());
|
storage.deleteIncrementRecord(tx.getID(), record.longValue());
|
||||||
|
@ -271,8 +271,6 @@ public class PageSubscriptionCounterImpl implements PageSubscriptionCounter {
|
||||||
value.set(0);
|
value.set(0);
|
||||||
incrementRecords.clear();
|
incrementRecords.clear();
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
storage.readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
||||||
import org.apache.activemq.artemis.core.server.impl.JournalLoader;
|
import org.apache.activemq.artemis.core.server.impl.JournalLoader;
|
||||||
import org.apache.activemq.artemis.core.transaction.ResourceManager;
|
import org.apache.activemq.artemis.core.transaction.ResourceManager;
|
||||||
import org.apache.activemq.artemis.core.transaction.Transaction;
|
import org.apache.activemq.artemis.core.transaction.Transaction;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.apache.activemq.artemis.utils.IDGenerator;
|
import org.apache.activemq.artemis.utils.IDGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -479,15 +480,9 @@ public interface StorageManager extends IDGenerator, ActiveMQComponent {
|
||||||
* say Paging classes, that use locks of their own AND also write through the StorageManager MUST
|
* say Paging classes, that use locks of their own AND also write through the StorageManager MUST
|
||||||
* first read lock the storageManager before taking their own locks. Otherwise, we may dead-lock
|
* first read lock the storageManager before taking their own locks. Otherwise, we may dead-lock
|
||||||
* when starting replication sync.
|
* when starting replication sync.
|
||||||
*/
|
|
||||||
void readLock();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlock the manager.
|
|
||||||
*
|
*
|
||||||
* @see StorageManager#readLock()
|
|
||||||
*/
|
*/
|
||||||
void readUnLock();
|
ArtemisCloseable closeableReadLock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the {@link IDGenerator} persisting the current record ID.
|
* Closes the {@link IDGenerator} persisting the current record ID.
|
||||||
|
|
|
@ -116,12 +116,15 @@ import org.apache.activemq.artemis.core.transaction.Transaction;
|
||||||
import org.apache.activemq.artemis.core.transaction.TransactionPropertyIndexes;
|
import org.apache.activemq.artemis.core.transaction.TransactionPropertyIndexes;
|
||||||
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
|
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
|
||||||
import org.apache.activemq.artemis.spi.core.protocol.MessagePersister;
|
import org.apache.activemq.artemis.spi.core.protocol.MessagePersister;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.apache.activemq.artemis.utils.ExecutorFactory;
|
import org.apache.activemq.artemis.utils.ExecutorFactory;
|
||||||
import org.apache.activemq.artemis.utils.IDGenerator;
|
import org.apache.activemq.artemis.utils.IDGenerator;
|
||||||
import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashMap;
|
import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashMap;
|
||||||
import org.apache.activemq.artemis.utils.collections.SparseArrayLinkedList;
|
import org.apache.activemq.artemis.utils.collections.SparseArrayLinkedList;
|
||||||
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzer;
|
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzer;
|
||||||
|
import org.apache.activemq.artemis.utils.critical.CriticalCloseable;
|
||||||
import org.apache.activemq.artemis.utils.critical.CriticalComponentImpl;
|
import org.apache.activemq.artemis.utils.critical.CriticalComponentImpl;
|
||||||
|
import org.apache.activemq.artemis.utils.critical.CriticalMeasure;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,6 +174,11 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
|
|
||||||
protected final ReentrantReadWriteLock storageManagerLock = new ReentrantReadWriteLock(true);
|
protected final ReentrantReadWriteLock storageManagerLock = new ReentrantReadWriteLock(true);
|
||||||
|
|
||||||
|
// I would rather cache the Closeable instance here..
|
||||||
|
// I never know when the JRE decides to create a new instance on every call.
|
||||||
|
// So I'm playing safe here. That's all
|
||||||
|
protected final ArtemisCloseable unlockCloseable = storageManagerLock.readLock()::unlock;
|
||||||
|
|
||||||
protected Journal messageJournal;
|
protected Journal messageJournal;
|
||||||
|
|
||||||
protected Journal bindingsJournal;
|
protected Journal bindingsJournal;
|
||||||
|
@ -340,12 +348,9 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void confirmPendingLargeMessageTX(final Transaction tx, long messageID, long recordID) throws Exception {
|
public void confirmPendingLargeMessageTX(final Transaction tx, long messageID, long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
installLargeMessageConfirmationOnTX(tx, recordID);
|
installLargeMessageConfirmationOnTX(tx, recordID);
|
||||||
messageJournal.appendDeleteRecordTransactional(tx.getID(), recordID, new DeleteEncoding(JournalRecordIds.ADD_LARGE_MESSAGE_PENDING, messageID));
|
messageJournal.appendDeleteRecordTransactional(tx.getID(), recordID, new DeleteEncoding(JournalRecordIds.ADD_LARGE_MESSAGE_PENDING, messageID));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,11 +359,8 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void confirmPendingLargeMessage(long recordID) throws Exception {
|
public void confirmPendingLargeMessage(long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendDeleteRecord(recordID, true, getContext());
|
messageJournal.appendDeleteRecord(recordID, true, getContext());
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,9 +371,7 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
throw ActiveMQMessageBundle.BUNDLE.messageIdNotAssigned();
|
throw ActiveMQMessageBundle.BUNDLE.messageIdNotAssigned();
|
||||||
}
|
}
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) { // Note that we don't sync, the add reference that comes immediately after will sync if
|
||||||
try {
|
|
||||||
// Note that we don't sync, the add reference that comes immediately after will sync if
|
|
||||||
// appropriate
|
// appropriate
|
||||||
|
|
||||||
if (message.isLargeMessage() && message instanceof LargeServerMessageImpl) {
|
if (message.isLargeMessage() && message instanceof LargeServerMessageImpl) {
|
||||||
|
@ -379,109 +379,100 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
} else {
|
} else {
|
||||||
messageJournal.appendAddRecord(message.getMessageID(), JournalRecordIds.ADD_MESSAGE_PROTOCOL, message.getPersister(), message, false, getContext(false));
|
messageJournal.appendAddRecord(message.getMessageID(), JournalRecordIds.ADD_MESSAGE_PROTOCOL, message.getPersister(), message, false, getContext(false));
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeReference(final long queueID, final long messageID, final boolean last) throws Exception {
|
public void storeReference(final long queueID, final long messageID, final boolean last) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendUpdateRecord(messageID, JournalRecordIds.ADD_REF, new RefEncoding(queueID), last && syncNonTransactional, getContext(last && syncNonTransactional));
|
messageJournal.appendUpdateRecord(messageID, JournalRecordIds.ADD_REF, new RefEncoding(queueID), last && syncNonTransactional, getContext(last && syncNonTransactional));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readLock() {
|
public ArtemisCloseable closeableReadLock() {
|
||||||
enterCritical(CRITICAL_STORE);
|
CriticalCloseable measure = measureCritical(CRITICAL_STORE);
|
||||||
storageManagerLock.readLock().lock();
|
storageManagerLock.readLock().lock();
|
||||||
|
|
||||||
|
if (CriticalMeasure.isDummy(measure)) {
|
||||||
|
// The next statement could have been called like this:
|
||||||
|
// return storageManagerLock.readLock()::unlock;
|
||||||
|
// However I wasn't 100% sure the JDK would take good care
|
||||||
|
// of caching for me.
|
||||||
|
// Since this is important to me here, I decided to play safe and
|
||||||
|
// cache it myself
|
||||||
|
return unlockCloseable;
|
||||||
|
} else {
|
||||||
|
// Same applies to the next statement here
|
||||||
|
// measure.beforeClose(storageManagerLock.readLock()::unlock);
|
||||||
|
// I'm just playing safe and caching it myself
|
||||||
|
measure.beforeClose(unlockCloseable);
|
||||||
|
return measure;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void readUnLock() {
|
* for internal use and testsuite, don't use it outside of tests
|
||||||
storageManagerLock.readLock().unlock();
|
*/
|
||||||
leaveCritical(CRITICAL_STORE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** for internal use and testsuite, don't use it outside of tests */
|
|
||||||
public void writeLock() {
|
public void writeLock() {
|
||||||
storageManagerLock.writeLock().lock();
|
storageManagerLock.writeLock().lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** for internal use and testsuite, don't use it outside of tests */
|
/**
|
||||||
|
* for internal use and testsuite, don't use it outside of tests
|
||||||
|
*/
|
||||||
public void writeUnlock() {
|
public void writeUnlock() {
|
||||||
storageManagerLock.writeLock().unlock();
|
storageManagerLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeAcknowledge(final long queueID, final long messageID) throws Exception {
|
public void storeAcknowledge(final long queueID, final long messageID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendUpdateRecord(messageID, JournalRecordIds.ACKNOWLEDGE_REF, new RefEncoding(queueID), syncNonTransactional, getContext(syncNonTransactional));
|
messageJournal.appendUpdateRecord(messageID, JournalRecordIds.ACKNOWLEDGE_REF, new RefEncoding(queueID), syncNonTransactional, getContext(syncNonTransactional));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeCursorAcknowledge(long queueID, PagePosition position) throws Exception {
|
public void storeCursorAcknowledge(long queueID, PagePosition position) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
long ackID = idGenerator.generateID();
|
long ackID = idGenerator.generateID();
|
||||||
position.setRecordID(ackID);
|
position.setRecordID(ackID);
|
||||||
messageJournal.appendAddRecord(ackID, JournalRecordIds.ACKNOWLEDGE_CURSOR, new CursorAckRecordEncoding(queueID, position), syncNonTransactional, getContext(syncNonTransactional));
|
messageJournal.appendAddRecord(ackID, JournalRecordIds.ACKNOWLEDGE_CURSOR, new CursorAckRecordEncoding(queueID, position), syncNonTransactional, getContext(syncNonTransactional));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean deleteMessage(final long messageID) throws Exception {
|
public boolean deleteMessage(final long messageID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
// Messages are deleted on postACK, one after another.
|
// Messages are deleted on postACK, one after another.
|
||||||
// If these deletes are synchronized, we would build up messages on the Executor
|
// If these deletes are synchronized, we would build up messages on the Executor
|
||||||
// increasing chances of losing deletes.
|
// increasing chances of losing deletes.
|
||||||
// The StorageManager should verify messages without references
|
// The StorageManager should verify messages without references
|
||||||
return messageJournal.tryAppendDeleteRecord(messageID, false, getContext(false));
|
return messageJournal.tryAppendDeleteRecord(messageID, false, getContext(false));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateScheduledDeliveryTime(final MessageReference ref) throws Exception {
|
public boolean updateScheduledDeliveryTime(final MessageReference ref) throws Exception {
|
||||||
ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(), ref.getQueue().getID());
|
ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(), ref.getQueue().getID());
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
return messageJournal.tryAppendUpdateRecord(ref.getMessage().getMessageID(), JournalRecordIds.SET_SCHEDULED_DELIVERY_TIME, encoding, syncNonTransactional, getContext(syncNonTransactional));
|
return messageJournal.tryAppendUpdateRecord(ref.getMessage().getMessageID(), JournalRecordIds.SET_SCHEDULED_DELIVERY_TIME, encoding, syncNonTransactional, getContext(syncNonTransactional));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeDuplicateID(final SimpleString address, final byte[] duplID, final long recordID) throws Exception {
|
public void storeDuplicateID(final SimpleString address, final byte[] duplID, final long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
DuplicateIDEncoding encoding = new DuplicateIDEncoding(address, duplID);
|
DuplicateIDEncoding encoding = new DuplicateIDEncoding(address, duplID);
|
||||||
|
|
||||||
messageJournal.appendAddRecord(recordID, JournalRecordIds.DUPLICATE_ID, encoding, syncNonTransactional, getContext(syncNonTransactional));
|
messageJournal.appendAddRecord(recordID, JournalRecordIds.DUPLICATE_ID, encoding, syncNonTransactional, getContext(syncNonTransactional));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteDuplicateID(final long recordID) throws Exception {
|
public void deleteDuplicateID(final long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendDeleteRecord(recordID, syncNonTransactional, getContext(syncNonTransactional));
|
messageJournal.appendDeleteRecord(recordID, syncNonTransactional, getContext(syncNonTransactional));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,8 +484,7 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
throw ActiveMQMessageBundle.BUNDLE.messageIdNotAssigned();
|
throw ActiveMQMessageBundle.BUNDLE.messageIdNotAssigned();
|
||||||
}
|
}
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
if (message.isLargeMessage() && message instanceof LargeServerMessageImpl) {
|
if (message.isLargeMessage() && message instanceof LargeServerMessageImpl) {
|
||||||
// this is a core large message
|
// this is a core large message
|
||||||
messageJournal.appendAddRecordTransactional(txID, message.getMessageID(), JournalRecordIds.ADD_LARGE_MESSAGE, LargeMessagePersister.getInstance(), message);
|
messageJournal.appendAddRecordTransactional(txID, message.getMessageID(), JournalRecordIds.ADD_LARGE_MESSAGE, LargeMessagePersister.getInstance(), message);
|
||||||
|
@ -502,19 +492,14 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
messageJournal.appendAddRecordTransactional(txID, message.getMessageID(), JournalRecordIds.ADD_MESSAGE_PROTOCOL, message.getPersister(), message);
|
messageJournal.appendAddRecordTransactional(txID, message.getMessageID(), JournalRecordIds.ADD_MESSAGE_PROTOCOL, message.getPersister(), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storePageTransaction(final long txID, final PageTransactionInfo pageTransaction) throws Exception {
|
public void storePageTransaction(final long txID, final PageTransactionInfo pageTransaction) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
pageTransaction.setRecordID(generateID());
|
pageTransaction.setRecordID(generateID());
|
||||||
messageJournal.appendAddRecordTransactional(txID, pageTransaction.getRecordID(), JournalRecordIds.PAGE_TRANSACTION, pageTransaction);
|
messageJournal.appendAddRecordTransactional(txID, pageTransaction.getRecordID(), JournalRecordIds.PAGE_TRANSACTION, pageTransaction);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,21 +507,15 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public void updatePageTransaction(final long txID,
|
public void updatePageTransaction(final long txID,
|
||||||
final PageTransactionInfo pageTransaction,
|
final PageTransactionInfo pageTransaction,
|
||||||
final int depages) throws Exception {
|
final int depages) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendUpdateRecordTransactional(txID, pageTransaction.getRecordID(), JournalRecordIds.PAGE_TRANSACTION, new PageUpdateTXEncoding(pageTransaction.getTransactionID(), depages));
|
messageJournal.appendUpdateRecordTransactional(txID, pageTransaction.getRecordID(), JournalRecordIds.PAGE_TRANSACTION, new PageUpdateTXEncoding(pageTransaction.getTransactionID(), depages));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeReferenceTransactional(final long txID, final long queueID, final long messageID) throws Exception {
|
public void storeReferenceTransactional(final long txID, final long queueID, final long messageID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendUpdateRecordTransactional(txID, messageID, JournalRecordIds.ADD_REF, new RefEncoding(queueID));
|
messageJournal.appendUpdateRecordTransactional(txID, messageID, JournalRecordIds.ADD_REF, new RefEncoding(queueID));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,23 +523,17 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public void storeAcknowledgeTransactional(final long txID,
|
public void storeAcknowledgeTransactional(final long txID,
|
||||||
final long queueID,
|
final long queueID,
|
||||||
final long messageID) throws Exception {
|
final long messageID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendUpdateRecordTransactional(txID, messageID, JournalRecordIds.ACKNOWLEDGE_REF, new RefEncoding(queueID));
|
messageJournal.appendUpdateRecordTransactional(txID, messageID, JournalRecordIds.ACKNOWLEDGE_REF, new RefEncoding(queueID));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeCursorAcknowledgeTransactional(long txID, long queueID, PagePosition position) throws Exception {
|
public void storeCursorAcknowledgeTransactional(long txID, long queueID, PagePosition position) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
long ackID = idGenerator.generateID();
|
long ackID = idGenerator.generateID();
|
||||||
position.setRecordID(ackID);
|
position.setRecordID(ackID);
|
||||||
messageJournal.appendAddRecordTransactional(txID, ackID, JournalRecordIds.ACKNOWLEDGE_CURSOR, new CursorAckRecordEncoding(queueID, position));
|
messageJournal.appendAddRecordTransactional(txID, ackID, JournalRecordIds.ACKNOWLEDGE_CURSOR, new CursorAckRecordEncoding(queueID, position));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,11 +551,8 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteCursorAcknowledgeTransactional(long txID, long ackID) throws Exception {
|
public void deleteCursorAcknowledgeTransactional(long txID, long ackID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendDeleteRecordTransactional(txID, ackID);
|
messageJournal.appendDeleteRecordTransactional(txID, ackID);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,57 +563,40 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long storeHeuristicCompletion(final Xid xid, final boolean isCommit) throws Exception {
|
public long storeHeuristicCompletion(final Xid xid, final boolean isCommit) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
long id = generateID();
|
long id = generateID();
|
||||||
|
|
||||||
messageJournal.appendAddRecord(id, JournalRecordIds.HEURISTIC_COMPLETION, new HeuristicCompletionEncoding(xid, isCommit), true, getContext(true));
|
messageJournal.appendAddRecord(id, JournalRecordIds.HEURISTIC_COMPLETION, new HeuristicCompletionEncoding(xid, isCommit), true, getContext(true));
|
||||||
return id;
|
return id;
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteHeuristicCompletion(final long id) throws Exception {
|
public void deleteHeuristicCompletion(final long id) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
|
|
||||||
messageJournal.appendDeleteRecord(id, true, getContext(true));
|
messageJournal.appendDeleteRecord(id, true, getContext(true));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deletePageTransactional(final long recordID) throws Exception {
|
public void deletePageTransactional(final long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendDeleteRecord(recordID, false);
|
messageJournal.appendDeleteRecord(recordID, false);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateScheduledDeliveryTimeTransactional(final long txID, final MessageReference ref) throws Exception {
|
public void updateScheduledDeliveryTimeTransactional(final long txID, final MessageReference ref) throws Exception {
|
||||||
ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(), ref.getQueue().getID());
|
ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(), ref.getQueue().getID());
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
|
|
||||||
messageJournal.appendUpdateRecordTransactional(txID, ref.getMessage().getMessageID(), JournalRecordIds.SET_SCHEDULED_DELIVERY_TIME, encoding);
|
messageJournal.appendUpdateRecordTransactional(txID, ref.getMessage().getMessageID(), JournalRecordIds.SET_SCHEDULED_DELIVERY_TIME, encoding);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepare(final long txID, final Xid xid) throws Exception {
|
public void prepare(final long txID, final Xid xid) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendPrepareRecord(txID, new XidEncoding(xid), syncTransactional, getContext(syncTransactional));
|
messageJournal.appendPrepareRecord(txID, new XidEncoding(xid), syncTransactional, getContext(syncTransactional));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,8 +618,7 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void commit(final long txID, final boolean lineUpContext) throws Exception {
|
public void commit(final long txID, final boolean lineUpContext) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendCommitRecord(txID, syncTransactional, getContext(syncTransactional), lineUpContext);
|
messageJournal.appendCommitRecord(txID, syncTransactional, getContext(syncTransactional), lineUpContext);
|
||||||
if (!lineUpContext && !syncTransactional) {
|
if (!lineUpContext && !syncTransactional) {
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
|
@ -681,18 +633,13 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
*/
|
*/
|
||||||
getContext(true).done();
|
getContext(true).done();
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void rollback(final long txID) throws Exception {
|
public void rollback(final long txID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendRollbackRecord(txID, syncTransactional, getContext(syncTransactional));
|
messageJournal.appendRollbackRecord(txID, syncTransactional, getContext(syncTransactional));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,11 +650,8 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
final long recordID) throws Exception {
|
final long recordID) throws Exception {
|
||||||
DuplicateIDEncoding encoding = new DuplicateIDEncoding(address, duplID);
|
DuplicateIDEncoding encoding = new DuplicateIDEncoding(address, duplID);
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendAddRecordTransactional(txID, recordID, JournalRecordIds.DUPLICATE_ID, encoding);
|
messageJournal.appendAddRecordTransactional(txID, recordID, JournalRecordIds.DUPLICATE_ID, encoding);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -718,21 +662,15 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
final long recordID) throws Exception {
|
final long recordID) throws Exception {
|
||||||
DuplicateIDEncoding encoding = new DuplicateIDEncoding(address, duplID);
|
DuplicateIDEncoding encoding = new DuplicateIDEncoding(address, duplID);
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendUpdateRecordTransactional(txID, recordID, JournalRecordIds.DUPLICATE_ID, encoding);
|
messageJournal.appendUpdateRecordTransactional(txID, recordID, JournalRecordIds.DUPLICATE_ID, encoding);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteDuplicateIDTransactional(final long txID, final long recordID) throws Exception {
|
public void deleteDuplicateIDTransactional(final long txID, final long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendDeleteRecordTransactional(txID, recordID);
|
messageJournal.appendDeleteRecordTransactional(txID, recordID);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -749,25 +687,19 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
ref.setPersistedCount(ref.getDeliveryCount());
|
ref.setPersistedCount(ref.getDeliveryCount());
|
||||||
DeliveryCountUpdateEncoding updateInfo = new DeliveryCountUpdateEncoding(ref.getQueue().getID(), ref.getDeliveryCount());
|
DeliveryCountUpdateEncoding updateInfo = new DeliveryCountUpdateEncoding(ref.getQueue().getID(), ref.getDeliveryCount());
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
return messageJournal.tryAppendUpdateRecord(ref.getMessage().getMessageID(), JournalRecordIds.UPDATE_DELIVERY_COUNT, updateInfo, syncNonTransactional, getContext(syncNonTransactional));
|
return messageJournal.tryAppendUpdateRecord(ref.getMessage().getMessageID(), JournalRecordIds.UPDATE_DELIVERY_COUNT, updateInfo, syncNonTransactional, getContext(syncNonTransactional));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeAddressSetting(PersistedAddressSetting addressSetting) throws Exception {
|
public void storeAddressSetting(PersistedAddressSetting addressSetting) throws Exception {
|
||||||
deleteAddressSetting(addressSetting.getAddressMatch());
|
deleteAddressSetting(addressSetting.getAddressMatch());
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
long id = idGenerator.generateID();
|
long id = idGenerator.generateID();
|
||||||
addressSetting.setStoreId(id);
|
addressSetting.setStoreId(id);
|
||||||
bindingsJournal.appendAddRecord(id, JournalRecordIds.ADDRESS_SETTING_RECORD, addressSetting, true);
|
bindingsJournal.appendAddRecord(id, JournalRecordIds.ADDRESS_SETTING_RECORD, addressSetting, true);
|
||||||
mapPersistedAddressSettings.put(addressSetting.getAddressMatch(), addressSetting);
|
mapPersistedAddressSettings.put(addressSetting.getAddressMatch(), addressSetting);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,28 +717,22 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public void storeSecuritySetting(PersistedSecuritySetting persistedRoles) throws Exception {
|
public void storeSecuritySetting(PersistedSecuritySetting persistedRoles) throws Exception {
|
||||||
|
|
||||||
deleteSecuritySetting(persistedRoles.getAddressMatch());
|
deleteSecuritySetting(persistedRoles.getAddressMatch());
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
final long id = idGenerator.generateID();
|
final long id = idGenerator.generateID();
|
||||||
persistedRoles.setStoreId(id);
|
persistedRoles.setStoreId(id);
|
||||||
bindingsJournal.appendAddRecord(id, JournalRecordIds.SECURITY_SETTING_RECORD, persistedRoles, true);
|
bindingsJournal.appendAddRecord(id, JournalRecordIds.SECURITY_SETTING_RECORD, persistedRoles, true);
|
||||||
mapPersistedSecuritySettings.put(persistedRoles.getAddressMatch(), persistedRoles);
|
mapPersistedSecuritySettings.put(persistedRoles.getAddressMatch(), persistedRoles);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeDivertConfiguration(PersistedDivertConfiguration persistedDivertConfiguration) throws Exception {
|
public void storeDivertConfiguration(PersistedDivertConfiguration persistedDivertConfiguration) throws Exception {
|
||||||
deleteDivertConfiguration(persistedDivertConfiguration.getName());
|
deleteDivertConfiguration(persistedDivertConfiguration.getName());
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
final long id = idGenerator.generateID();
|
final long id = idGenerator.generateID();
|
||||||
persistedDivertConfiguration.setStoreId(id);
|
persistedDivertConfiguration.setStoreId(id);
|
||||||
bindingsJournal.appendAddRecord(id, JournalRecordIds.DIVERT_RECORD, persistedDivertConfiguration, true);
|
bindingsJournal.appendAddRecord(id, JournalRecordIds.DIVERT_RECORD, persistedDivertConfiguration, true);
|
||||||
mapPersistedDivertConfigurations.put(persistedDivertConfiguration.getName(), persistedDivertConfiguration);
|
mapPersistedDivertConfigurations.put(persistedDivertConfiguration.getName(), persistedDivertConfiguration);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,11 +740,8 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public void deleteDivertConfiguration(String divertName) throws Exception {
|
public void deleteDivertConfiguration(String divertName) throws Exception {
|
||||||
PersistedDivertConfiguration oldDivert = mapPersistedDivertConfigurations.remove(divertName);
|
PersistedDivertConfiguration oldDivert = mapPersistedDivertConfigurations.remove(divertName);
|
||||||
if (oldDivert != null) {
|
if (oldDivert != null) {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecord(oldDivert.getStoreId(), false);
|
bindingsJournal.appendDeleteRecord(oldDivert.getStoreId(), false);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -831,14 +754,11 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
@Override
|
@Override
|
||||||
public void storeUser(PersistedUser persistedUser) throws Exception {
|
public void storeUser(PersistedUser persistedUser) throws Exception {
|
||||||
deleteUser(persistedUser.getUsername());
|
deleteUser(persistedUser.getUsername());
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
final long id = idGenerator.generateID();
|
final long id = idGenerator.generateID();
|
||||||
persistedUser.setStoreId(id);
|
persistedUser.setStoreId(id);
|
||||||
bindingsJournal.appendAddRecord(id, JournalRecordIds.USER_RECORD, persistedUser, true);
|
bindingsJournal.appendAddRecord(id, JournalRecordIds.USER_RECORD, persistedUser, true);
|
||||||
mapPersistedUsers.put(persistedUser.getUsername(), persistedUser);
|
mapPersistedUsers.put(persistedUser.getUsername(), persistedUser);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,11 +766,8 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public void deleteUser(String username) throws Exception {
|
public void deleteUser(String username) throws Exception {
|
||||||
PersistedUser oldUser = mapPersistedUsers.remove(username);
|
PersistedUser oldUser = mapPersistedUsers.remove(username);
|
||||||
if (oldUser != null) {
|
if (oldUser != null) {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecord(oldUser.getStoreId(), false);
|
bindingsJournal.appendDeleteRecord(oldUser.getStoreId(), false);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -863,14 +780,11 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
@Override
|
@Override
|
||||||
public void storeRole(PersistedRole persistedRole) throws Exception {
|
public void storeRole(PersistedRole persistedRole) throws Exception {
|
||||||
deleteRole(persistedRole.getUsername());
|
deleteRole(persistedRole.getUsername());
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
final long id = idGenerator.generateID();
|
final long id = idGenerator.generateID();
|
||||||
persistedRole.setStoreId(id);
|
persistedRole.setStoreId(id);
|
||||||
bindingsJournal.appendAddRecord(id, JournalRecordIds.ROLE_RECORD, persistedRole, true);
|
bindingsJournal.appendAddRecord(id, JournalRecordIds.ROLE_RECORD, persistedRole, true);
|
||||||
mapPersistedRoles.put(persistedRole.getUsername(), persistedRole);
|
mapPersistedRoles.put(persistedRole.getUsername(), persistedRole);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,11 +792,8 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public void deleteRole(String username) throws Exception {
|
public void deleteRole(String username) throws Exception {
|
||||||
PersistedRole oldRole = mapPersistedRoles.remove(username);
|
PersistedRole oldRole = mapPersistedRoles.remove(username);
|
||||||
if (oldRole != null) {
|
if (oldRole != null) {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecord(oldRole.getStoreId(), false);
|
bindingsJournal.appendDeleteRecord(oldRole.getStoreId(), false);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -894,21 +805,15 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeID(final long journalID, final long id) throws Exception {
|
public void storeID(final long journalID, final long id) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendAddRecord(journalID, JournalRecordIds.ID_COUNTER_RECORD, BatchingIDGenerator.createIDEncodingSupport(id), true, getContext(true));
|
bindingsJournal.appendAddRecord(journalID, JournalRecordIds.ID_COUNTER_RECORD, BatchingIDGenerator.createIDEncodingSupport(id), true, getContext(true));
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteID(long journalD) throws Exception {
|
public void deleteID(long journalD) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecord(journalD, false);
|
bindingsJournal.appendDeleteRecord(journalD, false);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,11 +821,8 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public void deleteAddressSetting(SimpleString addressMatch) throws Exception {
|
public void deleteAddressSetting(SimpleString addressMatch) throws Exception {
|
||||||
PersistedAddressSetting oldSetting = mapPersistedAddressSettings.remove(addressMatch);
|
PersistedAddressSetting oldSetting = mapPersistedAddressSettings.remove(addressMatch);
|
||||||
if (oldSetting != null) {
|
if (oldSetting != null) {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecord(oldSetting.getStoreId(), false);
|
bindingsJournal.appendDeleteRecord(oldSetting.getStoreId(), false);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -929,11 +831,8 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public void deleteSecuritySetting(SimpleString addressMatch) throws Exception {
|
public void deleteSecuritySetting(SimpleString addressMatch) throws Exception {
|
||||||
PersistedSecuritySetting oldRoles = mapPersistedSecuritySettings.remove(addressMatch);
|
PersistedSecuritySetting oldRoles = mapPersistedSecuritySettings.remove(addressMatch);
|
||||||
if (oldRoles != null) {
|
if (oldRoles != null) {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecord(oldRoles.getStoreId(), false);
|
bindingsJournal.appendDeleteRecord(oldRoles.getStoreId(), false);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -954,9 +853,7 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
Set<PageTransactionInfo> invalidPageTransactions = new HashSet<>();
|
Set<PageTransactionInfo> invalidPageTransactions = new HashSet<>();
|
||||||
|
|
||||||
Map<Long, Message> messages = new HashMap<>();
|
Map<Long, Message> messages = new HashMap<>();
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
|
|
||||||
messageJournal.setRemoveExtraFilesOnLoad(true);
|
messageJournal.setRemoveExtraFilesOnLoad(true);
|
||||||
JournalLoadInformation info = messageJournal.load(records, preparedTransactions, new LargeMessageTXFailureCallback(this));
|
JournalLoadInformation info = messageJournal.load(records, preparedTransactions, new LargeMessageTXFailureCallback(this));
|
||||||
|
|
||||||
|
@ -976,13 +873,7 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
final MutableLong recordNumber = new MutableLong();
|
final MutableLong recordNumber = new MutableLong();
|
||||||
final CoreMessageObjectPools pools;
|
final CoreMessageObjectPools pools;
|
||||||
if (totalSize > 0) {
|
if (totalSize > 0) {
|
||||||
final int addresses = (int)Math.max(
|
final int addresses = (int) Math.max(DEFAULT_POOL_CAPACITY, queueInfos == null ? 0 : queueInfos.values().stream().map(QueueBindingInfo::getAddress).filter(addr -> addr.length() <= DEFAULT_MAX_LENGTH).count() * 2);
|
||||||
DEFAULT_POOL_CAPACITY,
|
|
||||||
queueInfos == null ? 0 :
|
|
||||||
queueInfos.values().stream()
|
|
||||||
.map(QueueBindingInfo::getAddress)
|
|
||||||
.filter(addr -> addr.length() <= DEFAULT_MAX_LENGTH)
|
|
||||||
.count() * 2);
|
|
||||||
pools = new CoreMessageObjectPools(addresses, DEFAULT_POOL_CAPACITY, 128, 128);
|
pools = new CoreMessageObjectPools(addresses, DEFAULT_POOL_CAPACITY, 128, 128);
|
||||||
} else {
|
} else {
|
||||||
pools = null;
|
pools = null;
|
||||||
|
@ -1328,8 +1219,6 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
|
|
||||||
journalLoaded = true;
|
journalLoaded = true;
|
||||||
return info;
|
return info;
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1380,21 +1269,15 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
@Override
|
@Override
|
||||||
public void addGrouping(final GroupBinding groupBinding) throws Exception {
|
public void addGrouping(final GroupBinding groupBinding) throws Exception {
|
||||||
GroupingEncoding groupingEncoding = new GroupingEncoding(groupBinding.getId(), groupBinding.getGroupId(), groupBinding.getClusterName());
|
GroupingEncoding groupingEncoding = new GroupingEncoding(groupBinding.getId(), groupBinding.getGroupId(), groupBinding.getClusterName());
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendAddRecord(groupBinding.getId(), JournalRecordIds.GROUP_RECORD, groupingEncoding, true);
|
bindingsJournal.appendAddRecord(groupBinding.getId(), JournalRecordIds.GROUP_RECORD, groupingEncoding, true);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteGrouping(long tx, final GroupBinding groupBinding) throws Exception {
|
public void deleteGrouping(long tx, final GroupBinding groupBinding) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecordTransactional(tx, groupBinding.getId());
|
bindingsJournal.appendDeleteRecordTransactional(tx, groupBinding.getId());
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1419,25 +1302,19 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
|
|
||||||
PersistentQueueBindingEncoding bindingEncoding = new PersistentQueueBindingEncoding(queue.getName(), binding.getAddress(), filterString, queue.getUser(), queue.isAutoCreated(), queue.getMaxConsumers(), queue.isPurgeOnNoConsumers(), queue.isEnabled(), queue.isExclusive(), queue.isGroupRebalance(), queue.isGroupRebalancePauseDispatch(), queue.getGroupBuckets(), queue.getGroupFirstKey(), queue.isLastValue(), queue.getLastValueKey(), queue.isNonDestructive(), queue.getConsumersBeforeDispatch(), queue.getDelayBeforeDispatch(), queue.isAutoDelete(), queue.getAutoDeleteDelay(), queue.getAutoDeleteMessageCount(), queue.getRoutingType().getType(), queue.isConfigurationManaged(), queue.getRingSize());
|
PersistentQueueBindingEncoding bindingEncoding = new PersistentQueueBindingEncoding(queue.getName(), binding.getAddress(), filterString, queue.getUser(), queue.isAutoCreated(), queue.getMaxConsumers(), queue.isPurgeOnNoConsumers(), queue.isEnabled(), queue.isExclusive(), queue.isGroupRebalance(), queue.isGroupRebalancePauseDispatch(), queue.getGroupBuckets(), queue.getGroupFirstKey(), queue.isLastValue(), queue.getLastValueKey(), queue.isNonDestructive(), queue.getConsumersBeforeDispatch(), queue.getDelayBeforeDispatch(), queue.isAutoDelete(), queue.getAutoDeleteDelay(), queue.getAutoDeleteMessageCount(), queue.getRoutingType().getType(), queue.isConfigurationManaged(), queue.getRingSize());
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
if (update) {
|
if (update) {
|
||||||
bindingsJournal.appendUpdateRecordTransactional(tx, binding.getID(), JournalRecordIds.QUEUE_BINDING_RECORD, bindingEncoding);
|
bindingsJournal.appendUpdateRecordTransactional(tx, binding.getID(), JournalRecordIds.QUEUE_BINDING_RECORD, bindingEncoding);
|
||||||
} else {
|
} else {
|
||||||
bindingsJournal.appendAddRecordTransactional(tx, binding.getID(), JournalRecordIds.QUEUE_BINDING_RECORD, bindingEncoding);
|
bindingsJournal.appendAddRecordTransactional(tx, binding.getID(), JournalRecordIds.QUEUE_BINDING_RECORD, bindingEncoding);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteQueueBinding(long tx, final long queueBindingID) throws Exception {
|
public void deleteQueueBinding(long tx, final long queueBindingID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecordTransactional(tx, queueBindingID);
|
bindingsJournal.appendDeleteRecordTransactional(tx, queueBindingID);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1445,24 +1322,17 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public long storeQueueStatus(long queueID, AddressQueueStatus status) throws Exception {
|
public long storeQueueStatus(long queueID, AddressQueueStatus status) throws Exception {
|
||||||
long recordID = idGenerator.generateID();
|
long recordID = idGenerator.generateID();
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendAddRecord(recordID, JournalRecordIds.QUEUE_STATUS_RECORD, new QueueStatusEncoding(queueID, status), true);
|
bindingsJournal.appendAddRecord(recordID, JournalRecordIds.QUEUE_STATUS_RECORD, new QueueStatusEncoding(queueID, status), true);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return recordID;
|
return recordID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteQueueStatus(long recordID) throws Exception {
|
public void deleteQueueStatus(long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecord(recordID, true);
|
bindingsJournal.appendDeleteRecord(recordID, true);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1470,132 +1340,96 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
public long storeAddressStatus(long addressID, AddressQueueStatus status) throws Exception {
|
public long storeAddressStatus(long addressID, AddressQueueStatus status) throws Exception {
|
||||||
long recordID = idGenerator.generateID();
|
long recordID = idGenerator.generateID();
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendAddRecord(recordID, JournalRecordIds.ADDRESS_STATUS_RECORD, new AddressStatusEncoding(addressID, status), true);
|
bindingsJournal.appendAddRecord(recordID, JournalRecordIds.ADDRESS_STATUS_RECORD, new AddressStatusEncoding(addressID, status), true);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return recordID;
|
return recordID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteAddressStatus(long recordID) throws Exception {
|
public void deleteAddressStatus(long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecord(recordID, true);
|
bindingsJournal.appendDeleteRecord(recordID, true);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addAddressBinding(final long tx, final AddressInfo addressInfo) throws Exception {
|
public void addAddressBinding(final long tx, final AddressInfo addressInfo) throws Exception {
|
||||||
PersistentAddressBindingEncoding bindingEncoding = new PersistentAddressBindingEncoding(addressInfo.getName(),
|
PersistentAddressBindingEncoding bindingEncoding = new PersistentAddressBindingEncoding(addressInfo.getName(), addressInfo.getRoutingTypes(), addressInfo.isAutoCreated());
|
||||||
addressInfo.getRoutingTypes(),
|
|
||||||
addressInfo.isAutoCreated());
|
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
long recordID = idGenerator.generateID();
|
long recordID = idGenerator.generateID();
|
||||||
bindingEncoding.setId(recordID);
|
bindingEncoding.setId(recordID);
|
||||||
addressInfo.setId(recordID);
|
addressInfo.setId(recordID);
|
||||||
bindingsJournal.appendAddRecordTransactional(tx, recordID, JournalRecordIds.ADDRESS_BINDING_RECORD, bindingEncoding);
|
bindingsJournal.appendAddRecordTransactional(tx, recordID, JournalRecordIds.ADDRESS_BINDING_RECORD, bindingEncoding);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteAddressBinding(long tx, final long addressBindingID) throws Exception {
|
public void deleteAddressBinding(long tx, final long addressBindingID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
bindingsJournal.appendDeleteRecordTransactional(tx, addressBindingID);
|
bindingsJournal.appendDeleteRecordTransactional(tx, addressBindingID);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long storePageCounterInc(long txID, long queueID, int value, long persistentSize) throws Exception {
|
public long storePageCounterInc(long txID, long queueID, int value, long persistentSize) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
long recordID = idGenerator.generateID();
|
long recordID = idGenerator.generateID();
|
||||||
messageJournal.appendAddRecordTransactional(txID, recordID, JournalRecordIds.PAGE_CURSOR_COUNTER_INC, new PageCountRecordInc(queueID, value, persistentSize));
|
messageJournal.appendAddRecordTransactional(txID, recordID, JournalRecordIds.PAGE_CURSOR_COUNTER_INC, new PageCountRecordInc(queueID, value, persistentSize));
|
||||||
return recordID;
|
return recordID;
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long storePageCounterInc(long queueID, int value, long persistentSize) throws Exception {
|
public long storePageCounterInc(long queueID, int value, long persistentSize) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
final long recordID = idGenerator.generateID();
|
final long recordID = idGenerator.generateID();
|
||||||
messageJournal.appendAddRecord(recordID, JournalRecordIds.PAGE_CURSOR_COUNTER_INC, new PageCountRecordInc(queueID, value, persistentSize), true, getContext());
|
messageJournal.appendAddRecord(recordID, JournalRecordIds.PAGE_CURSOR_COUNTER_INC, new PageCountRecordInc(queueID, value, persistentSize), true, getContext());
|
||||||
return recordID;
|
return recordID;
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long storePageCounter(long txID, long queueID, long value, long persistentSize) throws Exception {
|
public long storePageCounter(long txID, long queueID, long value, long persistentSize) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
final long recordID = idGenerator.generateID();
|
final long recordID = idGenerator.generateID();
|
||||||
messageJournal.appendAddRecordTransactional(txID, recordID, JournalRecordIds.PAGE_CURSOR_COUNTER_VALUE, new PageCountRecord(queueID, value, persistentSize));
|
messageJournal.appendAddRecordTransactional(txID, recordID, JournalRecordIds.PAGE_CURSOR_COUNTER_VALUE, new PageCountRecord(queueID, value, persistentSize));
|
||||||
return recordID;
|
return recordID;
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long storePendingCounter(final long queueID, final long pageID) throws Exception {
|
public long storePendingCounter(final long queueID, final long pageID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
final long recordID = idGenerator.generateID();
|
final long recordID = idGenerator.generateID();
|
||||||
PageCountPendingImpl pendingInc = new PageCountPendingImpl(queueID, pageID);
|
PageCountPendingImpl pendingInc = new PageCountPendingImpl(queueID, pageID);
|
||||||
// We must guarantee the record sync before we actually write on the page otherwise we may get out of sync
|
// We must guarantee the record sync before we actually write on the page otherwise we may get out of sync
|
||||||
// on the counter
|
// on the counter
|
||||||
messageJournal.appendAddRecord(recordID, JournalRecordIds.PAGE_CURSOR_PENDING_COUNTER, pendingInc, true);
|
messageJournal.appendAddRecord(recordID, JournalRecordIds.PAGE_CURSOR_PENDING_COUNTER, pendingInc, true);
|
||||||
return recordID;
|
return recordID;
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteIncrementRecord(long txID, long recordID) throws Exception {
|
public void deleteIncrementRecord(long txID, long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendDeleteRecordTransactional(txID, recordID);
|
messageJournal.appendDeleteRecordTransactional(txID, recordID);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deletePageCounter(long txID, long recordID) throws Exception {
|
public void deletePageCounter(long txID, long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendDeleteRecordTransactional(txID, recordID);
|
messageJournal.appendDeleteRecordTransactional(txID, recordID);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deletePendingPageCounter(long txID, long recordID) throws Exception {
|
public void deletePendingPageCounter(long txID, long recordID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.appendDeleteRecordTransactional(txID, recordID);
|
messageJournal.appendDeleteRecordTransactional(txID, recordID);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1694,11 +1528,8 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void lineUpContext() {
|
public void lineUpContext() {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
messageJournal.lineUpContext(getContext());
|
messageJournal.lineUpContext(getContext());
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1787,15 +1618,12 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
* TODO: Is this still being used ?
|
* TODO: Is this still being used ?
|
||||||
*/
|
*/
|
||||||
public JournalLoadInformation[] loadInternalOnly() throws Exception {
|
public JournalLoadInformation[] loadInternalOnly() throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
JournalLoadInformation[] info = new JournalLoadInformation[2];
|
JournalLoadInformation[] info = new JournalLoadInformation[2];
|
||||||
info[0] = bindingsJournal.loadInternalOnly();
|
info[0] = bindingsJournal.loadInternalOnly();
|
||||||
info[1] = messageJournal.loadInternalOnly();
|
info[1] = messageJournal.loadInternalOnly();
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2171,6 +1999,7 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
persistedRole.setStoreId(id);
|
persistedRole.setStoreId(id);
|
||||||
return persistedRole;
|
return persistedRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id
|
* @param id
|
||||||
* @param buffer
|
* @param buffer
|
||||||
|
@ -2221,10 +2050,7 @@ public abstract class AbstractJournalStorageManager extends CriticalComponentImp
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addToPage(PagingStore store,
|
public boolean addToPage(PagingStore store, Message msg, Transaction tx, RouteContextList listCtx) throws Exception {
|
||||||
Message msg,
|
|
||||||
Transaction tx,
|
|
||||||
RouteContextList listCtx) throws Exception {
|
|
||||||
/**
|
/**
|
||||||
* Exposing the read-lock here is an encapsulation violation done in order to keep the code
|
* Exposing the read-lock here is an encapsulation violation done in order to keep the code
|
||||||
* simpler. The alternative would be to add a second method, say 'verifyPaging', to
|
* simpler. The alternative would be to add a second method, say 'verifyPaging', to
|
||||||
|
|
|
@ -64,6 +64,7 @@ import org.apache.activemq.artemis.core.server.JournalType;
|
||||||
import org.apache.activemq.artemis.core.server.LargeServerMessage;
|
import org.apache.activemq.artemis.core.server.LargeServerMessage;
|
||||||
import org.apache.activemq.artemis.core.server.files.FileStoreMonitor;
|
import org.apache.activemq.artemis.core.server.files.FileStoreMonitor;
|
||||||
import org.apache.activemq.artemis.journal.ActiveMQJournalBundle;
|
import org.apache.activemq.artemis.journal.ActiveMQJournalBundle;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.apache.activemq.artemis.utils.ExecutorFactory;
|
import org.apache.activemq.artemis.utils.ExecutorFactory;
|
||||||
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzer;
|
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzer;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
@ -253,14 +254,11 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop(boolean ioCriticalError, boolean sendFailover) throws Exception {
|
public void stop(boolean ioCriticalError, boolean sendFailover) throws Exception {
|
||||||
try {
|
try (ArtemisCloseable critical = measureCritical(CRITICAL_STOP)) {
|
||||||
enterCritical(CRITICAL_STOP);
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (internalStop(ioCriticalError, sendFailover))
|
if (internalStop(ioCriticalError, sendFailover))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_STOP);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,39 +288,39 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
// that's ok
|
// that's ok
|
||||||
}
|
}
|
||||||
|
|
||||||
enterCritical(CRITICAL_STOP_2);
|
try (ArtemisCloseable critical = measureCritical(CRITICAL_STOP_2)) {
|
||||||
storageManagerLock.writeLock().lock();
|
storageManagerLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// We cache the variable as the replicator could be changed between here and the time we call stop
|
// We cache the variable as the replicator could be changed between here and the time we call stop
|
||||||
// since sendLiveIsStopping may issue a close back from the channel
|
// since sendLiveIsStopping may issue a close back from the channel
|
||||||
// and we want to ensure a stop here just in case
|
// and we want to ensure a stop here just in case
|
||||||
ReplicationManager replicatorInUse = replicator;
|
ReplicationManager replicatorInUse = replicator;
|
||||||
if (replicatorInUse != null) {
|
if (replicatorInUse != null) {
|
||||||
if (sendFailover) {
|
if (sendFailover) {
|
||||||
final OperationContext token = replicator.sendLiveIsStopping(ReplicationLiveIsStoppingMessage.LiveStopping.FAIL_OVER);
|
final OperationContext token = replicator.sendLiveIsStopping(ReplicationLiveIsStoppingMessage.LiveStopping.FAIL_OVER);
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
try {
|
try {
|
||||||
token.waitCompletion(5000);
|
token.waitCompletion(5000);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// ignore it
|
// ignore it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// we cannot clear replication tokens, otherwise clients will eventually be informed of completion during a server's shutdown
|
||||||
|
// while the backup will never receive then
|
||||||
|
replicatorInUse.stop(false);
|
||||||
}
|
}
|
||||||
// we cannot clear replication tokens, otherwise clients will eventually be informed of completion during a server's shutdown
|
bindingsJournal.stop();
|
||||||
// while the backup will never receive then
|
|
||||||
replicatorInUse.stop(false);
|
messageJournal.stop();
|
||||||
|
|
||||||
|
journalLoaded = false;
|
||||||
|
|
||||||
|
started = false;
|
||||||
|
} finally {
|
||||||
|
storageManagerLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
bindingsJournal.stop();
|
|
||||||
|
|
||||||
messageJournal.stop();
|
|
||||||
|
|
||||||
journalLoaded = false;
|
|
||||||
|
|
||||||
started = false;
|
|
||||||
} finally {
|
|
||||||
storageManagerLock.writeLock().unlock();
|
|
||||||
leaveCritical(CRITICAL_STOP_2);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -388,12 +386,9 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
@Override
|
@Override
|
||||||
public void pageClosed(final SimpleString storeName, final int pageNumber) {
|
public void pageClosed(final SimpleString storeName, final int pageNumber) {
|
||||||
if (isReplicated()) {
|
if (isReplicated()) {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
if (isReplicated())
|
if (isReplicated())
|
||||||
replicator.pageClosed(storeName, pageNumber);
|
replicator.pageClosed(storeName, pageNumber);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,12 +396,9 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
@Override
|
@Override
|
||||||
public void pageDeleted(final SimpleString storeName, final int pageNumber) {
|
public void pageDeleted(final SimpleString storeName, final int pageNumber) {
|
||||||
if (isReplicated()) {
|
if (isReplicated()) {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
if (isReplicated())
|
if (isReplicated())
|
||||||
replicator.pageDeleted(storeName, pageNumber);
|
replicator.pageDeleted(storeName, pageNumber);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,12 +412,9 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
// Say you are sending durable and non-durable messages to a page
|
// Say you are sending durable and non-durable messages to a page
|
||||||
// The ACKs would be done to wrong positions, and the backup would be a mess
|
// The ACKs would be done to wrong positions, and the backup would be a mess
|
||||||
|
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
if (isReplicated())
|
if (isReplicated())
|
||||||
replicator.pageWrite(message, pageNumber);
|
replicator.pageWrite(message, pageNumber);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,26 +430,20 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public long storePendingLargeMessage(final long messageID) throws Exception {
|
public long storePendingLargeMessage(final long messageID) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
long recordID = generateID();
|
long recordID = generateID();
|
||||||
messageJournal.appendAddRecord(recordID, JournalRecordIds.ADD_LARGE_MESSAGE_PENDING, new PendingLargeMessageEncoding(messageID), true, getContext(true));
|
messageJournal.appendAddRecord(recordID, JournalRecordIds.ADD_LARGE_MESSAGE_PENDING, new PendingLargeMessageEncoding(messageID), true, getContext(true));
|
||||||
|
|
||||||
return recordID;
|
return recordID;
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void largeMessageClosed(LargeServerMessage largeServerMessage) throws ActiveMQException {
|
public void largeMessageClosed(LargeServerMessage largeServerMessage) throws ActiveMQException {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
if (isReplicated()) {
|
if (isReplicated()) {
|
||||||
replicator.largeMessageClosed(largeServerMessage.toMessage().getMessageID(), JournalStorageManager.this);
|
replicator.largeMessageClosed(largeServerMessage.toMessage().getMessageID(), JournalStorageManager.this);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,22 +468,18 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (largeServerMessage.toMessage().isDurable() && isReplicated()) {
|
if (largeServerMessage.toMessage().isDurable() && isReplicated()) {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
if (isReplicated() && replicator.isSynchronizing()) {
|
if (isReplicated() && replicator.isSynchronizing()) {
|
||||||
largeMessagesToDelete.put(largeServerMessage.toMessage().getMessageID(), largeServerMessage);
|
largeMessagesToDelete.put(largeServerMessage.toMessage().getMessageID(), largeServerMessage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Runnable deleteAction = new Runnable() {
|
Runnable deleteAction = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
if (replicator != null) {
|
if (replicator != null) {
|
||||||
replicator.largeMessageDelete(largeServerMessage.toMessage().getMessageID(), JournalStorageManager.this);
|
replicator.largeMessageDelete(largeServerMessage.toMessage().getMessageID(), JournalStorageManager.this);
|
||||||
}
|
}
|
||||||
|
@ -508,8 +487,6 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
|
|
||||||
// The confirm could only be done after the actual delete is done
|
// The confirm could only be done after the actual delete is done
|
||||||
confirmLargeMessage(largeServerMessage);
|
confirmLargeMessage(largeServerMessage);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ActiveMQServerLogger.LOGGER.journalErrorDeletingMessage(e, largeServerMessage.toMessage().getMessageID());
|
ActiveMQServerLogger.LOGGER.journalErrorDeletingMessage(e, largeServerMessage.toMessage().getMessageID());
|
||||||
|
@ -542,8 +519,7 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LargeServerMessage createLargeMessage(final long id, final Message message) throws Exception {
|
public LargeServerMessage createLargeMessage(final long id, final Message message) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
if (isReplicated()) {
|
if (isReplicated()) {
|
||||||
replicator.largeMessageBegin(id);
|
replicator.largeMessageBegin(id);
|
||||||
}
|
}
|
||||||
|
@ -553,8 +529,6 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
largeMessage.moveHeadersAndProperties(message);
|
largeMessage.moveHeadersAndProperties(message);
|
||||||
|
|
||||||
return largeMessageCreated(id, largeMessage);
|
return largeMessageCreated(id, largeMessage);
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,8 +839,7 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
public final void addBytesToLargeMessage(final SequentialFile file,
|
public final void addBytesToLargeMessage(final SequentialFile file,
|
||||||
final long messageId,
|
final long messageId,
|
||||||
final ActiveMQBuffer bytes) throws Exception {
|
final ActiveMQBuffer bytes) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
file.position(file.size());
|
file.position(file.size());
|
||||||
if (bytes.byteBuf() != null && bytes.byteBuf().nioBufferCount() == 1) {
|
if (bytes.byteBuf() != null && bytes.byteBuf().nioBufferCount() == 1) {
|
||||||
final ByteBuffer nioBytes = bytes.byteBuf().internalNioBuffer(bytes.readerIndex(), bytes.readableBytes());
|
final ByteBuffer nioBytes = bytes.byteBuf().internalNioBuffer(bytes.readerIndex(), bytes.readableBytes());
|
||||||
|
@ -883,8 +856,6 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
bytes.readBytes(bytesCopy);
|
bytes.readBytes(bytesCopy);
|
||||||
addBytesToLargeMessage(file, messageId, bytesCopy);
|
addBytesToLargeMessage(file, messageId, bytesCopy);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,8 +863,7 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
public final void addBytesToLargeMessage(final SequentialFile file,
|
public final void addBytesToLargeMessage(final SequentialFile file,
|
||||||
final long messageId,
|
final long messageId,
|
||||||
final byte[] bytes) throws Exception {
|
final byte[] bytes) throws Exception {
|
||||||
readLock();
|
try (ArtemisCloseable lock = closeableReadLock()) {
|
||||||
try {
|
|
||||||
file.position(file.size());
|
file.position(file.size());
|
||||||
//that's an additional precaution to avoid ByteBuffer to be pooled:
|
//that's an additional precaution to avoid ByteBuffer to be pooled:
|
||||||
//NIOSequentialFileFactory doesn't pool heap ByteBuffer, but better to make evident
|
//NIOSequentialFileFactory doesn't pool heap ByteBuffer, but better to make evident
|
||||||
|
@ -903,8 +873,6 @@ public class JournalStorageManager extends AbstractJournalStorageManager {
|
||||||
if (isReplicated()) {
|
if (isReplicated()) {
|
||||||
replicator.largeMessageWrite(messageId, bytes);
|
replicator.largeMessageWrite(messageId, bytes);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
||||||
import org.apache.activemq.artemis.core.server.impl.JournalLoader;
|
import org.apache.activemq.artemis.core.server.impl.JournalLoader;
|
||||||
import org.apache.activemq.artemis.core.transaction.ResourceManager;
|
import org.apache.activemq.artemis.core.transaction.ResourceManager;
|
||||||
import org.apache.activemq.artemis.core.transaction.Transaction;
|
import org.apache.activemq.artemis.core.transaction.Transaction;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
|
|
||||||
public class NullStorageManager implements StorageManager {
|
public class NullStorageManager implements StorageManager {
|
||||||
|
|
||||||
|
@ -78,6 +79,13 @@ public class NullStorageManager implements StorageManager {
|
||||||
this.ioCriticalErrorListener = ioCriticalErrorListener;
|
this.ioCriticalErrorListener = ioCriticalErrorListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final ArtemisCloseable dummy = () -> { };
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArtemisCloseable closeableReadLock() {
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
|
||||||
public NullStorageManager() {
|
public NullStorageManager() {
|
||||||
this(new IOCriticalErrorListener() {
|
this(new IOCriticalErrorListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -682,16 +690,6 @@ public class NullStorageManager implements StorageManager {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readLock() {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readUnLock() {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void persistIdGenerator() {
|
public void persistIdGenerator() {
|
||||||
// no-op
|
// no-op
|
||||||
|
|
|
@ -100,6 +100,7 @@ import org.apache.activemq.artemis.core.transaction.TransactionPropertyIndexes;
|
||||||
import org.apache.activemq.artemis.core.transaction.impl.BindingsTransactionImpl;
|
import org.apache.activemq.artemis.core.transaction.impl.BindingsTransactionImpl;
|
||||||
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
|
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
|
||||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.apache.activemq.artemis.utils.BooleanUtil;
|
import org.apache.activemq.artemis.utils.BooleanUtil;
|
||||||
import org.apache.activemq.artemis.utils.Env;
|
import org.apache.activemq.artemis.utils.Env;
|
||||||
import org.apache.activemq.artemis.utils.ReferenceCounter;
|
import org.apache.activemq.artemis.utils.ReferenceCounter;
|
||||||
|
@ -1087,9 +1088,8 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
/* Called when a message is cancelled back into the queue */
|
/* Called when a message is cancelled back into the queue */
|
||||||
@Override
|
@Override
|
||||||
public void addHead(final MessageReference ref, boolean scheduling) {
|
public void addHead(final MessageReference ref, boolean scheduling) {
|
||||||
enterCritical(CRITICAL_PATH_ADD_HEAD);
|
try (ArtemisCloseable metric = measureCritical(CRITICAL_PATH_ADD_HEAD)) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
try {
|
|
||||||
if (ringSize != -1) {
|
if (ringSize != -1) {
|
||||||
enforceRing(ref, scheduling, true);
|
enforceRing(ref, scheduling, true);
|
||||||
}
|
}
|
||||||
|
@ -1103,8 +1103,6 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
|
|
||||||
directDeliver = false;
|
directDeliver = false;
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_ADD_HEAD);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1112,9 +1110,8 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
/* Called when a message is cancelled back into the queue */
|
/* Called when a message is cancelled back into the queue */
|
||||||
@Override
|
@Override
|
||||||
public void addSorted(final MessageReference ref, boolean scheduling) {
|
public void addSorted(final MessageReference ref, boolean scheduling) {
|
||||||
enterCritical(CRITICAL_PATH_ADD_HEAD);
|
try (ArtemisCloseable metric = measureCritical(CRITICAL_PATH_ADD_HEAD)) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
try {
|
|
||||||
if (ringSize != -1) {
|
if (ringSize != -1) {
|
||||||
enforceRing(ref, false, true);
|
enforceRing(ref, false, true);
|
||||||
}
|
}
|
||||||
|
@ -1127,8 +1124,6 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
|
|
||||||
directDeliver = false;
|
directDeliver = false;
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_ADD_HEAD);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1136,9 +1131,8 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
/* Called when a message is cancelled back into the queue */
|
/* Called when a message is cancelled back into the queue */
|
||||||
@Override
|
@Override
|
||||||
public void addHead(final List<MessageReference> refs, boolean scheduling) {
|
public void addHead(final List<MessageReference> refs, boolean scheduling) {
|
||||||
enterCritical(CRITICAL_PATH_ADD_HEAD);
|
try (ArtemisCloseable metric = measureCritical(CRITICAL_PATH_ADD_HEAD)) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
try {
|
|
||||||
for (MessageReference ref : refs) {
|
for (MessageReference ref : refs) {
|
||||||
addHead(ref, scheduling);
|
addHead(ref, scheduling);
|
||||||
}
|
}
|
||||||
|
@ -1146,8 +1140,6 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
resetAllIterators();
|
resetAllIterators();
|
||||||
|
|
||||||
deliverAsync();
|
deliverAsync();
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_ADD_HEAD);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1155,9 +1147,8 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
/* Called when a message is cancelled back into the queue */
|
/* Called when a message is cancelled back into the queue */
|
||||||
@Override
|
@Override
|
||||||
public void addSorted(final List<MessageReference> refs, boolean scheduling) {
|
public void addSorted(final List<MessageReference> refs, boolean scheduling) {
|
||||||
enterCritical(CRITICAL_PATH_ADD_HEAD);
|
try (ArtemisCloseable metric = measureCritical(CRITICAL_PATH_ADD_HEAD)) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
try {
|
|
||||||
for (MessageReference ref : refs) {
|
for (MessageReference ref : refs) {
|
||||||
addSorted(ref, scheduling);
|
addSorted(ref, scheduling);
|
||||||
}
|
}
|
||||||
|
@ -1165,8 +1156,6 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
resetAllIterators();
|
resetAllIterators();
|
||||||
|
|
||||||
deliverAsync();
|
deliverAsync();
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_ADD_HEAD);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1192,8 +1181,7 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTail(final MessageReference ref, final boolean direct) {
|
public void addTail(final MessageReference ref, final boolean direct) {
|
||||||
enterCritical(CRITICAL_PATH_ADD_TAIL);
|
try (ArtemisCloseable metric = measureCritical(CRITICAL_PATH_ADD_TAIL)) {
|
||||||
try {
|
|
||||||
if (scheduleIfPossible(ref)) {
|
if (scheduleIfPossible(ref)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1240,8 +1228,6 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
|
|
||||||
// Delivery async will both poll for intermediate reference and deliver to clients
|
// Delivery async will both poll for intermediate reference and deliver to clients
|
||||||
deliverAsync();
|
deliverAsync();
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_PATH_ADD_TAIL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1405,8 +1391,7 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
logger.debug(this + " adding consumer " + consumer);
|
logger.debug(this + " adding consumer " + consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
enterCritical(CRITICAL_CONSUMER);
|
try (ArtemisCloseable metric = measureCritical(CRITICAL_CONSUMER)) {
|
||||||
try {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (maxConsumers != MAX_CONSUMERS_UNLIMITED && consumers.size() >= maxConsumers) {
|
if (maxConsumers != MAX_CONSUMERS_UNLIMITED && consumers.size() >= maxConsumers) {
|
||||||
throw ActiveMQMessageBundle.BUNDLE.maxConsumerLimitReachedForQueue(address, name);
|
throw ActiveMQMessageBundle.BUNDLE.maxConsumerLimitReachedForQueue(address, name);
|
||||||
|
@ -1442,10 +1427,7 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_CONSUMER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1461,8 +1443,7 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
@Override
|
@Override
|
||||||
public void removeConsumer(final Consumer consumer) {
|
public void removeConsumer(final Consumer consumer) {
|
||||||
|
|
||||||
enterCritical(CRITICAL_CONSUMER);
|
try (ArtemisCloseable metric = measureCritical(CRITICAL_CONSUMER)) {
|
||||||
try {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
|
||||||
boolean consumerRemoved = false;
|
boolean consumerRemoved = false;
|
||||||
|
@ -1498,8 +1479,6 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_CONSUMER);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4131,25 +4110,19 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
|
||||||
// this will avoid that possibility
|
// this will avoid that possibility
|
||||||
// We will be using the deliverRunner instance as the guard object to avoid multiple threads executing
|
// We will be using the deliverRunner instance as the guard object to avoid multiple threads executing
|
||||||
// an asynchronous delivery
|
// an asynchronous delivery
|
||||||
enterCritical(CRITICAL_DELIVER);
|
|
||||||
boolean needCheckDepage = false;
|
boolean needCheckDepage = false;
|
||||||
try {
|
try (ArtemisCloseable metric = measureCritical(CRITICAL_DELIVER)) {
|
||||||
deliverLock.lock();
|
deliverLock.lock();
|
||||||
try {
|
try {
|
||||||
needCheckDepage = deliver();
|
needCheckDepage = deliver();
|
||||||
} finally {
|
} finally {
|
||||||
deliverLock.unlock();
|
deliverLock.unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_DELIVER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needCheckDepage) {
|
if (needCheckDepage) {
|
||||||
enterCritical(CRITICAL_CHECK_DEPAGE);
|
try (ArtemisCloseable metric = measureCritical(CRITICAL_CHECK_DEPAGE)) {
|
||||||
try {
|
|
||||||
checkDepage(true);
|
checkDepage(true);
|
||||||
} finally {
|
|
||||||
leaveCritical(CRITICAL_CHECK_DEPAGE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.apache.activemq.artemis.core.server.impl.AckReason;
|
||||||
import org.apache.activemq.artemis.core.server.impl.RefsOperation;
|
import org.apache.activemq.artemis.core.server.impl.RefsOperation;
|
||||||
import org.apache.activemq.artemis.core.transaction.Transaction;
|
import org.apache.activemq.artemis.core.transaction.Transaction;
|
||||||
import org.apache.activemq.artemis.core.transaction.TransactionOperation;
|
import org.apache.activemq.artemis.core.transaction.TransactionOperation;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
public class TransactionImpl implements Transaction {
|
public class TransactionImpl implements Transaction {
|
||||||
|
@ -190,8 +191,7 @@ public class TransactionImpl implements Transaction {
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("TransactionImpl::prepare::" + this);
|
logger.trace("TransactionImpl::prepare::" + this);
|
||||||
}
|
}
|
||||||
storageManager.readLock();
|
try (ArtemisCloseable lock = storageManager.closeableReadLock()) {
|
||||||
try {
|
|
||||||
synchronized (timeoutLock) {
|
synchronized (timeoutLock) {
|
||||||
if (isEffective()) {
|
if (isEffective()) {
|
||||||
logger.debug("TransactionImpl::prepare::" + this + " is being ignored");
|
logger.debug("TransactionImpl::prepare::" + this + " is being ignored");
|
||||||
|
@ -239,8 +239,6 @@ public class TransactionImpl implements Transaction {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
storageManager.readUnLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ import org.apache.activemq.artemis.core.transaction.ResourceManager;
|
||||||
import org.apache.activemq.artemis.core.transaction.Transaction;
|
import org.apache.activemq.artemis.core.transaction.Transaction;
|
||||||
import org.apache.activemq.artemis.core.transaction.TransactionOperation;
|
import org.apache.activemq.artemis.core.transaction.TransactionOperation;
|
||||||
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -216,6 +217,11 @@ public class TransactionImplTest extends ActiveMQTestBase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArtemisCloseable closeableReadLock() {
|
||||||
|
return () -> { };
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void criticalError(Throwable error) {
|
public void criticalError(Throwable error) {
|
||||||
error.printStackTrace();
|
error.printStackTrace();
|
||||||
|
@ -745,16 +751,6 @@ public class TransactionImplTest extends ActiveMQTestBase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readLock() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readUnLock() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void persistIdGenerator() {
|
public void persistIdGenerator() {
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,7 @@ import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager
|
||||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
|
||||||
import org.apache.activemq.artemis.spi.core.security.jaas.InVMLoginModule;
|
import org.apache.activemq.artemis.spi.core.security.jaas.InVMLoginModule;
|
||||||
import org.apache.activemq.artemis.tests.util.SpawnedTestBase;
|
import org.apache.activemq.artemis.tests.util.SpawnedTestBase;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.apache.activemq.artemis.utils.SpawnedVMSupport;
|
import org.apache.activemq.artemis.utils.SpawnedVMSupport;
|
||||||
import org.apache.activemq.artemis.tests.util.Wait;
|
import org.apache.activemq.artemis.tests.util.Wait;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
@ -838,13 +839,8 @@ public class SendAckFailTest extends SpawnedTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readLock() {
|
public ArtemisCloseable closeableReadLock() {
|
||||||
manager.readLock();
|
return manager.closeableReadLock();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readUnLock() {
|
|
||||||
manager.readUnLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager
|
||||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
|
||||||
import org.apache.activemq.artemis.spi.core.security.jaas.InVMLoginModule;
|
import org.apache.activemq.artemis.spi.core.security.jaas.InVMLoginModule;
|
||||||
import org.apache.activemq.artemis.tests.util.SpawnedTestBase;
|
import org.apache.activemq.artemis.tests.util.SpawnedTestBase;
|
||||||
|
import org.apache.activemq.artemis.utils.ArtemisCloseable;
|
||||||
import org.apache.activemq.artemis.utils.SpawnedVMSupport;
|
import org.apache.activemq.artemis.utils.SpawnedVMSupport;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -102,19 +103,26 @@ public class CriticalCrashTest extends SpawnedTestBase {
|
||||||
|
|
||||||
JournalStorageManager storageManager = new JournalStorageManager(conf, getCriticalAnalyzer(), executorFactory, scheduledPool, ioExecutorFactory, ioCriticalErrorListener) {
|
JournalStorageManager storageManager = new JournalStorageManager(conf, getCriticalAnalyzer(), executorFactory, scheduledPool, ioExecutorFactory, ioCriticalErrorListener) {
|
||||||
@Override
|
@Override
|
||||||
public void readLock() {
|
public ArtemisCloseable closeableReadLock() {
|
||||||
super.readLock();
|
ArtemisCloseable measure = measureCritical(CRITICAL_STORE);
|
||||||
|
storageManagerLock.readLock().lock();
|
||||||
|
|
||||||
if (blocked.get()) {
|
if (blocked.get()) {
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return () -> {
|
||||||
|
storageManagerLock.readLock().unlock();
|
||||||
|
measure.close();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeMessage(Message message) throws Exception {
|
public void storeMessage(Message message) throws Exception {
|
||||||
super.storeMessage(message);
|
super.storeMessage(message);
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.activemq.artemis.tests.integration.critical;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzer;
|
||||||
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
|
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
|
||||||
import org.apache.activemq.artemis.api.core.ActiveMQException;
|
import org.apache.activemq.artemis.api.core.ActiveMQException;
|
||||||
import org.apache.activemq.artemis.core.config.Configuration;
|
import org.apache.activemq.artemis.core.config.Configuration;
|
||||||
|
@ -28,6 +29,7 @@ import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerPlugin;
|
||||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||||
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
||||||
import org.apache.activemq.artemis.tests.util.Wait;
|
import org.apache.activemq.artemis.tests.util.Wait;
|
||||||
|
import org.apache.activemq.artemis.utils.critical.CriticalCloseable;
|
||||||
import org.apache.activemq.artemis.utils.critical.CriticalComponent;
|
import org.apache.activemq.artemis.utils.critical.CriticalComponent;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -53,6 +55,17 @@ public class CriticalSimpleTest extends ActiveMQTestBase {
|
||||||
});
|
});
|
||||||
|
|
||||||
server.getCriticalAnalyzer().add(new CriticalComponent() {
|
server.getCriticalAnalyzer().add(new CriticalComponent() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CriticalAnalyzer getCriticalAnalyzer() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CriticalCloseable measureCritical(int path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkExpiration(long timeout, boolean reset) {
|
public boolean checkExpiration(long timeout, boolean reset) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -82,6 +95,17 @@ public class CriticalSimpleTest extends ActiveMQTestBase {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
server.getCriticalAnalyzer().add(new CriticalComponent() {
|
server.getCriticalAnalyzer().add(new CriticalComponent() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CriticalAnalyzer getCriticalAnalyzer() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CriticalCloseable measureCritical(int path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkExpiration(long timeout, boolean reset) {
|
public boolean checkExpiration(long timeout, boolean reset) {
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue