diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/process/ProcessBuilder.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/process/ProcessBuilder.java
index 5e4acf4df9..9eb796098e 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/process/ProcessBuilder.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/process/ProcessBuilder.java
@@ -22,7 +22,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
public class ProcessBuilder {
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/core/server/NetworkHealthCheck.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/core/server/NetworkHealthCheck.java
index cabd0454ce..eef79a1ec7 100644
--- a/artemis-commons/src/main/java/org/apache/activemq/artemis/core/server/NetworkHealthCheck.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/core/server/NetworkHealthCheck.java
@@ -33,7 +33,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.logs.ActiveMQUtilLogger;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/DataConstants.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/DataConstants.java
index 38df9b61e2..5b2b365ecc 100644
--- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/DataConstants.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/DataConstants.java
@@ -32,7 +32,7 @@ public final class DataConstants {
public static final int SIZE_FLOAT = 4;
- static final int SIZE_CHAR = 2;
+ public static final int SIZE_CHAR = 2;
public static final byte TRUE = 1;
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/TypedProperties.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/TypedProperties.java
index fda135be61..29cf8348e9 100644
--- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/TypedProperties.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/TypedProperties.java
@@ -1,4 +1,4 @@
-/*
+/**
* 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.
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -14,924 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.apache.activemq.artemis.utils;
-import java.nio.ByteBuffer;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import io.netty.buffer.ByteBuf;
-import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException;
-import org.apache.activemq.artemis.api.core.SimpleString;
-import org.apache.activemq.artemis.logs.ActiveMQUtilBundle;
-
-import static org.apache.activemq.artemis.utils.DataConstants.BOOLEAN;
-import static org.apache.activemq.artemis.utils.DataConstants.BYTE;
-import static org.apache.activemq.artemis.utils.DataConstants.BYTES;
-import static org.apache.activemq.artemis.utils.DataConstants.CHAR;
-import static org.apache.activemq.artemis.utils.DataConstants.DOUBLE;
-import static org.apache.activemq.artemis.utils.DataConstants.FLOAT;
-import static org.apache.activemq.artemis.utils.DataConstants.INT;
-import static org.apache.activemq.artemis.utils.DataConstants.LONG;
-import static org.apache.activemq.artemis.utils.DataConstants.NULL;
-import static org.apache.activemq.artemis.utils.DataConstants.SHORT;
-import static org.apache.activemq.artemis.utils.DataConstants.STRING;
-
/**
- * Property Value Conversion.
- *
- * This implementation follows section 3.5.4 of the Java Message Service specification
- * (Version 1.1 April 12, 2002).
- *
+ * @deprecated Use {@link org.apache.activemq.artemis.utils.collections.TypedProperties instead}
*/
-public final class TypedProperties {
+@Deprecated
+public class TypedProperties extends org.apache.activemq.artemis.utils.collections.TypedProperties {
- private static final SimpleString AMQ_PROPNAME = new SimpleString("_AMQ_");
-
- private Map properties;
-
- private volatile int size;
-
- private boolean internalProperties;
-
- public TypedProperties() {
- }
-
- /**
- * Return the number of properites
- * */
- public int size() {
- return properties.size();
- }
-
- public int getMemoryOffset() {
- // The estimate is basically the encode size + 2 object references for each entry in the map
- // Note we don't include the attributes or anything else since they already included in the memory estimate
- // of the ServerMessage
-
- return properties == null ? 0 : size + 2 * DataConstants.SIZE_INT * properties.size();
- }
-
- public TypedProperties(final TypedProperties other) {
- properties = other.properties == null ? null : new HashMap<>(other.properties);
- size = other.size;
- }
-
- public boolean hasInternalProperties() {
- return internalProperties;
- }
-
- public void putBooleanProperty(final SimpleString key, final boolean value) {
- checkCreateProperties();
- doPutValue(key, new BooleanValue(value));
- }
-
- public void putByteProperty(final SimpleString key, final byte value) {
- checkCreateProperties();
- doPutValue(key, new ByteValue(value));
- }
-
- public void putBytesProperty(final SimpleString key, final byte[] value) {
- checkCreateProperties();
- doPutValue(key, value == null ? new NullValue() : new BytesValue(value));
- }
-
- public void putShortProperty(final SimpleString key, final short value) {
- checkCreateProperties();
- doPutValue(key, new ShortValue(value));
- }
-
- public void putIntProperty(final SimpleString key, final int value) {
- checkCreateProperties();
- doPutValue(key, new IntValue(value));
- }
-
- public void putLongProperty(final SimpleString key, final long value) {
- checkCreateProperties();
- doPutValue(key, new LongValue(value));
- }
-
- public void putFloatProperty(final SimpleString key, final float value) {
- checkCreateProperties();
- doPutValue(key, new FloatValue(value));
- }
-
- public void putDoubleProperty(final SimpleString key, final double value) {
- checkCreateProperties();
- doPutValue(key, new DoubleValue(value));
- }
-
- public void putSimpleStringProperty(final SimpleString key, final SimpleString value) {
- checkCreateProperties();
- doPutValue(key, value == null ? new NullValue() : new StringValue(value));
- }
-
- public void putNullValue(final SimpleString key) {
- checkCreateProperties();
- doPutValue(key, new NullValue());
- }
-
- public void putCharProperty(final SimpleString key, final char value) {
- checkCreateProperties();
- doPutValue(key, new CharValue(value));
- }
-
- public void putTypedProperties(final TypedProperties otherProps) {
- if (otherProps == null || otherProps.properties == null) {
- return;
- }
-
- checkCreateProperties();
- Set> otherEntries = otherProps.properties.entrySet();
- for (Entry otherEntry : otherEntries) {
- doPutValue(otherEntry.getKey(), otherEntry.getValue());
- }
- }
-
- public Object getProperty(final SimpleString key) {
- return doGetProperty(key);
- }
-
- public Boolean getBooleanProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
- if (value == null) {
- return Boolean.valueOf(null);
- } else if (value instanceof Boolean) {
- return (Boolean) value;
- } else if (value instanceof SimpleString) {
- return Boolean.valueOf(((SimpleString) value).toString());
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public Byte getByteProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
- if (value == null) {
- return Byte.valueOf(null);
- } else if (value instanceof Byte) {
- return (Byte) value;
- } else if (value instanceof SimpleString) {
- return Byte.parseByte(((SimpleString) value).toString());
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public Character getCharProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
- if (value == null) {
- throw new NullPointerException("Invalid conversion: " + key);
- }
-
- if (value instanceof Character) {
- return ((Character) value);
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public byte[] getBytesProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
- if (value == null) {
- return null;
- } else if (value instanceof byte[]) {
- return (byte[]) value;
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public Double getDoubleProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
- if (value == null) {
- return Double.valueOf(null);
- } else if (value instanceof Float) {
- return ((Float) value).doubleValue();
- } else if (value instanceof Double) {
- return (Double) value;
- } else if (value instanceof SimpleString) {
- return Double.parseDouble(((SimpleString) value).toString());
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public Integer getIntProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
- if (value == null) {
- return Integer.valueOf(null);
- } else if (value instanceof Integer) {
- return (Integer) value;
- } else if (value instanceof Byte) {
- return ((Byte) value).intValue();
- } else if (value instanceof Short) {
- return ((Short) value).intValue();
- } else if (value instanceof SimpleString) {
- return Integer.parseInt(((SimpleString) value).toString());
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public Long getLongProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
- if (value == null) {
- return Long.valueOf(null);
- } else if (value instanceof Long) {
- return (Long) value;
- } else if (value instanceof Byte) {
- return ((Byte) value).longValue();
- } else if (value instanceof Short) {
- return ((Short) value).longValue();
- } else if (value instanceof Integer) {
- return ((Integer) value).longValue();
- } else if (value instanceof SimpleString) {
- return Long.parseLong(((SimpleString) value).toString());
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public Short getShortProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
- if (value == null) {
- return Short.valueOf(null);
- } else if (value instanceof Byte) {
- return ((Byte) value).shortValue();
- } else if (value instanceof Short) {
- return (Short) value;
- } else if (value instanceof SimpleString) {
- return Short.parseShort(((SimpleString) value).toString());
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public Float getFloatProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
- if (value == null)
- return Float.valueOf(null);
- if (value instanceof Float) {
- return ((Float) value);
- }
- if (value instanceof SimpleString) {
- return Float.parseFloat(((SimpleString) value).toString());
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public SimpleString getSimpleStringProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
- Object value = doGetProperty(key);
-
- if (value == null) {
- return null;
- }
-
- if (value instanceof SimpleString) {
- return (SimpleString) value;
- } else if (value instanceof Boolean) {
- return new SimpleString(value.toString());
- } else if (value instanceof Character) {
- return new SimpleString(value.toString());
- } else if (value instanceof Byte) {
- return new SimpleString(value.toString());
- } else if (value instanceof Short) {
- return new SimpleString(value.toString());
- } else if (value instanceof Integer) {
- return new SimpleString(value.toString());
- } else if (value instanceof Long) {
- return new SimpleString(value.toString());
- } else if (value instanceof Float) {
- return new SimpleString(value.toString());
- } else if (value instanceof Double) {
- return new SimpleString(value.toString());
- }
- throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
- }
-
- public Object removeProperty(final SimpleString key) {
- return doRemoveProperty(key);
- }
-
- public boolean containsProperty(final SimpleString key) {
- if (size == 0) {
- return false;
-
- } else {
- return properties.containsKey(key);
- }
- }
-
- public Set getPropertyNames() {
- if (size == 0) {
- return Collections.emptySet();
- } else {
- return properties.keySet();
- }
- }
-
- public synchronized void decode(final ByteBuf buffer) {
- byte b = buffer.readByte();
-
- if (b == DataConstants.NULL) {
- properties = null;
- } else {
- int numHeaders = buffer.readInt();
-
- properties = new HashMap<>(numHeaders);
- size = 0;
-
- for (int i = 0; i < numHeaders; i++) {
- int len = buffer.readInt();
- byte[] data = new byte[len];
- buffer.readBytes(data);
- SimpleString key = new SimpleString(data);
-
- byte type = buffer.readByte();
-
- PropertyValue val;
-
- switch (type) {
- case NULL: {
- val = new NullValue();
- doPutValue(key, val);
- break;
- }
- case CHAR: {
- val = new CharValue(buffer);
- doPutValue(key, val);
- break;
- }
- case BOOLEAN: {
- val = new BooleanValue(buffer);
- doPutValue(key, val);
- break;
- }
- case BYTE: {
- val = new ByteValue(buffer);
- doPutValue(key, val);
- break;
- }
- case BYTES: {
- val = new BytesValue(buffer);
- doPutValue(key, val);
- break;
- }
- case SHORT: {
- val = new ShortValue(buffer);
- doPutValue(key, val);
- break;
- }
- case INT: {
- val = new IntValue(buffer);
- doPutValue(key, val);
- break;
- }
- case LONG: {
- val = new LongValue(buffer);
- doPutValue(key, val);
- break;
- }
- case FLOAT: {
- val = new FloatValue(buffer);
- doPutValue(key, val);
- break;
- }
- case DOUBLE: {
- val = new DoubleValue(buffer);
- doPutValue(key, val);
- break;
- }
- case STRING: {
- val = new StringValue(buffer);
- doPutValue(key, val);
- break;
- }
- default: {
- throw ActiveMQUtilBundle.BUNDLE.invalidType(type);
- }
- }
- }
- }
- }
-
- public synchronized void encode(final ByteBuf buffer) {
- if (properties == null) {
- buffer.writeByte(DataConstants.NULL);
- } else {
- buffer.writeByte(DataConstants.NOT_NULL);
-
- buffer.writeInt(properties.size());
-
- for (Map.Entry entry : properties.entrySet()) {
- SimpleString s = entry.getKey();
- byte[] data = s.getData();
- buffer.writeInt(data.length);
- buffer.writeBytes(data);
-
- entry.getValue().write(buffer);
- }
- }
- }
-
- public int getEncodeSize() {
- if (properties == null) {
- return DataConstants.SIZE_BYTE;
- } else {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + size;
- }
- }
-
- public void clear() {
- if (properties != null) {
- properties.clear();
- }
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder("TypedProperties[");
-
- if (properties != null) {
-
- Iterator> iter = properties.entrySet().iterator();
-
- while (iter.hasNext()) {
- Entry iterItem = iter.next();
- sb.append(iterItem.getKey() + "=");
-
- // it seems weird but it's right!!
- // The first getValue is from the EntrySet
- // The second is to convert the PropertyValue into the actual value
- Object theValue = iterItem.getValue().getValue();
-
- if (theValue == null) {
- sb.append("NULL-value");
- } else if (theValue instanceof byte[]) {
- sb.append("[" + ByteUtil.maxString(ByteUtil.bytesToHex((byte[]) theValue, 2), 150) + ")");
-
- if (iterItem.getKey().toString().startsWith("_AMQ_ROUTE_TO")) {
- sb.append(",bytesAsLongs(");
- try {
- ByteBuffer buff = ByteBuffer.wrap((byte[]) theValue);
- while (buff.hasRemaining()) {
- long bindingID = buff.getLong();
- sb.append(bindingID);
- if (buff.hasRemaining()) {
- sb.append(",");
- }
- }
- } catch (Throwable e) {
- sb.append("error-converting-longs=" + e.getMessage());
- }
- sb.append("]");
- }
- } else {
- sb.append(theValue.toString());
- }
-
- if (iter.hasNext()) {
- sb.append(",");
- }
- }
- }
-
- return sb.append("]").toString();
- }
-
- // Private ------------------------------------------------------------------------------------
-
- private void checkCreateProperties() {
- if (properties == null) {
- properties = new HashMap<>();
- }
- }
-
- private synchronized void doPutValue(final SimpleString key, final PropertyValue value) {
- if (key.startsWith(AMQ_PROPNAME)) {
- internalProperties = true;
- }
-
- PropertyValue oldValue = properties.put(key, value);
- if (oldValue != null) {
- size += value.encodeSize() - oldValue.encodeSize();
- } else {
- size += SimpleString.sizeofString(key) + value.encodeSize();
- }
- }
-
- private synchronized Object doRemoveProperty(final SimpleString key) {
- if (properties == null) {
- return null;
- }
-
- PropertyValue val = properties.remove(key);
-
- if (val == null) {
- return null;
- } else {
- size -= SimpleString.sizeofString(key) + val.encodeSize();
-
- return val.getValue();
- }
- }
-
- private synchronized Object doGetProperty(final Object key) {
- if (size == 0) {
- return null;
- }
-
- PropertyValue val = properties.get(key);
-
- if (val == null) {
- return null;
- } else {
- return val.getValue();
- }
- }
-
- // Inner classes ------------------------------------------------------------------------------
-
- private abstract static class PropertyValue {
-
- abstract Object getValue();
-
- abstract void write(ByteBuf buffer);
-
- abstract int encodeSize();
-
- @Override
- public String toString() {
- return "" + getValue();
- }
- }
-
- private static final class NullValue extends PropertyValue {
-
- private NullValue() {
- }
-
- @Override
- public Object getValue() {
- return null;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.NULL);
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE;
- }
-
- }
-
- private static final class BooleanValue extends PropertyValue {
-
- final boolean val;
-
- private BooleanValue(final boolean val) {
- this.val = val;
- }
-
- private BooleanValue(final ByteBuf buffer) {
- val = buffer.readBoolean();
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.BOOLEAN);
- buffer.writeBoolean(val);
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_BOOLEAN;
- }
-
- }
-
- private static final class ByteValue extends PropertyValue {
-
- final byte val;
-
- private ByteValue(final byte val) {
- this.val = val;
- }
-
- private ByteValue(final ByteBuf buffer) {
- val = buffer.readByte();
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.BYTE);
- buffer.writeByte(val);
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_BYTE;
- }
- }
-
- private static final class BytesValue extends PropertyValue {
-
- final byte[] val;
-
- private BytesValue(final byte[] val) {
- this.val = val;
- }
-
- private BytesValue(final ByteBuf buffer) {
- int len = buffer.readInt();
- val = new byte[len];
- buffer.readBytes(val);
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.BYTES);
- buffer.writeInt(val.length);
- buffer.writeBytes(val);
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + val.length;
- }
-
- }
-
- private static final class ShortValue extends PropertyValue {
-
- final short val;
-
- private ShortValue(final short val) {
- this.val = val;
- }
-
- private ShortValue(final ByteBuf buffer) {
- val = buffer.readShort();
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.SHORT);
- buffer.writeShort(val);
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_SHORT;
- }
- }
-
- private static final class IntValue extends PropertyValue {
-
- final int val;
-
- private IntValue(final int val) {
- this.val = val;
- }
-
- private IntValue(final ByteBuf buffer) {
- val = buffer.readInt();
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.INT);
- buffer.writeInt(val);
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT;
- }
- }
-
- private static final class LongValue extends PropertyValue {
-
- final long val;
-
- private LongValue(final long val) {
- this.val = val;
- }
-
- private LongValue(final ByteBuf buffer) {
- val = buffer.readLong();
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.LONG);
- buffer.writeLong(val);
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_LONG;
- }
- }
-
- private static final class FloatValue extends PropertyValue {
-
- final float val;
-
- private FloatValue(final float val) {
- this.val = val;
- }
-
- private FloatValue(final ByteBuf buffer) {
- val = Float.intBitsToFloat(buffer.readInt());
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.FLOAT);
- buffer.writeInt(Float.floatToIntBits(val));
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_FLOAT;
- }
-
- }
-
- private static final class DoubleValue extends PropertyValue {
-
- final double val;
-
- private DoubleValue(final double val) {
- this.val = val;
- }
-
- private DoubleValue(final ByteBuf buffer) {
- val = Double.longBitsToDouble(buffer.readLong());
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.DOUBLE);
- buffer.writeLong(Double.doubleToLongBits(val));
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_DOUBLE;
- }
- }
-
- private static final class CharValue extends PropertyValue {
-
- final char val;
-
- private CharValue(final char val) {
- this.val = val;
- }
-
- private CharValue(final ByteBuf buffer) {
- val = (char) buffer.readShort();
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.CHAR);
- buffer.writeShort((short) val);
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + DataConstants.SIZE_CHAR;
- }
- }
-
- private static final class StringValue extends PropertyValue {
-
- final SimpleString val;
-
- private StringValue(final SimpleString val) {
- this.val = val;
- }
-
- private StringValue(final ByteBuf buffer) {
- val = SimpleString.readSimpleString(buffer);
- }
-
- @Override
- public Object getValue() {
- return val;
- }
-
- @Override
- public void write(final ByteBuf buffer) {
- buffer.writeByte(DataConstants.STRING);
- SimpleString.writeSimpleString(buffer, val);
- }
-
- @Override
- public int encodeSize() {
- return DataConstants.SIZE_BYTE + SimpleString.sizeofString(val);
- }
- }
-
- public boolean isEmpty() {
- return properties.isEmpty();
- }
-
- public Map getMap() {
- Map m = new HashMap<>();
- for (Entry entry : properties.entrySet()) {
- Object val = entry.getValue().getValue();
- if (val instanceof SimpleString) {
- m.put(entry.getKey().toString(), ((SimpleString) val).toString());
- } else {
- m.put(entry.getKey().toString(), val);
- }
- }
- return m;
- }
-
- /**
- * Helper for MapMessage#setObjectProperty(String, Object)
- *
- * @param key The SimpleString key
- * @param value The Object value
- * @param properties The typed properties
- */
- public static void setObjectProperty(final SimpleString key, final Object value, final TypedProperties properties) {
- if (value == null) {
- properties.putNullValue(key);
- } else if (value instanceof Boolean) {
- properties.putBooleanProperty(key, (Boolean) value);
- } else if (value instanceof Byte) {
- properties.putByteProperty(key, (Byte) value);
- } else if (value instanceof Character) {
- properties.putCharProperty(key, (Character) value);
- } else if (value instanceof Short) {
- properties.putShortProperty(key, (Short) value);
- } else if (value instanceof Integer) {
- properties.putIntProperty(key, (Integer) value);
- } else if (value instanceof Long) {
- properties.putLongProperty(key, (Long) value);
- } else if (value instanceof Float) {
- properties.putFloatProperty(key, (Float) value);
- } else if (value instanceof Double) {
- properties.putDoubleProperty(key, (Double) value);
- } else if (value instanceof String) {
- properties.putSimpleStringProperty(key, new SimpleString((String) value));
- } else if (value instanceof SimpleString) {
- properties.putSimpleStringProperty(key, (SimpleString) value);
- } else if (value instanceof byte[]) {
- properties.putBytesProperty(key, (byte[]) value);
- } else {
- throw new ActiveMQPropertyConversionException(value.getClass() + " is not a valid property type");
- }
- }
}
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ConcurrentHashSet.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentHashSet.java
similarity index 97%
rename from artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ConcurrentHashSet.java
rename to artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentHashSet.java
index 1b4e5d7753..21c15885a4 100644
--- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ConcurrentHashSet.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentHashSet.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.utils;
+package org.apache.activemq.artemis.utils.collections;
import java.util.AbstractSet;
import java.util.Iterator;
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashMap.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashMap.java
new file mode 100644
index 0000000000..8af0660be6
--- /dev/null
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashMap.java
@@ -0,0 +1,504 @@
+/*
+ *
+ * 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.collections;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+import java.util.concurrent.locks.StampedLock;
+import java.util.function.LongFunction;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Map from long to an Object.
+ *
+ * Provides similar methods as a ConcurrentMap with 2 differences:
+ *
+ * - No boxing/unboxing from long -> Long
+ *
- Open hash map with linear probing, no node allocations to store the values
+ *
+ *
+ * @param
+ */
+@SuppressWarnings("unchecked")
+public class ConcurrentLongHashMap {
+
+ private static final Object EmptyValue = null;
+ private static final Object DeletedValue = new Object();
+
+ private static final float MapFillFactor = 0.66f;
+
+ private static final int DefaultExpectedItems = 256;
+ private static final int DefaultConcurrencyLevel = 16;
+
+ private final Section[] sections;
+
+ public ConcurrentLongHashMap() {
+ this(DefaultExpectedItems);
+ }
+
+ public ConcurrentLongHashMap(int expectedItems) {
+ this(expectedItems, DefaultConcurrencyLevel);
+ }
+
+ public ConcurrentLongHashMap(int expectedItems, int numSections) {
+ checkArgument(numSections > 0);
+ if (expectedItems < numSections) {
+ expectedItems = numSections;
+ }
+
+ int perSectionExpectedItems = expectedItems / numSections;
+ int perSectionCapacity = (int) (perSectionExpectedItems / MapFillFactor);
+ this.sections = (Section[]) new Section[numSections];
+
+ for (int i = 0; i < numSections; i++) {
+ sections[i] = new Section<>(perSectionCapacity);
+ }
+ }
+
+ public int size() {
+ int size = 0;
+ for (Section s : sections) {
+ size += s.size;
+ }
+ return size;
+ }
+
+ long getUsedBucketCount() {
+ long usedBucketCount = 0;
+ for (Section s : sections) {
+ usedBucketCount += s.usedBuckets;
+ }
+ return usedBucketCount;
+ }
+
+ public long capacity() {
+ long capacity = 0;
+ for (Section s : sections) {
+ capacity += s.capacity;
+ }
+ return capacity;
+ }
+
+ public boolean isEmpty() {
+ for (Section s : sections) {
+ if (s.size != 0) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public V get(long key) {
+ long h = hash(key);
+ return getSection(h).get(key, (int) h);
+ }
+
+ public boolean containsKey(long key) {
+ return get(key) != null;
+ }
+
+ public V put(long key, V value) {
+ checkNotNull(value);
+ long h = hash(key);
+ return getSection(h).put(key, value, (int) h, false, null);
+ }
+
+ public V putIfAbsent(long key, V value) {
+ checkNotNull(value);
+ long h = hash(key);
+ return getSection(h).put(key, value, (int) h, true, null);
+ }
+
+ public V computeIfAbsent(long key, LongFunction provider) {
+ checkNotNull(provider);
+ long h = hash(key);
+ return getSection(h).put(key, null, (int) h, true, provider);
+ }
+
+ public V remove(long key) {
+ long h = hash(key);
+ return getSection(h).remove(key, null, (int) h);
+ }
+
+ public boolean remove(long key, Object value) {
+ checkNotNull(value);
+ long h = hash(key);
+ return getSection(h).remove(key, value, (int) h) != null;
+ }
+
+ private Section getSection(long hash) {
+ // Use 32 msb out of long to get the section
+ final int sectionIdx = (int) (hash >>> 32) & (sections.length - 1);
+ return sections[sectionIdx];
+ }
+
+ public void clear() {
+ for (Section s : sections) {
+ s.clear();
+ }
+ }
+
+ public void forEach(EntryProcessor processor) {
+ for (Section s : sections) {
+ s.forEach(processor);
+ }
+ }
+
+ /**
+ * @return a new list of all keys (makes a copy)
+ */
+ public List keys() {
+ List keys = Lists.newArrayListWithExpectedSize((int) size());
+ forEach((key, value) -> keys.add(key));
+ return keys;
+ }
+
+ public ConcurrentLongHashSet keysLongHashSet() {
+ ConcurrentLongHashSet concurrentLongHashSet = new ConcurrentLongHashSet(size());
+ forEach((key, value) -> concurrentLongHashSet.add(key));
+ return concurrentLongHashSet;
+ }
+
+ public List values() {
+ List values = Lists.newArrayListWithExpectedSize((int) size());
+ forEach((key, value) -> values.add(value));
+ return values;
+ }
+
+ public interface EntryProcessor {
+ void accept(long key, V value);
+ }
+
+ // A section is a portion of the hash map that is covered by a single
+ @SuppressWarnings("serial")
+ private static final class Section extends StampedLock {
+ private long[] keys;
+ private V[] values;
+
+ private int capacity;
+ private volatile int size;
+ private int usedBuckets;
+ private int resizeThreshold;
+
+ Section(int capacity) {
+ this.capacity = alignToPowerOfTwo(capacity);
+ this.keys = new long[this.capacity];
+ this.values = (V[]) new Object[this.capacity];
+ this.size = 0;
+ this.usedBuckets = 0;
+ this.resizeThreshold = (int) (this.capacity * MapFillFactor);
+ }
+
+ @SuppressWarnings("NonAtomicVolatileUpdate")
+ V get(long key, int keyHash) {
+ int bucket = keyHash;
+
+ long stamp = tryOptimisticRead();
+ boolean acquiredLock = false;
+
+ try {
+ while (true) {
+ int capacity = this.capacity;
+ bucket = signSafeMod(bucket, capacity);
+
+ // First try optimistic locking
+ long storedKey = keys[bucket];
+ V storedValue = values[bucket];
+
+ if (!acquiredLock && validate(stamp)) {
+ // The values we have read are consistent
+ if (storedKey == key) {
+ return storedValue != DeletedValue ? storedValue : null;
+ } else if (storedValue == EmptyValue) {
+ // Not found
+ return null;
+ }
+ } else {
+ // Fallback to acquiring read lock
+ if (!acquiredLock) {
+ stamp = readLock();
+ acquiredLock = true;
+ storedKey = keys[bucket];
+ storedValue = values[bucket];
+ }
+
+ if (capacity != this.capacity) {
+ // There has been a rehashing. We need to restart the search
+ bucket = keyHash;
+ continue;
+ }
+
+ if (storedKey == key) {
+ return storedValue != DeletedValue ? storedValue : null;
+ } else if (storedValue == EmptyValue) {
+ // Not found
+ return null;
+ }
+ }
+
+ ++bucket;
+ }
+ } finally {
+ if (acquiredLock) {
+ unlockRead(stamp);
+ }
+ }
+ }
+
+ @SuppressWarnings("NonAtomicVolatileUpdate")
+ V put(long key, V value, int keyHash, boolean onlyIfAbsent, LongFunction valueProvider) {
+ int bucket = keyHash;
+
+ long stamp = writeLock();
+ int capacity = this.capacity;
+
+ // Remember where we find the first available spot
+ int firstDeletedKey = -1;
+
+ try {
+ while (true) {
+ bucket = signSafeMod(bucket, capacity);
+
+ long storedKey = keys[bucket];
+ V storedValue = values[bucket];
+
+ if (storedKey == key) {
+ if (storedValue == EmptyValue) {
+ values[bucket] = value != null ? value : valueProvider.apply(key);
+ ++size;
+ ++usedBuckets;
+ return valueProvider != null ? values[bucket] : null;
+ } else if (storedValue == DeletedValue) {
+ values[bucket] = value != null ? value : valueProvider.apply(key);
+ ++size;
+ return valueProvider != null ? values[bucket] : null;
+ } else if (!onlyIfAbsent) {
+ // Over written an old value for same key
+ values[bucket] = value;
+ return storedValue;
+ } else {
+ return storedValue;
+ }
+ } else if (storedValue == EmptyValue) {
+ // Found an empty bucket. This means the key is not in the map. If we've already seen a deleted
+ // key, we should write at that position
+ if (firstDeletedKey != -1) {
+ bucket = firstDeletedKey;
+ } else {
+ ++usedBuckets;
+ }
+
+ keys[bucket] = key;
+ values[bucket] = value != null ? value : valueProvider.apply(key);
+ ++size;
+ return valueProvider != null ? values[bucket] : null;
+ } else if (storedValue == DeletedValue) {
+ // The bucket contained a different deleted key
+ if (firstDeletedKey == -1) {
+ firstDeletedKey = bucket;
+ }
+ }
+
+ ++bucket;
+ }
+ } finally {
+ if (usedBuckets > resizeThreshold) {
+ try {
+ rehash();
+ } finally {
+ unlockWrite(stamp);
+ }
+ } else {
+ unlockWrite(stamp);
+ }
+ }
+ }
+
+ @SuppressWarnings("NonAtomicVolatileUpdate")
+ private V remove(long key, Object value, int keyHash) {
+ int bucket = keyHash;
+ long stamp = writeLock();
+
+ try {
+ while (true) {
+ int capacity = this.capacity;
+ bucket = signSafeMod(bucket, capacity);
+
+ long storedKey = keys[bucket];
+ V storedValue = values[bucket];
+ if (storedKey == key) {
+ if (value == null || value.equals(storedValue)) {
+ if (storedValue == EmptyValue || storedValue == DeletedValue) {
+ return null;
+ }
+
+ --size;
+ V nextValueInArray = values[signSafeMod(bucket + 1, capacity)];
+ if (nextValueInArray == EmptyValue) {
+ values[bucket] = (V) EmptyValue;
+ --usedBuckets;
+ } else {
+ values[bucket] = (V) DeletedValue;
+ }
+
+ return storedValue;
+ } else {
+ return null;
+ }
+ } else if (storedValue == EmptyValue) {
+ // Key wasn't found
+ return null;
+ }
+
+ ++bucket;
+ }
+
+ } finally {
+ unlockWrite(stamp);
+ }
+ }
+
+ void clear() {
+ long stamp = writeLock();
+
+ try {
+ Arrays.fill(keys, 0);
+ Arrays.fill(values, EmptyValue);
+ this.size = 0;
+ this.usedBuckets = 0;
+ } finally {
+ unlockWrite(stamp);
+ }
+ }
+
+ public void forEach(EntryProcessor processor) {
+ long stamp = tryOptimisticRead();
+
+ int capacity = this.capacity;
+ long[] keys = this.keys;
+ V[] values = this.values;
+
+ boolean acquiredReadLock = false;
+
+ try {
+
+ // Validate no rehashing
+ if (!validate(stamp)) {
+ // Fallback to read lock
+ stamp = readLock();
+ acquiredReadLock = true;
+
+ capacity = this.capacity;
+ keys = this.keys;
+ values = this.values;
+ }
+
+ // Go through all the buckets for this section
+ for (int bucket = 0; bucket < capacity; bucket++) {
+ long storedKey = keys[bucket];
+ V storedValue = values[bucket];
+
+ if (!acquiredReadLock && !validate(stamp)) {
+ // Fallback to acquiring read lock
+ stamp = readLock();
+ acquiredReadLock = true;
+
+ storedKey = keys[bucket];
+ storedValue = values[bucket];
+ }
+
+ if (storedValue != DeletedValue && storedValue != EmptyValue) {
+ processor.accept(storedKey, storedValue);
+ }
+ }
+ } finally {
+ if (acquiredReadLock) {
+ unlockRead(stamp);
+ }
+ }
+ }
+
+ private void rehash() {
+ // Expand the hashmap
+ int newCapacity = capacity * 2;
+ long[] newKeys = new long[newCapacity];
+ V[] newValues = (V[]) new Object[newCapacity];
+
+ // Re-hash table
+ for (int i = 0; i < keys.length; i++) {
+ long storedKey = keys[i];
+ V storedValue = values[i];
+ if (storedValue != EmptyValue && storedValue != DeletedValue) {
+ insertKeyValueNoLock(newKeys, newValues, storedKey, storedValue);
+ }
+ }
+
+ capacity = newCapacity;
+ keys = newKeys;
+ values = newValues;
+ usedBuckets = size;
+ resizeThreshold = (int) (capacity * MapFillFactor);
+ }
+
+ private static void insertKeyValueNoLock(long[] keys, V[] values, long key, V value) {
+ int bucket = (int) hash(key);
+
+ while (true) {
+ bucket = signSafeMod(bucket, keys.length);
+
+ V storedValue = values[bucket];
+
+ if (storedValue == EmptyValue) {
+ // The bucket is empty, so we can use it
+ keys[bucket] = key;
+ values[bucket] = value;
+ return;
+ }
+
+ ++bucket;
+ }
+ }
+ }
+
+ private static final long HashMixer = 0xc6a4a7935bd1e995L;
+ private static final int R = 47;
+
+ static long hash(long key) {
+ long hash = key * HashMixer;
+ hash ^= hash >>> R;
+ hash *= HashMixer;
+ return hash;
+ }
+
+ static int signSafeMod(long n, int Max) {
+ return (int) n & (Max - 1);
+ }
+
+ static int alignToPowerOfTwo(int n) {
+ return (int) Math.pow(2, 32 - Integer.numberOfLeadingZeros(n - 1));
+ }
+}
\ No newline at end of file
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashSet.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashSet.java
new file mode 100644
index 0000000000..17d94b7c51
--- /dev/null
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashSet.java
@@ -0,0 +1,423 @@
+/*
+ *
+ * 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.collections;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.locks.StampedLock;
+
+/**
+ * Concurrent hash set for primitive longs
+ *
+ * Provides similar methods as a ConcurrentSet<Long> but since it's an open hash map with linear probing, no node
+ * allocations are required to store the values.
+ *
+ * Items MUST be >= 0.
+ */
+public class ConcurrentLongHashSet {
+
+ private static final long EmptyItem = -1L;
+ private static final long DeletedItem = -2L;
+
+ private static final float SetFillFactor = 0.66f;
+
+ private static final int DefaultExpectedItems = 256;
+ private static final int DefaultConcurrencyLevel = 16;
+
+ private final Section[] sections;
+
+ public interface ConsumerLong {
+ void accept(long item);
+ }
+
+ public ConcurrentLongHashSet() {
+ this(DefaultExpectedItems);
+ }
+
+ public ConcurrentLongHashSet(int expectedItems) {
+ this(expectedItems, DefaultConcurrencyLevel);
+ }
+
+ public ConcurrentLongHashSet(int expectedItems, final int numSections) {
+ checkArgument(numSections > 0);
+ if (expectedItems < numSections) {
+ expectedItems = numSections;
+ }
+
+ int perSectionExpectedItems = expectedItems / numSections;
+ int perSectionCapacity = (int) (perSectionExpectedItems / SetFillFactor);
+ this.sections = new Section[numSections];
+
+ for (int i = 0; i < numSections; i++) {
+ sections[i] = new Section(perSectionCapacity);
+ }
+ }
+
+ public int size() {
+ int size = 0;
+ for (Section s : sections) {
+ size += s.size;
+ }
+ return size;
+ }
+
+ public long capacity() {
+ long capacity = 0;
+ for (Section s : sections) {
+ capacity += s.capacity;
+ }
+ return capacity;
+ }
+
+ public boolean isEmpty() {
+ for (Section s : sections) {
+ if (s.size != 0) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ long getUsedBucketCount() {
+ long usedBucketCount = 0;
+ for (Section s : sections) {
+ usedBucketCount += s.usedBuckets;
+ }
+ return usedBucketCount;
+ }
+
+ public boolean contains(long item) {
+ checkBiggerEqualZero(item);
+ long h = hash(item);
+ return getSection(h).contains(item, (int) h);
+ }
+
+ public boolean add(long item) {
+ checkBiggerEqualZero(item);
+ long h = hash(item);
+ return getSection(h).add(item, (int) h);
+ }
+
+ /**
+ * Remove an existing entry if found
+ *
+ * @param item
+ * @return true if removed or false if item was not present
+ */
+ public boolean remove(long item) {
+ checkBiggerEqualZero(item);
+ long h = hash(item);
+ return getSection(h).remove(item, (int) h);
+ }
+
+ private Section getSection(long hash) {
+ // Use 32 msb out of long to get the section
+ final int sectionIdx = (int) (hash >>> 32) & (sections.length - 1);
+ return sections[sectionIdx];
+ }
+
+ public void clear() {
+ for (Section s : sections) {
+ s.clear();
+ }
+ }
+
+ public void forEach(ConsumerLong processor) {
+ for (Section s : sections) {
+ s.forEach(processor);
+ }
+ }
+
+ /**
+ * @return a new list of all keys (makes a copy)
+ */
+ public Set items() {
+ Set items = new HashSet<>();
+ forEach(items::add);
+ return items;
+ }
+
+ // A section is a portion of the hash map that is covered by a single
+ @SuppressWarnings("serial")
+ private static final class Section extends StampedLock {
+ // Keys and values are stored interleaved in the table array
+ private long[] table;
+
+ private int capacity;
+ private volatile int size;
+ private int usedBuckets;
+ private int resizeThreshold;
+
+ Section(int capacity) {
+ this.capacity = alignToPowerOfTwo(capacity);
+ this.table = new long[this.capacity];
+ this.size = 0;
+ this.usedBuckets = 0;
+ this.resizeThreshold = (int) (this.capacity * SetFillFactor);
+ Arrays.fill(table, EmptyItem);
+ }
+
+ boolean contains(long item, int hash) {
+ long stamp = tryOptimisticRead();
+ boolean acquiredLock = false;
+ int bucket = signSafeMod(hash, capacity);
+
+ try {
+ while (true) {
+ // First try optimistic locking
+ long storedItem = table[bucket];
+
+ if (!acquiredLock && validate(stamp)) {
+ // The values we have read are consistent
+ if (item == storedItem) {
+ return true;
+ } else if (storedItem == EmptyItem) {
+ // Not found
+ return false;
+ }
+ } else {
+ // Fallback to acquiring read lock
+ if (!acquiredLock) {
+ stamp = readLock();
+ acquiredLock = true;
+
+ bucket = signSafeMod(hash, capacity);
+ storedItem = table[bucket];
+ }
+
+ if (item == storedItem) {
+ return true;
+ } else if (storedItem == EmptyItem) {
+ // Not found
+ return false;
+ }
+ }
+
+ bucket = (bucket + 1) & (table.length - 1);
+ }
+ } finally {
+ if (acquiredLock) {
+ unlockRead(stamp);
+ }
+ }
+ }
+
+ @SuppressWarnings("NonAtomicVolatileUpdate")
+ boolean add(long item, long hash) {
+ long stamp = writeLock();
+ int bucket = signSafeMod(hash, capacity);
+
+ // Remember where we find the first available spot
+ int firstDeletedItem = -1;
+
+ try {
+ while (true) {
+ long storedItem = table[bucket];
+
+ if (item == storedItem) {
+ // Item was already in set
+ return false;
+ } else if (storedItem == EmptyItem) {
+ // Found an empty bucket. This means the key is not in the map. If we've already seen a deleted
+ // key, we should write at that position
+ if (firstDeletedItem != -1) {
+ bucket = firstDeletedItem;
+ } else {
+ ++usedBuckets;
+ }
+
+ table[bucket] = item;
+ ++size;
+ return true;
+ } else if (storedItem == DeletedItem) {
+ // The bucket contained a different deleted key
+ if (firstDeletedItem == -1) {
+ firstDeletedItem = bucket;
+ }
+ }
+
+ bucket = (bucket + 1) & (table.length - 1);
+ }
+ } finally {
+ if (usedBuckets > resizeThreshold) {
+ try {
+ rehash();
+ } finally {
+ unlockWrite(stamp);
+ }
+ } else {
+ unlockWrite(stamp);
+ }
+ }
+ }
+
+ @SuppressWarnings("NonAtomicVolatileUpdate")
+ private boolean remove(long item, int hash) {
+ long stamp = writeLock();
+ int bucket = signSafeMod(hash, capacity);
+
+ try {
+ while (true) {
+ long storedItem = table[bucket];
+ if (item == storedItem) {
+ --size;
+
+ cleanBucket(bucket);
+ return true;
+
+ } else if (storedItem == EmptyItem) {
+ // Key wasn't found
+ return false;
+ }
+
+ bucket = (bucket + 1) & (table.length - 1);
+ }
+ } finally {
+ unlockWrite(stamp);
+ }
+ }
+
+ private void cleanBucket(int bucket) {
+ int nextInArray = (bucket + 1) & (table.length - 1);
+ if (table[nextInArray] == EmptyItem) {
+ table[bucket] = EmptyItem;
+ --usedBuckets;
+ } else {
+ table[bucket] = DeletedItem;
+ }
+ }
+
+ void clear() {
+ long stamp = writeLock();
+
+ try {
+ Arrays.fill(table, EmptyItem);
+ this.size = 0;
+ this.usedBuckets = 0;
+ } finally {
+ unlockWrite(stamp);
+ }
+ }
+
+ public void forEach(ConsumerLong processor) {
+ long stamp = tryOptimisticRead();
+
+ long[] table = this.table;
+ boolean acquiredReadLock = false;
+
+ try {
+
+ // Validate no rehashing
+ if (!validate(stamp)) {
+ // Fallback to read lock
+ stamp = readLock();
+ acquiredReadLock = true;
+ table = this.table;
+ }
+
+ // Go through all the buckets for this section
+ for (int bucket = 0; bucket < table.length; bucket++) {
+ long storedItem = table[bucket];
+
+ if (!acquiredReadLock && !validate(stamp)) {
+ // Fallback to acquiring read lock
+ stamp = readLock();
+ acquiredReadLock = true;
+
+ storedItem = table[bucket];
+ }
+
+ if (storedItem != DeletedItem && storedItem != EmptyItem) {
+ processor.accept(storedItem);
+ }
+ }
+ } finally {
+ if (acquiredReadLock) {
+ unlockRead(stamp);
+ }
+ }
+ }
+
+ private void rehash() {
+ // Expand the hashmap
+ int newCapacity = capacity * 2;
+ long[] newTable = new long[newCapacity];
+ Arrays.fill(newTable, EmptyItem);
+
+ // Re-hash table
+ for (int i = 0; i < table.length; i++) {
+ long storedItem = table[i];
+ if (storedItem != EmptyItem && storedItem != DeletedItem) {
+ insertKeyValueNoLock(newTable, newCapacity, storedItem);
+ }
+ }
+
+ capacity = newCapacity;
+ table = newTable;
+ usedBuckets = size;
+ resizeThreshold = (int) (capacity * SetFillFactor);
+ }
+
+ private static void insertKeyValueNoLock(long[] table, int capacity, long item) {
+ int bucket = signSafeMod(hash(item), capacity);
+
+ while (true) {
+ long storedKey = table[bucket];
+
+ if (storedKey == EmptyItem) {
+ // The bucket is empty, so we can use it
+ table[bucket] = item;
+ return;
+ }
+
+ bucket = (bucket + 1) & (table.length - 1);
+ }
+ }
+ }
+
+ private static final long HashMixer = 0xc6a4a7935bd1e995L;
+ private static final int R = 47;
+
+ static long hash(long key) {
+ long hash = key * HashMixer;
+ hash ^= hash >>> R;
+ hash *= HashMixer;
+ return hash;
+ }
+
+ static int signSafeMod(long n, int Max) {
+ return (int) (n & (Max - 1));
+ }
+
+ static int alignToPowerOfTwo(int n) {
+ return (int) Math.pow(2, 32 - Integer.numberOfLeadingZeros(n - 1));
+ }
+
+ static void checkBiggerEqualZero(long n) {
+ if (n < 0L) {
+ throw new IllegalArgumentException("Keys and values must be >= 0");
+ }
+ }
+}
\ No newline at end of file
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ConcurrentSet.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentSet.java
similarity index 94%
rename from artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ConcurrentSet.java
rename to artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentSet.java
index e55be241aa..bab7aa3747 100644
--- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ConcurrentSet.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/ConcurrentSet.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.utils;
+package org.apache.activemq.artemis.utils.collections;
import java.util.Set;
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/LinkedList.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedList.java
similarity index 94%
rename from artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/LinkedList.java
rename to artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedList.java
index fd64aaf6f7..3a77c42808 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/LinkedList.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedList.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.utils;
+package org.apache.activemq.artemis.utils.collections;
public interface LinkedList {
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/LinkedListImpl.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListImpl.java
similarity index 99%
rename from artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/LinkedListImpl.java
rename to artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListImpl.java
index f0d2945684..81b5d6091a 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/LinkedListImpl.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListImpl.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.utils;
+package org.apache.activemq.artemis.utils.collections;
import java.lang.reflect.Array;
import java.util.NoSuchElementException;
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/LinkedListIterator.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListIterator.java
similarity index 95%
rename from artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/LinkedListIterator.java
rename to artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListIterator.java
index 10700e5558..62ab097adc 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/LinkedListIterator.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListIterator.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.utils;
+package org.apache.activemq.artemis.utils.collections;
import java.util.Iterator;
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/PriorityLinkedList.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/PriorityLinkedList.java
similarity index 95%
rename from artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/PriorityLinkedList.java
rename to artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/PriorityLinkedList.java
index 450f58a8e1..79a99f310b 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/PriorityLinkedList.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/PriorityLinkedList.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.utils;
+package org.apache.activemq.artemis.utils.collections;
/**
* A type of linked list which maintains items according to a priority
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/PriorityLinkedListImpl.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/PriorityLinkedListImpl.java
similarity index 99%
rename from artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/PriorityLinkedListImpl.java
rename to artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/PriorityLinkedListImpl.java
index 427a927d90..39d6b6dcc6 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/PriorityLinkedListImpl.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/PriorityLinkedListImpl.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.utils;
+package org.apache.activemq.artemis.utils.collections;
import java.lang.reflect.Array;
import java.util.NoSuchElementException;
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/TypedProperties.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/TypedProperties.java
new file mode 100644
index 0000000000..9657f366cd
--- /dev/null
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/TypedProperties.java
@@ -0,0 +1,939 @@
+/*
+ * 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.collections;
+
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException;
+import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.logs.ActiveMQUtilBundle;
+import org.apache.activemq.artemis.utils.ByteUtil;
+import org.apache.activemq.artemis.utils.DataConstants;
+
+import static org.apache.activemq.artemis.utils.DataConstants.BOOLEAN;
+import static org.apache.activemq.artemis.utils.DataConstants.BYTE;
+import static org.apache.activemq.artemis.utils.DataConstants.BYTES;
+import static org.apache.activemq.artemis.utils.DataConstants.CHAR;
+import static org.apache.activemq.artemis.utils.DataConstants.DOUBLE;
+import static org.apache.activemq.artemis.utils.DataConstants.FLOAT;
+import static org.apache.activemq.artemis.utils.DataConstants.INT;
+import static org.apache.activemq.artemis.utils.DataConstants.LONG;
+import static org.apache.activemq.artemis.utils.DataConstants.NULL;
+import static org.apache.activemq.artemis.utils.DataConstants.SHORT;
+import static org.apache.activemq.artemis.utils.DataConstants.STRING;
+
+/**
+ * Property Value Conversion.
+ *
+ * This implementation follows section 3.5.4 of the Java Message Service specification
+ * (Version 1.1 April 12, 2002).
+ *
+ */
+public class TypedProperties {
+
+ private static final SimpleString AMQ_PROPNAME = new SimpleString("_AMQ_");
+
+ private Map properties;
+
+ private volatile int size;
+
+ private boolean internalProperties;
+
+ public TypedProperties() {
+ }
+
+ /**
+ * Return the number of properites
+ * */
+ public int size() {
+ return properties.size();
+ }
+
+ public int getMemoryOffset() {
+ // The estimate is basically the encode size + 2 object references for each entry in the map
+ // Note we don't include the attributes or anything else since they already included in the memory estimate
+ // of the ServerMessage
+
+ return properties == null ? 0 : size + 2 * DataConstants.SIZE_INT * properties.size();
+ }
+
+ public TypedProperties(final TypedProperties other) {
+ properties = other.properties == null ? null : new HashMap<>(other.properties);
+ size = other.size;
+ }
+
+ public boolean hasInternalProperties() {
+ return internalProperties;
+ }
+
+ public void putBooleanProperty(final SimpleString key, final boolean value) {
+ checkCreateProperties();
+ doPutValue(key, new BooleanValue(value));
+ }
+
+ public void putByteProperty(final SimpleString key, final byte value) {
+ checkCreateProperties();
+ doPutValue(key, new ByteValue(value));
+ }
+
+ public void putBytesProperty(final SimpleString key, final byte[] value) {
+ checkCreateProperties();
+ doPutValue(key, value == null ? new NullValue() : new BytesValue(value));
+ }
+
+ public void putShortProperty(final SimpleString key, final short value) {
+ checkCreateProperties();
+ doPutValue(key, new ShortValue(value));
+ }
+
+ public void putIntProperty(final SimpleString key, final int value) {
+ checkCreateProperties();
+ doPutValue(key, new IntValue(value));
+ }
+
+ public void putLongProperty(final SimpleString key, final long value) {
+ checkCreateProperties();
+ doPutValue(key, new LongValue(value));
+ }
+
+ public void putFloatProperty(final SimpleString key, final float value) {
+ checkCreateProperties();
+ doPutValue(key, new FloatValue(value));
+ }
+
+ public void putDoubleProperty(final SimpleString key, final double value) {
+ checkCreateProperties();
+ doPutValue(key, new DoubleValue(value));
+ }
+
+ public void putSimpleStringProperty(final SimpleString key, final SimpleString value) {
+ checkCreateProperties();
+ doPutValue(key, value == null ? new NullValue() : new StringValue(value));
+ }
+
+ public void putNullValue(final SimpleString key) {
+ checkCreateProperties();
+ doPutValue(key, new NullValue());
+ }
+
+ public void putCharProperty(final SimpleString key, final char value) {
+ checkCreateProperties();
+ doPutValue(key, new CharValue(value));
+ }
+
+ public void putTypedProperties(final TypedProperties otherProps) {
+ if (otherProps == null || otherProps.properties == null) {
+ return;
+ }
+
+ checkCreateProperties();
+ Set> otherEntries = otherProps.properties.entrySet();
+ for (Entry otherEntry : otherEntries) {
+ doPutValue(otherEntry.getKey(), otherEntry.getValue());
+ }
+ }
+
+ public Object getProperty(final SimpleString key) {
+ return doGetProperty(key);
+ }
+
+ public Boolean getBooleanProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+ if (value == null) {
+ return Boolean.valueOf(null);
+ } else if (value instanceof Boolean) {
+ return (Boolean) value;
+ } else if (value instanceof SimpleString) {
+ return Boolean.valueOf(((SimpleString) value).toString());
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public Byte getByteProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+ if (value == null) {
+ return Byte.valueOf(null);
+ } else if (value instanceof Byte) {
+ return (Byte) value;
+ } else if (value instanceof SimpleString) {
+ return Byte.parseByte(((SimpleString) value).toString());
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public Character getCharProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+ if (value == null) {
+ throw new NullPointerException("Invalid conversion: " + key);
+ }
+
+ if (value instanceof Character) {
+ return ((Character) value);
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public byte[] getBytesProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+ if (value == null) {
+ return null;
+ } else if (value instanceof byte[]) {
+ return (byte[]) value;
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public Double getDoubleProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+ if (value == null) {
+ return Double.valueOf(null);
+ } else if (value instanceof Float) {
+ return ((Float) value).doubleValue();
+ } else if (value instanceof Double) {
+ return (Double) value;
+ } else if (value instanceof SimpleString) {
+ return Double.parseDouble(((SimpleString) value).toString());
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public Integer getIntProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+ if (value == null) {
+ return Integer.valueOf(null);
+ } else if (value instanceof Integer) {
+ return (Integer) value;
+ } else if (value instanceof Byte) {
+ return ((Byte) value).intValue();
+ } else if (value instanceof Short) {
+ return ((Short) value).intValue();
+ } else if (value instanceof SimpleString) {
+ return Integer.parseInt(((SimpleString) value).toString());
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public Long getLongProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+ if (value == null) {
+ return Long.valueOf(null);
+ } else if (value instanceof Long) {
+ return (Long) value;
+ } else if (value instanceof Byte) {
+ return ((Byte) value).longValue();
+ } else if (value instanceof Short) {
+ return ((Short) value).longValue();
+ } else if (value instanceof Integer) {
+ return ((Integer) value).longValue();
+ } else if (value instanceof SimpleString) {
+ return Long.parseLong(((SimpleString) value).toString());
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public Short getShortProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+ if (value == null) {
+ return Short.valueOf(null);
+ } else if (value instanceof Byte) {
+ return ((Byte) value).shortValue();
+ } else if (value instanceof Short) {
+ return (Short) value;
+ } else if (value instanceof SimpleString) {
+ return Short.parseShort(((SimpleString) value).toString());
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public Float getFloatProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+ if (value == null)
+ return Float.valueOf(null);
+ if (value instanceof Float) {
+ return ((Float) value);
+ }
+ if (value instanceof SimpleString) {
+ return Float.parseFloat(((SimpleString) value).toString());
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public SimpleString getSimpleStringProperty(final SimpleString key) throws ActiveMQPropertyConversionException {
+ Object value = doGetProperty(key);
+
+ if (value == null) {
+ return null;
+ }
+
+ if (value instanceof SimpleString) {
+ return (SimpleString) value;
+ } else if (value instanceof Boolean) {
+ return new SimpleString(value.toString());
+ } else if (value instanceof Character) {
+ return new SimpleString(value.toString());
+ } else if (value instanceof Byte) {
+ return new SimpleString(value.toString());
+ } else if (value instanceof Short) {
+ return new SimpleString(value.toString());
+ } else if (value instanceof Integer) {
+ return new SimpleString(value.toString());
+ } else if (value instanceof Long) {
+ return new SimpleString(value.toString());
+ } else if (value instanceof Float) {
+ return new SimpleString(value.toString());
+ } else if (value instanceof Double) {
+ return new SimpleString(value.toString());
+ }
+ throw new ActiveMQPropertyConversionException("Invalid conversion: " + key);
+ }
+
+ public Object removeProperty(final SimpleString key) {
+ return doRemoveProperty(key);
+ }
+
+ public boolean containsProperty(final SimpleString key) {
+ if (size == 0) {
+ return false;
+
+ } else {
+ return properties.containsKey(key);
+ }
+ }
+
+ public Set getPropertyNames() {
+ if (size == 0) {
+ return Collections.emptySet();
+ } else {
+ return properties.keySet();
+ }
+ }
+
+ public synchronized void decode(final ByteBuf buffer) {
+ byte b = buffer.readByte();
+
+ if (b == DataConstants.NULL) {
+ properties = null;
+ } else {
+ int numHeaders = buffer.readInt();
+
+ properties = new HashMap<>(numHeaders);
+ size = 0;
+
+ for (int i = 0; i < numHeaders; i++) {
+ int len = buffer.readInt();
+ byte[] data = new byte[len];
+ buffer.readBytes(data);
+ SimpleString key = new SimpleString(data);
+
+ byte type = buffer.readByte();
+
+ PropertyValue val;
+
+ switch (type) {
+ case NULL: {
+ val = new NullValue();
+ doPutValue(key, val);
+ break;
+ }
+ case CHAR: {
+ val = new CharValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case BOOLEAN: {
+ val = new BooleanValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case BYTE: {
+ val = new ByteValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case BYTES: {
+ val = new BytesValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case SHORT: {
+ val = new ShortValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case INT: {
+ val = new IntValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case LONG: {
+ val = new LongValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case FLOAT: {
+ val = new FloatValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case DOUBLE: {
+ val = new DoubleValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ case STRING: {
+ val = new StringValue(buffer);
+ doPutValue(key, val);
+ break;
+ }
+ default: {
+ throw ActiveMQUtilBundle.BUNDLE.invalidType(type);
+ }
+ }
+ }
+ }
+ }
+
+ public synchronized void encode(final ByteBuf buffer) {
+ if (properties == null) {
+ buffer.writeByte(DataConstants.NULL);
+ } else {
+ buffer.writeByte(DataConstants.NOT_NULL);
+
+ buffer.writeInt(properties.size());
+
+ for (Map.Entry entry : properties.entrySet()) {
+ SimpleString s = entry.getKey();
+ byte[] data = s.getData();
+ buffer.writeInt(data.length);
+ buffer.writeBytes(data);
+
+ entry.getValue().write(buffer);
+ }
+ }
+ }
+
+ public int getEncodeSize() {
+ if (properties == null) {
+ return DataConstants.SIZE_BYTE;
+ } else {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + size;
+ }
+ }
+
+ public void clear() {
+ if (properties != null) {
+ properties.clear();
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("TypedProperties[");
+
+ if (properties != null) {
+
+ Iterator> iter = properties.entrySet().iterator();
+
+ while (iter.hasNext()) {
+ Entry iterItem = iter.next();
+ sb.append(iterItem.getKey() + "=");
+
+ // it seems weird but it's right!!
+ // The first getValue is from the EntrySet
+ // The second is to convert the PropertyValue into the actual value
+ Object theValue = iterItem.getValue().getValue();
+
+ if (theValue == null) {
+ sb.append("NULL-value");
+ } else if (theValue instanceof byte[]) {
+ sb.append("[" + ByteUtil.maxString(ByteUtil.bytesToHex((byte[]) theValue, 2), 150) + ")");
+
+ if (iterItem.getKey().toString().startsWith("_AMQ_ROUTE_TO")) {
+ sb.append(",bytesAsLongs(");
+ try {
+ ByteBuffer buff = ByteBuffer.wrap((byte[]) theValue);
+ while (buff.hasRemaining()) {
+ long bindingID = buff.getLong();
+ sb.append(bindingID);
+ if (buff.hasRemaining()) {
+ sb.append(",");
+ }
+ }
+ } catch (Throwable e) {
+ sb.append("error-converting-longs=" + e.getMessage());
+ }
+ sb.append("]");
+ }
+ } else {
+ sb.append(theValue.toString());
+ }
+
+ if (iter.hasNext()) {
+ sb.append(",");
+ }
+ }
+ }
+
+ return sb.append("]").toString();
+ }
+
+ // Private ------------------------------------------------------------------------------------
+
+ private void checkCreateProperties() {
+ if (properties == null) {
+ properties = new HashMap<>();
+ }
+ }
+
+ private synchronized void doPutValue(final SimpleString key, final PropertyValue value) {
+ if (key.startsWith(AMQ_PROPNAME)) {
+ internalProperties = true;
+ }
+
+ PropertyValue oldValue = properties.put(key, value);
+ if (oldValue != null) {
+ size += value.encodeSize() - oldValue.encodeSize();
+ } else {
+ size += SimpleString.sizeofString(key) + value.encodeSize();
+ }
+ }
+
+ private synchronized Object doRemoveProperty(final SimpleString key) {
+ if (properties == null) {
+ return null;
+ }
+
+ PropertyValue val = properties.remove(key);
+
+ if (val == null) {
+ return null;
+ } else {
+ size -= SimpleString.sizeofString(key) + val.encodeSize();
+
+ return val.getValue();
+ }
+ }
+
+ private synchronized Object doGetProperty(final Object key) {
+ if (size == 0) {
+ return null;
+ }
+
+ PropertyValue val = properties.get(key);
+
+ if (val == null) {
+ return null;
+ } else {
+ return val.getValue();
+ }
+ }
+
+ // Inner classes ------------------------------------------------------------------------------
+
+ private abstract static class PropertyValue {
+
+ abstract Object getValue();
+
+ abstract void write(ByteBuf buffer);
+
+ abstract int encodeSize();
+
+ @Override
+ public String toString() {
+ return "" + getValue();
+ }
+ }
+
+ private static final class NullValue extends PropertyValue {
+
+ private NullValue() {
+ }
+
+ @Override
+ public Object getValue() {
+ return null;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.NULL);
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE;
+ }
+
+ }
+
+ private static final class BooleanValue extends PropertyValue {
+
+ final boolean val;
+
+ private BooleanValue(final boolean val) {
+ this.val = val;
+ }
+
+ private BooleanValue(final ByteBuf buffer) {
+ val = buffer.readBoolean();
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.BOOLEAN);
+ buffer.writeBoolean(val);
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_BOOLEAN;
+ }
+
+ }
+
+ private static final class ByteValue extends PropertyValue {
+
+ final byte val;
+
+ private ByteValue(final byte val) {
+ this.val = val;
+ }
+
+ private ByteValue(final ByteBuf buffer) {
+ val = buffer.readByte();
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.BYTE);
+ buffer.writeByte(val);
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_BYTE;
+ }
+ }
+
+ private static final class BytesValue extends PropertyValue {
+
+ final byte[] val;
+
+ private BytesValue(final byte[] val) {
+ this.val = val;
+ }
+
+ private BytesValue(final ByteBuf buffer) {
+ int len = buffer.readInt();
+ val = new byte[len];
+ buffer.readBytes(val);
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.BYTES);
+ buffer.writeInt(val.length);
+ buffer.writeBytes(val);
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + val.length;
+ }
+
+ }
+
+ private static final class ShortValue extends PropertyValue {
+
+ final short val;
+
+ private ShortValue(final short val) {
+ this.val = val;
+ }
+
+ private ShortValue(final ByteBuf buffer) {
+ val = buffer.readShort();
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.SHORT);
+ buffer.writeShort(val);
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_SHORT;
+ }
+ }
+
+ private static final class IntValue extends PropertyValue {
+
+ final int val;
+
+ private IntValue(final int val) {
+ this.val = val;
+ }
+
+ private IntValue(final ByteBuf buffer) {
+ val = buffer.readInt();
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.INT);
+ buffer.writeInt(val);
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT;
+ }
+ }
+
+ private static final class LongValue extends PropertyValue {
+
+ final long val;
+
+ private LongValue(final long val) {
+ this.val = val;
+ }
+
+ private LongValue(final ByteBuf buffer) {
+ val = buffer.readLong();
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.LONG);
+ buffer.writeLong(val);
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_LONG;
+ }
+ }
+
+ private static final class FloatValue extends PropertyValue {
+
+ final float val;
+
+ private FloatValue(final float val) {
+ this.val = val;
+ }
+
+ private FloatValue(final ByteBuf buffer) {
+ val = Float.intBitsToFloat(buffer.readInt());
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.FLOAT);
+ buffer.writeInt(Float.floatToIntBits(val));
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_FLOAT;
+ }
+
+ }
+
+ private static final class DoubleValue extends PropertyValue {
+
+ final double val;
+
+ private DoubleValue(final double val) {
+ this.val = val;
+ }
+
+ private DoubleValue(final ByteBuf buffer) {
+ val = Double.longBitsToDouble(buffer.readLong());
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.DOUBLE);
+ buffer.writeLong(Double.doubleToLongBits(val));
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_DOUBLE;
+ }
+ }
+
+ private static final class CharValue extends PropertyValue {
+
+ final char val;
+
+ private CharValue(final char val) {
+ this.val = val;
+ }
+
+ private CharValue(final ByteBuf buffer) {
+ val = (char) buffer.readShort();
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.CHAR);
+ buffer.writeShort((short) val);
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + DataConstants.SIZE_CHAR;
+ }
+ }
+
+ private static final class StringValue extends PropertyValue {
+
+ final SimpleString val;
+
+ private StringValue(final SimpleString val) {
+ this.val = val;
+ }
+
+ private StringValue(final ByteBuf buffer) {
+ val = SimpleString.readSimpleString(buffer);
+ }
+
+ @Override
+ public Object getValue() {
+ return val;
+ }
+
+ @Override
+ public void write(final ByteBuf buffer) {
+ buffer.writeByte(DataConstants.STRING);
+ SimpleString.writeSimpleString(buffer, val);
+ }
+
+ @Override
+ public int encodeSize() {
+ return DataConstants.SIZE_BYTE + SimpleString.sizeofString(val);
+ }
+ }
+
+ public boolean isEmpty() {
+ return properties.isEmpty();
+ }
+
+ public Map getMap() {
+ Map m = new HashMap<>();
+ for (Entry entry : properties.entrySet()) {
+ Object val = entry.getValue().getValue();
+ if (val instanceof SimpleString) {
+ m.put(entry.getKey().toString(), ((SimpleString) val).toString());
+ } else {
+ m.put(entry.getKey().toString(), val);
+ }
+ }
+ return m;
+ }
+
+ /**
+ * Helper for MapMessage#setObjectProperty(String, Object)
+ *
+ * @param key The SimpleString key
+ * @param value The Object value
+ * @param properties The typed properties
+ */
+ public static void setObjectProperty(final SimpleString key, final Object value, final TypedProperties properties) {
+ if (value == null) {
+ properties.putNullValue(key);
+ } else if (value instanceof Boolean) {
+ properties.putBooleanProperty(key, (Boolean) value);
+ } else if (value instanceof Byte) {
+ properties.putByteProperty(key, (Byte) value);
+ } else if (value instanceof Character) {
+ properties.putCharProperty(key, (Character) value);
+ } else if (value instanceof Short) {
+ properties.putShortProperty(key, (Short) value);
+ } else if (value instanceof Integer) {
+ properties.putIntProperty(key, (Integer) value);
+ } else if (value instanceof Long) {
+ properties.putLongProperty(key, (Long) value);
+ } else if (value instanceof Float) {
+ properties.putFloatProperty(key, (Float) value);
+ } else if (value instanceof Double) {
+ properties.putDoubleProperty(key, (Double) value);
+ } else if (value instanceof String) {
+ properties.putSimpleStringProperty(key, new SimpleString((String) value));
+ } else if (value instanceof SimpleString) {
+ properties.putSimpleStringProperty(key, (SimpleString) value);
+ } else if (value instanceof byte[]) {
+ properties.putBytesProperty(key, (byte[]) value);
+ } else {
+ throw new ActiveMQPropertyConversionException(value.getClass() + " is not a valid property type");
+ }
+ }
+}
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/uri/FluentPropertyBeanIntrospectorWithIgnores.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/uri/FluentPropertyBeanIntrospectorWithIgnores.java
index 7df9131255..ad56353eef 100644
--- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/uri/FluentPropertyBeanIntrospectorWithIgnores.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/uri/FluentPropertyBeanIntrospectorWithIgnores.java
@@ -23,7 +23,7 @@ import java.lang.reflect.Method;
import java.util.Locale;
import org.apache.activemq.artemis.api.core.Pair;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.apache.commons.beanutils.FluentPropertyBeanIntrospector;
import org.apache.commons.beanutils.IntrospectionContext;
import org.jboss.logging.Logger;
diff --git a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/ConcurrentHashSetTest.java b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/ConcurrentHashSetTest.java
index 4055801c4a..8e0c8c835f 100644
--- a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/ConcurrentHashSetTest.java
+++ b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/ConcurrentHashSetTest.java
@@ -18,6 +18,8 @@ package org.apache.activemq.artemis.utils;
import java.util.Iterator;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentSet;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
diff --git a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesConversionTest.java b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesConversionTest.java
index cec395969b..539172412f 100644
--- a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesConversionTest.java
+++ b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesConversionTest.java
@@ -18,6 +18,7 @@ package org.apache.activemq.artemis.utils;
import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException;
import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
diff --git a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesTest.java b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesTest.java
index cb6c8fe776..38144c9082 100644
--- a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesTest.java
+++ b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesTest.java
@@ -21,6 +21,7 @@ import java.util.Iterator;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
diff --git a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashMapTest.java b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashMapTest.java
new file mode 100644
index 0000000000..b08251fe44
--- /dev/null
+++ b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashMapTest.java
@@ -0,0 +1,405 @@
+/*
+ *
+ * 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.collections;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.LongFunction;
+
+import com.google.common.collect.Lists;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
+
+public class ConcurrentLongHashMapTest {
+
+ @Test
+ public void simpleInsertions() {
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>(16);
+
+ assertTrue(map.isEmpty());
+ assertNull(map.put(1, "one"));
+ assertFalse(map.isEmpty());
+
+ assertNull(map.put(2, "two"));
+ assertNull(map.put(3, "three"));
+
+ assertEquals(map.size(), 3);
+
+ assertEquals(map.get(1), "one");
+ assertEquals(map.size(), 3);
+
+ assertEquals(map.remove(1), "one");
+ assertEquals(map.size(), 2);
+ assertEquals(map.get(1), null);
+ assertEquals(map.get(5), null);
+ assertEquals(map.size(), 2);
+
+ assertNull(map.put(1, "one"));
+ assertEquals(map.size(), 3);
+ assertEquals(map.put(1, "uno"), "one");
+ assertEquals(map.size(), 3);
+ }
+
+ @Test
+ public void testRemove() {
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>();
+
+ assertTrue(map.isEmpty());
+ assertNull(map.put(1, "one"));
+ assertFalse(map.isEmpty());
+
+ assertFalse(map.remove(0, "zero"));
+ assertFalse(map.remove(1, "uno"));
+
+ assertFalse(map.isEmpty());
+ assertTrue(map.remove(1, "one"));
+ assertTrue(map.isEmpty());
+ }
+
+ @Test
+ public void testNegativeUsedBucketCount() {
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>(16, 1);
+
+ map.put(0, "zero");
+ assertEquals(1, map.getUsedBucketCount());
+ map.put(0, "zero1");
+ assertEquals(1, map.getUsedBucketCount());
+ map.remove(0);
+ assertEquals(0, map.getUsedBucketCount());
+ map.remove(0);
+ assertEquals(0, map.getUsedBucketCount());
+ }
+
+ @Test
+ public void testRehashing() {
+ int n = 16;
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>(n / 2, 1);
+ assertEquals(map.capacity(), n);
+ assertEquals(map.size(), 0);
+
+ for (int i = 0; i < n; i++) {
+ map.put(i, i);
+ }
+
+ assertEquals(map.capacity(), 2 * n);
+ assertEquals(map.size(), n);
+ }
+
+ @Test
+ public void testRehashingWithDeletes() {
+ int n = 16;
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>(n / 2, 1);
+ assertEquals(map.capacity(), n);
+ assertEquals(map.size(), 0);
+
+ for (int i = 0; i < n / 2; i++) {
+ map.put(i, i);
+ }
+
+ for (int i = 0; i < n / 2; i++) {
+ map.remove(i);
+ }
+
+ for (int i = n; i < (2 * n); i++) {
+ map.put(i, i);
+ }
+
+ assertEquals(map.capacity(), 2 * n);
+ assertEquals(map.size(), n);
+ }
+
+ @Test
+ public void concurrentInsertions() throws Throwable {
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>();
+ ExecutorService executor = Executors.newCachedThreadPool();
+
+ final int nThreads = 16;
+ final int N = 100_000;
+ String value = "value";
+
+ List> futures = new ArrayList<>();
+ for (int i = 0; i < nThreads; i++) {
+ final int threadIdx = i;
+
+ futures.add(executor.submit(() -> {
+ Random random = new Random();
+
+ for (int j = 0; j < N; j++) {
+ long key = random.nextLong();
+ // Ensure keys are uniques
+ key -= key % (threadIdx + 1);
+
+ map.put(key, value);
+ }
+ }));
+ }
+
+ for (Future> future : futures) {
+ future.get();
+ }
+
+ assertEquals(map.size(), N * nThreads);
+
+ executor.shutdown();
+ }
+
+ @Test
+ public void concurrentInsertionsAndReads() throws Throwable {
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>();
+ ExecutorService executor = Executors.newCachedThreadPool();
+
+ final int nThreads = 16;
+ final int N = 100_000;
+ String value = "value";
+
+ List> futures = new ArrayList<>();
+ for (int i = 0; i < nThreads; i++) {
+ final int threadIdx = i;
+
+ futures.add(executor.submit(() -> {
+ Random random = new Random();
+
+ for (int j = 0; j < N; j++) {
+ long key = random.nextLong();
+ // Ensure keys are uniques
+ key -= key % (threadIdx + 1);
+
+ map.put(key, value);
+ }
+ }));
+ }
+
+ for (Future> future : futures) {
+ future.get();
+ }
+
+ assertEquals(map.size(), N * nThreads);
+
+ executor.shutdown();
+ }
+
+ @Test
+ public void testIteration() {
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>();
+
+ assertEquals(map.keys(), Collections.emptyList());
+ assertEquals(map.values(), Collections.emptyList());
+
+ map.put(0, "zero");
+
+ assertEquals(map.keys(), Lists.newArrayList(0L));
+ assertEquals(map.values(), Lists.newArrayList("zero"));
+
+ map.remove(0);
+
+ assertEquals(map.keys(), Collections.emptyList());
+ assertEquals(map.values(), Collections.emptyList());
+
+ map.put(0, "zero");
+ map.put(1, "one");
+ map.put(2, "two");
+
+ List keys = map.keys();
+ Collections.sort(keys);
+ assertEquals(keys, Lists.newArrayList(0L, 1L, 2L));
+
+ List values = map.values();
+ Collections.sort(values);
+ assertEquals(values, Lists.newArrayList("one", "two", "zero"));
+
+ map.put(1, "uno");
+
+ keys = map.keys();
+ Collections.sort(keys);
+ assertEquals(keys, Lists.newArrayList(0L, 1L, 2L));
+
+ values = map.values();
+ Collections.sort(values);
+ assertEquals(values, Lists.newArrayList("two", "uno", "zero"));
+
+ map.clear();
+ assertTrue(map.isEmpty());
+ }
+
+ @Test
+ public void testHashConflictWithDeletion() {
+ final int Buckets = 16;
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>(Buckets, 1);
+
+ // Pick 2 keys that fall into the same bucket
+ long key1 = 1;
+ long key2 = 27;
+
+ int bucket1 = ConcurrentLongHashMap.signSafeMod(ConcurrentLongHashMap.hash(key1), Buckets);
+ int bucket2 = ConcurrentLongHashMap.signSafeMod(ConcurrentLongHashMap.hash(key2), Buckets);
+ assertEquals(bucket1, bucket2);
+
+ assertEquals(map.put(key1, "value-1"), null);
+ assertEquals(map.put(key2, "value-2"), null);
+ assertEquals(map.size(), 2);
+
+ assertEquals(map.remove(key1), "value-1");
+ assertEquals(map.size(), 1);
+
+ assertEquals(map.put(key1, "value-1-overwrite"), null);
+ assertEquals(map.size(), 2);
+
+ assertEquals(map.remove(key1), "value-1-overwrite");
+ assertEquals(map.size(), 1);
+
+ assertEquals(map.put(key2, "value-2-overwrite"), "value-2");
+ assertEquals(map.get(key2), "value-2-overwrite");
+
+ assertEquals(map.size(), 1);
+ assertEquals(map.remove(key2), "value-2-overwrite");
+ assertTrue(map.isEmpty());
+ }
+
+ @Test
+ public void testPutIfAbsent() {
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>();
+ assertEquals(map.putIfAbsent(1, "one"), null);
+ assertEquals(map.get(1), "one");
+
+ assertEquals(map.putIfAbsent(1, "uno"), "one");
+ assertEquals(map.get(1), "one");
+ }
+
+ @Test
+ public void testComputeIfAbsent() {
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>(16, 1);
+ AtomicInteger counter = new AtomicInteger();
+ LongFunction provider = key -> counter.getAndIncrement();
+
+ assertEquals(map.computeIfAbsent(0, provider).intValue(), 0);
+ assertEquals(map.get(0).intValue(), 0);
+
+ assertEquals(map.computeIfAbsent(1, provider).intValue(), 1);
+ assertEquals(map.get(1).intValue(), 1);
+
+ assertEquals(map.computeIfAbsent(1, provider).intValue(), 1);
+ assertEquals(map.get(1).intValue(), 1);
+
+ assertEquals(map.computeIfAbsent(2, provider).intValue(), 2);
+ assertEquals(map.get(2).intValue(), 2);
+ }
+
+ int Iterations = 1;
+ int ReadIterations = 100;
+ int N = 1_000_000;
+
+ public void benchConcurrentLongHashMap() throws Exception {
+ // public static void main(String args[]) {
+ ConcurrentLongHashMap map = new ConcurrentLongHashMap<>(N, 1);
+
+ for (long i = 0; i < Iterations; i++) {
+ for (int j = 0; j < N; j++) {
+ map.put(i, "value");
+ }
+
+ for (long h = 0; h < ReadIterations; h++) {
+ for (int j = 0; j < N; j++) {
+ map.get(i);
+ }
+ }
+
+ for (int j = 0; j < N; j++) {
+ map.remove(i);
+ }
+ }
+ }
+
+ public void benchConcurrentHashMap() throws Exception {
+ ConcurrentHashMap map = new ConcurrentHashMap<>(N, 0.66f, 1);
+
+ for (long i = 0; i < Iterations; i++) {
+ for (int j = 0; j < N; j++) {
+ map.put(i, "value");
+ }
+
+ for (long h = 0; h < ReadIterations; h++) {
+ for (int j = 0; j < N; j++) {
+ map.get(i);
+ }
+ }
+
+ for (int j = 0; j < N; j++) {
+ map.remove(i);
+ }
+ }
+ }
+
+ void benchHashMap() throws Exception {
+ HashMap map = new HashMap<>(N, 0.66f);
+
+ for (long i = 0; i < Iterations; i++) {
+ for (int j = 0; j < N; j++) {
+ map.put(i, "value");
+ }
+
+ for (long h = 0; h < ReadIterations; h++) {
+ for (int j = 0; j < N; j++) {
+ map.get(i);
+ }
+ }
+
+ for (int j = 0; j < N; j++) {
+ map.remove(i);
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ ConcurrentLongHashMapTest t = new ConcurrentLongHashMapTest();
+
+ long start = System.nanoTime();
+ // t.benchHashMap();
+ long end = System.nanoTime();
+
+ System.out.println("HM: " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
+
+ start = System.nanoTime();
+ t.benchConcurrentHashMap();
+ end = System.nanoTime();
+
+ System.out.println("CHM: " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
+
+ start = System.nanoTime();
+ // t.benchConcurrentLongHashMap();
+ end = System.nanoTime();
+
+ System.out.println("CLHM: " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
+
+ }
+}
\ No newline at end of file
diff --git a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashSetTest.java b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashSetTest.java
new file mode 100644
index 0000000000..24337f10bd
--- /dev/null
+++ b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/collections/ConcurrentLongHashSetTest.java
@@ -0,0 +1,249 @@
+/*
+ *
+ * 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.collections;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ConcurrentLongHashSetTest {
+
+ @Test
+ public void simpleInsertions() {
+ ConcurrentLongHashSet set = new ConcurrentLongHashSet(16);
+
+ assertTrue(set.isEmpty());
+ assertTrue(set.add(1));
+ assertFalse(set.isEmpty());
+
+ assertTrue(set.add(2));
+ assertTrue(set.add(3));
+
+ assertEquals(set.size(), 3);
+
+ assertTrue(set.contains(1));
+ assertEquals(set.size(), 3);
+
+ assertTrue(set.remove(1));
+ assertEquals(set.size(), 2);
+ assertFalse(set.contains(1));
+ assertFalse(set.contains(5));
+ assertEquals(set.size(), 2);
+
+ assertTrue(set.add(1));
+ assertEquals(set.size(), 3);
+ assertFalse(set.add(1));
+ assertEquals(set.size(), 3);
+ }
+
+ @Test
+ public void testRemove() {
+ ConcurrentLongHashSet set = new ConcurrentLongHashSet();
+
+ assertTrue(set.isEmpty());
+ assertTrue(set.add(1));
+ assertFalse(set.isEmpty());
+
+ assertFalse(set.remove(0));
+ assertFalse(set.isEmpty());
+ assertTrue(set.remove(1));
+ assertTrue(set.isEmpty());
+ }
+
+ @Test
+ public void testRehashing() {
+ int n = 16;
+ ConcurrentLongHashSet set = new ConcurrentLongHashSet(n / 2, 1);
+ assertEquals(set.capacity(), n);
+ assertEquals(set.size(), 0);
+
+ for (int i = 0; i < n; i++) {
+ set.add(i);
+ }
+
+ assertEquals(set.capacity(), 2 * n);
+ assertEquals(set.size(), n);
+ }
+
+ @Test
+ public void testRehashingWithDeletes() {
+ int n = 16;
+ ConcurrentLongHashSet set = new ConcurrentLongHashSet(n / 2, 1);
+ assertEquals(set.capacity(), n);
+ assertEquals(set.size(), 0);
+
+ for (int i = 0; i < n / 2; i++) {
+ set.add(i);
+ }
+
+ for (int i = 0; i < n / 2; i++) {
+ set.remove(i);
+ }
+
+ for (int i = n; i < (2 * n); i++) {
+ set.add(i);
+ }
+
+ assertEquals(set.capacity(), 2 * n);
+ assertEquals(set.size(), n);
+ }
+
+ @Test
+ public void concurrentInsertions() throws Throwable {
+ ConcurrentLongHashSet set = new ConcurrentLongHashSet();
+ ExecutorService executor = Executors.newCachedThreadPool();
+
+ final int nThreads = 16;
+ final int N = 100_000;
+
+ List> futures = new ArrayList<>();
+ for (int i = 0; i < nThreads; i++) {
+ final int threadIdx = i;
+
+ futures.add(executor.submit(() -> {
+ Random random = new Random();
+
+ for (int j = 0; j < N; j++) {
+ long key = Math.abs(random.nextLong());
+ // Ensure keys are unique
+ key -= key % (threadIdx + 1);
+
+ set.add(key);
+ }
+ }));
+ }
+
+ for (Future> future : futures) {
+ future.get();
+ }
+
+ assertEquals(set.size(), N * nThreads);
+
+ executor.shutdown();
+ }
+
+ @Test
+ public void concurrentInsertionsAndReads() throws Throwable {
+ ConcurrentLongHashSet map = new ConcurrentLongHashSet();
+ ExecutorService executor = Executors.newCachedThreadPool();
+
+ final int nThreads = 16;
+ final int N = 100_000;
+
+ List> futures = new ArrayList<>();
+ for (int i = 0; i < nThreads; i++) {
+ final int threadIdx = i;
+
+ futures.add(executor.submit(() -> {
+ Random random = new Random();
+
+ for (int j = 0; j < N; j++) {
+ long key = Math.abs(random.nextLong());
+ // Ensure keys are unique
+ key -= key % (threadIdx + 1);
+
+ map.add(key);
+ }
+ }));
+ }
+
+ for (Future> future : futures) {
+ future.get();
+ }
+
+ assertEquals(map.size(), N * nThreads);
+
+ executor.shutdown();
+ }
+
+ @Test
+ public void testIteration() {
+ ConcurrentLongHashSet set = new ConcurrentLongHashSet();
+
+ assertEquals(set.items(), Collections.emptySet());
+
+ set.add(0L);
+
+ assertEquals(set.items(), Sets.newHashSet(0L));
+
+ set.remove(0L);
+
+ assertEquals(set.items(), Collections.emptySet());
+
+ set.add(0L);
+ set.add(1L);
+ set.add(2L);
+
+ List values = Lists.newArrayList(set.items());
+ Collections.sort(values);
+ assertEquals(values, Lists.newArrayList(0L, 1L, 2L));
+
+ set.clear();
+ assertTrue(set.isEmpty());
+ }
+
+ @Test
+ public void testHashConflictWithDeletion() {
+ final int Buckets = 16;
+ ConcurrentLongHashSet set = new ConcurrentLongHashSet(Buckets, 1);
+
+ // Pick 2 keys that fall into the same bucket
+ long key1 = 1;
+ long key2 = 27;
+
+ int bucket1 = ConcurrentLongHashSet.signSafeMod(ConcurrentLongHashSet.hash(key1), Buckets);
+ int bucket2 = ConcurrentLongHashSet.signSafeMod(ConcurrentLongHashSet.hash(key2), Buckets);
+ assertEquals(bucket1, bucket2);
+
+ assertTrue(set.add(key1));
+ assertTrue(set.add(key2));
+ assertEquals(set.size(), 2);
+
+ assertTrue(set.remove(key1));
+ assertEquals(set.size(), 1);
+
+ assertTrue(set.add(key1));
+ assertEquals(set.size(), 2);
+
+ assertTrue(set.remove(key1));
+ assertEquals(set.size(), 1);
+
+ assertFalse(set.add(key2));
+ assertTrue(set.contains(key2));
+
+ assertEquals(set.size(), 1);
+ assertTrue(set.remove(key2));
+ assertTrue(set.isEmpty());
+ }
+
+}
\ No newline at end of file
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientConsumerImpl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientConsumerImpl.java
index 82af968919..0ff971dcaa 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientConsumerImpl.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientConsumerImpl.java
@@ -40,10 +40,10 @@ import org.apache.activemq.artemis.spi.core.remoting.ConsumerContext;
import org.apache.activemq.artemis.spi.core.remoting.SessionContext;
import org.apache.activemq.artemis.utils.ByteUtil;
import org.apache.activemq.artemis.utils.FutureLatch;
-import org.apache.activemq.artemis.utils.PriorityLinkedList;
-import org.apache.activemq.artemis.utils.PriorityLinkedListImpl;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.apache.activemq.artemis.utils.TokenBucketLimiter;
+import org.apache.activemq.artemis.utils.collections.PriorityLinkedList;
+import org.apache.activemq.artemis.utils.collections.PriorityLinkedListImpl;
import org.jboss.logging.Logger;
public final class ClientConsumerImpl implements ClientConsumerInternal {
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientMessageImpl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientMessageImpl.java
index 252ae86d77..91fb6caeda 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientMessageImpl.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientMessageImpl.java
@@ -31,8 +31,8 @@ import org.apache.activemq.artemis.core.client.ActiveMQClientMessageBundle;
import org.apache.activemq.artemis.core.message.LargeBodyEncoder;
import org.apache.activemq.artemis.core.message.impl.CoreMessage;
import org.apache.activemq.artemis.reader.MessageUtil;
-import org.apache.activemq.artemis.utils.TypedProperties;
import org.apache.activemq.artemis.utils.UUID;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
/**
* A ClientMessageImpl
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientMessageInternal.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientMessageInternal.java
index 4b878782b8..1a7fe07e0f 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientMessageInternal.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientMessageInternal.java
@@ -17,7 +17,7 @@
package org.apache.activemq.artemis.core.client.impl;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
public interface ClientMessageInternal extends ClientMessage {
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl.java
index addbbbde73..8f6a5eac3c 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl.java
@@ -62,11 +62,11 @@ import org.apache.activemq.artemis.spi.core.remoting.ConnectorFactory;
import org.apache.activemq.artemis.spi.core.remoting.SessionContext;
import org.apache.activemq.artemis.spi.core.remoting.TopologyResponseHandler;
import org.apache.activemq.artemis.utils.ClassloadingUtil;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.ConfirmationWindowWarning;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.OrderedExecutorFactory;
import org.apache.activemq.artemis.utils.UUIDGenerator;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;
public class ClientSessionFactoryImpl implements ClientSessionFactoryInternal, ClientConnectionLifeCycleListener {
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/cluster/DiscoveryGroup.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/cluster/DiscoveryGroup.java
index 7c40602de6..282932dbad 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/cluster/DiscoveryGroup.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/cluster/DiscoveryGroup.java
@@ -35,7 +35,7 @@ import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
import org.apache.activemq.artemis.core.server.ActiveMQComponent;
import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.core.server.management.NotificationService;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/message/impl/CoreMessage.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/message/impl/CoreMessage.java
index 215c268268..369de7dcfd 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/message/impl/CoreMessage.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/message/impl/CoreMessage.java
@@ -39,8 +39,8 @@ import org.apache.activemq.artemis.core.persistence.Persister;
import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
import org.apache.activemq.artemis.reader.MessageUtil;
import org.apache.activemq.artemis.utils.DataConstants;
-import org.apache.activemq.artemis.utils.TypedProperties;
import org.apache.activemq.artemis.utils.UUID;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/** Note: you shouldn't change properties using multi-threads. Change your properties before you can send it to multiple
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/server/management/Notification.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/server/management/Notification.java
index ae1f91db54..1bdc52af52 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/server/management/Notification.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/server/management/Notification.java
@@ -17,7 +17,7 @@
package org.apache.activemq.artemis.core.server.management;
import org.apache.activemq.artemis.api.core.management.NotificationType;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
/**
* A Notification
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/reader/MapMessageUtil.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/reader/MapMessageUtil.java
index 8560f5d213..52f8be582a 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/reader/MapMessageUtil.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/reader/MapMessageUtil.java
@@ -17,7 +17,7 @@
package org.apache.activemq.artemis.reader;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
public class MapMessageUtil extends MessageUtil {
diff --git a/artemis-core-client/src/test/java/org/apache/activemq/artemis/util/TimeAndCounterIDGeneratorTest.java b/artemis-core-client/src/test/java/org/apache/activemq/artemis/util/TimeAndCounterIDGeneratorTest.java
index c2ec02d7c9..812cafcd17 100644
--- a/artemis-core-client/src/test/java/org/apache/activemq/artemis/util/TimeAndCounterIDGeneratorTest.java
+++ b/artemis-core-client/src/test/java/org/apache/activemq/artemis/util/TimeAndCounterIDGeneratorTest.java
@@ -19,8 +19,8 @@ package org.apache.activemq.artemis.util;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.TimeAndCounterIDGenerator;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.junit.Assert;
import org.junit.Test;
diff --git a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactory.java b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactory.java
index 48cb638528..dfbf1ba647 100644
--- a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactory.java
+++ b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactory.java
@@ -34,7 +34,7 @@ import org.apache.activemq.artemis.core.io.nio.NIOSequentialFileFactory;
import org.apache.activemq.artemis.core.server.ActiveMQComponent;
import org.apache.activemq.artemis.jdbc.store.sql.SQLProvider;
import org.apache.activemq.artemis.journal.ActiveMQJournalLogger;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;
public class JDBCSequentialFileFactory implements SequentialFileFactory, ActiveMQComponent {
diff --git a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnection.java b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnection.java
index 0c6cf9de3e..c90e630ce1 100644
--- a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnection.java
+++ b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnection.java
@@ -53,9 +53,9 @@ import org.apache.activemq.artemis.core.client.impl.ClientSessionInternal;
import org.apache.activemq.artemis.core.version.Version;
import org.apache.activemq.artemis.reader.MessageUtil;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.UUIDGenerator;
import org.apache.activemq.artemis.utils.VersionLoader;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
/**
* ActiveMQ Artemis implementation of a JMS Connection.
diff --git a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQJMSProducer.java b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQJMSProducer.java
index 9911302b59..965eefd361 100644
--- a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQJMSProducer.java
+++ b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQJMSProducer.java
@@ -39,7 +39,7 @@ import java.util.Set;
import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException;
import org.apache.activemq.artemis.api.core.SimpleString;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
/**
* NOTE: this class forwards {@link #setDisableMessageID(boolean)} and
diff --git a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMapMessage.java b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMapMessage.java
index a69061e92e..9749328b1f 100644
--- a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMapMessage.java
+++ b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMapMessage.java
@@ -30,7 +30,7 @@ import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientSession;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import static org.apache.activemq.artemis.reader.MapMessageUtil.readBodyMap;
import static org.apache.activemq.artemis.reader.MapMessageUtil.writeBodyMap;
diff --git a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ThreadAwareContext.java b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ThreadAwareContext.java
index c74264f2fc..f825408807 100644
--- a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ThreadAwareContext.java
+++ b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ThreadAwareContext.java
@@ -19,7 +19,7 @@ package org.apache.activemq.artemis.jms.client;
import javax.jms.IllegalStateException;
import java.util.Set;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
/**
* Restricts what can be called on context passed in wrapped CompletionListener.
diff --git a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/impl/JMSServerManagerImpl.java b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/impl/JMSServerManagerImpl.java
index 2fa71087ee..afa39e363f 100644
--- a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/impl/JMSServerManagerImpl.java
+++ b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/impl/JMSServerManagerImpl.java
@@ -42,6 +42,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.activemq.artemis.api.core.ActiveMQAddressDoesNotExistException;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration;
+import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.management.AddressControl;
@@ -57,7 +58,6 @@ import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.server.ActivateCallback;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
-import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.server.management.Notification;
@@ -93,8 +93,8 @@ import org.apache.activemq.artemis.spi.core.naming.BindingRegistry;
import org.apache.activemq.artemis.utils.JsonLoader;
import org.apache.activemq.artemis.utils.SelectorTranslator;
import org.apache.activemq.artemis.utils.TimeAndCounterIDGenerator;
-import org.apache.activemq.artemis.utils.TypedProperties;
import org.apache.activemq.artemis.utils.XMLUtil;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
diff --git a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/AbstractJournalUpdateTask.java b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/AbstractJournalUpdateTask.java
index 943077c59f..8de3da6400 100644
--- a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/AbstractJournalUpdateTask.java
+++ b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/AbstractJournalUpdateTask.java
@@ -19,7 +19,6 @@ package org.apache.activemq.artemis.core.journal.impl;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
@@ -30,7 +29,7 @@ import org.apache.activemq.artemis.core.journal.EncoderPersister;
import org.apache.activemq.artemis.core.journal.impl.dataformat.ByteArrayEncoding;
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalAddRecord;
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalInternalRecord;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashSet;
/**
* Super class for Journal maintenances such as clean up and Compactor
@@ -56,7 +55,7 @@ public abstract class AbstractJournalUpdateTask implements JournalReaderCallback
private ActiveMQBuffer writingChannel;
- private final Set recordsSnapshot = new ConcurrentHashSet<>();
+ private final ConcurrentLongHashSet recordsSnapshot;
protected final List newDataFiles = new ArrayList<>();
@@ -67,14 +66,14 @@ public abstract class AbstractJournalUpdateTask implements JournalReaderCallback
protected AbstractJournalUpdateTask(final SequentialFileFactory fileFactory,
final JournalImpl journal,
final JournalFilesRepository filesRepository,
- final Set recordsSnapshot,
+ final ConcurrentLongHashSet recordsSnapshot,
final long nextOrderingID) {
super();
this.journal = journal;
this.filesRepository = filesRepository;
this.fileFactory = fileFactory;
this.nextOrderingID = nextOrderingID;
- this.recordsSnapshot.addAll(recordsSnapshot);
+ this.recordsSnapshot = recordsSnapshot;
}
// Public --------------------------------------------------------
diff --git a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/FileWrapperJournal.java b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/FileWrapperJournal.java
index 8e5ca2c8f8..5ef240ae2b 100644
--- a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/FileWrapperJournal.java
+++ b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/FileWrapperJournal.java
@@ -18,8 +18,6 @@ package org.apache.activemq.artemis.core.journal.impl;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
@@ -43,6 +41,7 @@ import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalDeleteRec
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalDeleteRecordTX;
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalInternalRecord;
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalRollbackRecordTX;
+import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashMap;
/**
* Journal used at a replicating backup server during the synchronization of data with the 'live'
@@ -54,7 +53,7 @@ public final class FileWrapperJournal extends JournalBase {
private final ReentrantLock lockAppend = new ReentrantLock();
- private final ConcurrentMap transactions = new ConcurrentHashMap<>();
+ private final ConcurrentLongHashMap transactions = new ConcurrentLongHashMap<>();
private final JournalImpl journal;
protected volatile JournalFile currentFile;
@@ -181,7 +180,7 @@ public final class FileWrapperJournal extends JournalBase {
IOCompletion callback,
boolean lineUpContext) throws Exception {
JournalInternalRecord commitRecord = new JournalCompleteRecordTX(TX_RECORD_TYPE.COMMIT, txID, null);
- AtomicInteger value = transactions.remove(Long.valueOf(txID));
+ AtomicInteger value = transactions.remove(txID);
if (value != null) {
commitRecord.setNumberOfRecords(value.get());
}
@@ -195,7 +194,7 @@ public final class FileWrapperJournal extends JournalBase {
boolean sync,
IOCompletion callback) throws Exception {
JournalInternalRecord prepareRecord = new JournalCompleteRecordTX(TX_RECORD_TYPE.PREPARE, txID, transactionData);
- AtomicInteger value = transactions.get(Long.valueOf(txID));
+ AtomicInteger value = transactions.get(txID);
if (value != null) {
prepareRecord.setNumberOfRecords(value.get());
}
@@ -204,7 +203,7 @@ public final class FileWrapperJournal extends JournalBase {
private int count(long txID) throws ActiveMQException {
AtomicInteger defaultValue = new AtomicInteger(1);
- AtomicInteger count = transactions.putIfAbsent(Long.valueOf(txID), defaultValue);
+ AtomicInteger count = transactions.putIfAbsent(txID, defaultValue);
if (count != null) {
return count.incrementAndGet();
}
@@ -219,7 +218,7 @@ public final class FileWrapperJournal extends JournalBase {
@Override
public void appendRollbackRecord(long txID, boolean sync, IOCompletion callback) throws Exception {
JournalInternalRecord rollbackRecord = new JournalRollbackRecordTX(txID);
- AtomicInteger value = transactions.remove(Long.valueOf(txID));
+ AtomicInteger value = transactions.remove(txID);
if (value != null) {
rollbackRecord.setNumberOfRecords(value.get());
}
diff --git a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalCompactor.java b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalCompactor.java
index 8b89c3ed96..e3e1e7b469 100644
--- a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalCompactor.java
+++ b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalCompactor.java
@@ -18,12 +18,8 @@ package org.apache.activemq.artemis.core.journal.impl;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
@@ -41,6 +37,8 @@ import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalDeleteRec
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalInternalRecord;
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalRollbackRecordTX;
import org.apache.activemq.artemis.journal.ActiveMQJournalLogger;
+import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashMap;
+import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashSet;
import org.jboss.logging.Logger;
public class JournalCompactor extends AbstractJournalUpdateTask implements JournalRecordProvider {
@@ -53,11 +51,11 @@ public class JournalCompactor extends AbstractJournalUpdateTask implements Journ
private static final short COMPACT_SPLIT_LINE = 2;
// Snapshot of transactions that were pending when the compactor started
- private final Map pendingTransactions = new ConcurrentHashMap<>();
+ private final ConcurrentLongHashMap pendingTransactions = new ConcurrentLongHashMap<>();
- private final Map newRecords = new HashMap<>();
+ private final ConcurrentLongHashMap newRecords = new ConcurrentLongHashMap<>();
- private final Map newTransactions = new HashMap<>();
+ private final ConcurrentLongHashMap newTransactions = new ConcurrentLongHashMap<>();
/**
* Commands that happened during compacting
@@ -120,18 +118,18 @@ public class JournalCompactor extends AbstractJournalUpdateTask implements Journ
return newDataFiles;
}
- public Map getNewRecords() {
+ public ConcurrentLongHashMap getNewRecords() {
return newRecords;
}
- public Map getNewTransactions() {
+ public ConcurrentLongHashMap getNewTransactions() {
return newTransactions;
}
public JournalCompactor(final SequentialFileFactory fileFactory,
final JournalImpl journal,
final JournalFilesRepository filesRepository,
- final Set recordsSnapshot,
+ final ConcurrentLongHashSet recordsSnapshot,
final long firstFileID) {
super(fileFactory, journal, filesRepository, recordsSnapshot, firstFileID);
}
@@ -628,7 +626,7 @@ public class JournalCompactor extends AbstractJournalUpdateTask implements Journ
}
@Override
- public Map getRecords() {
+ public ConcurrentLongHashMap getRecords() {
return newRecords;
}
diff --git a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
index 81ae9c0fee..7e8320c71b 100644
--- a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
+++ b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
@@ -31,8 +31,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
@@ -57,7 +55,6 @@ import org.apache.activemq.artemis.core.journal.EncodingSupport;
import org.apache.activemq.artemis.core.journal.IOCompletion;
import org.apache.activemq.artemis.core.journal.JournalLoadInformation;
import org.apache.activemq.artemis.core.journal.LoaderCallback;
-import org.apache.activemq.artemis.core.persistence.Persister;
import org.apache.activemq.artemis.core.journal.PreparedTransactionInfo;
import org.apache.activemq.artemis.core.journal.RecordInfo;
import org.apache.activemq.artemis.core.journal.TestableJournal;
@@ -70,15 +67,18 @@ import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalDeleteRec
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalDeleteRecordTX;
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalInternalRecord;
import org.apache.activemq.artemis.core.journal.impl.dataformat.JournalRollbackRecordTX;
+import org.apache.activemq.artemis.core.persistence.Persister;
import org.apache.activemq.artemis.journal.ActiveMQJournalBundle;
import org.apache.activemq.artemis.journal.ActiveMQJournalLogger;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.DataConstants;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.OrderedExecutorFactory;
import org.apache.activemq.artemis.utils.SimpleFuture;
import org.apache.activemq.artemis.utils.SimpleFutureImpl;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashMap;
+import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashSet;
import org.jboss.logging.Logger;
/**
@@ -168,12 +168,12 @@ public class JournalImpl extends JournalBase implements TestableJournal, Journal
private final JournalFilesRepository filesRepository;
// Compacting may replace this structure
- private final ConcurrentMap records = new ConcurrentHashMap<>();
+ private final ConcurrentLongHashMap records = new ConcurrentLongHashMap<>();
- private final Set pendingRecords = new ConcurrentHashSet<>();
+ private final ConcurrentLongHashSet pendingRecords = new ConcurrentLongHashSet();
// Compacting may replace this structure
- private final ConcurrentMap transactions = new ConcurrentHashMap<>();
+ private final ConcurrentLongHashMap transactions = new ConcurrentLongHashMap<>();
// This will be set only while the JournalCompactor is being executed
private volatile JournalCompactor compactor;
@@ -345,7 +345,7 @@ public class JournalImpl extends JournalBase implements TestableJournal, Journal
}
@Override
- public Map getRecords() {
+ public ConcurrentLongHashMap getRecords() {
return records;
}
@@ -1487,12 +1487,12 @@ public class JournalImpl extends JournalBase implements TestableJournal, Journal
return;
}
- compactor = new JournalCompactor(fileFactory, this, filesRepository, records.keySet(), dataFilesToProcess.get(0).getFileID());
+ compactor = new JournalCompactor(fileFactory, this, filesRepository, records.keysLongHashSet(), dataFilesToProcess.get(0).getFileID());
- for (Map.Entry entry : transactions.entrySet()) {
- compactor.addPendingTransaction(entry.getKey(), entry.getValue().getPositiveArray());
- entry.getValue().setCompacting();
- }
+ transactions.forEach((id, pendingTransaction) -> {
+ compactor.addPendingTransaction(id, pendingTransaction.getPositiveArray());
+ pendingTransaction.setCompacting();
+ });
// We will calculate the new records during compacting, what will take the position the records will take
// after compacting
@@ -1540,9 +1540,9 @@ public class JournalImpl extends JournalBase implements TestableJournal, Journal
newDatafiles = localCompactor.getNewDataFiles();
// Restore newRecords created during compacting
- for (Map.Entry newRecordEntry : localCompactor.getNewRecords().entrySet()) {
- records.put(newRecordEntry.getKey(), newRecordEntry.getValue());
- }
+ localCompactor.getNewRecords().forEach((id, newRecord) -> {
+ records.put(id, newRecord);
+ });
// Restore compacted dataFiles
for (int i = newDatafiles.size() - 1; i >= 0; i--) {
@@ -1559,9 +1559,7 @@ public class JournalImpl extends JournalBase implements TestableJournal, Journal
// Replay pending commands (including updates, deletes and commits)
- for (JournalTransaction newTransaction : localCompactor.getNewTransactions().values()) {
- newTransaction.replaceRecordProvider(this);
- }
+ localCompactor.getNewTransactions().forEach((id, newTransaction) -> newTransaction.replaceRecordProvider(this));
localCompactor.replayPendingCommands();
@@ -1569,7 +1567,7 @@ public class JournalImpl extends JournalBase implements TestableJournal, Journal
// This has to be done after the replay pending commands, as we need to delete commits
// that happened during the compacting
- for (JournalTransaction newTransaction : localCompactor.getNewTransactions().values()) {
+ localCompactor.getNewTransactions().forEach((id, newTransaction) -> {
if (logger.isTraceEnabled()) {
logger.trace("Merging pending transaction " + newTransaction + " after compacting the journal");
}
@@ -1579,7 +1577,7 @@ public class JournalImpl extends JournalBase implements TestableJournal, Journal
} else {
ActiveMQJournalLogger.LOGGER.compactMergeError(newTransaction.getId());
}
- }
+ });
} finally {
journalLock.writeLock().unlock();
}
diff --git a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalRecordProvider.java b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalRecordProvider.java
index 6c5107a752..c9c92f4407 100644
--- a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalRecordProvider.java
+++ b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalRecordProvider.java
@@ -16,7 +16,7 @@
*/
package org.apache.activemq.artemis.core.journal.impl;
-import java.util.Map;
+import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashMap;
/**
* This is an interface used only internally.
@@ -29,5 +29,5 @@ public interface JournalRecordProvider {
JournalCompactor getCompactor();
- Map getRecords();
+ ConcurrentLongHashMap getRecords();
}
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/jms/ServerJMSMapMessage.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/jms/ServerJMSMapMessage.java
index f72239e27e..c904944b6f 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/jms/ServerJMSMapMessage.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/jms/ServerJMSMapMessage.java
@@ -28,7 +28,7 @@ import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException;
import org.apache.activemq.artemis.api.core.ICoreMessage;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import static org.apache.activemq.artemis.reader.MapMessageUtil.readBodyMap;
import static org.apache.activemq.artemis.reader.MapMessageUtil.writeBodyMap;
diff --git a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java
index 9800be5ee4..bd180b64c1 100644
--- a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java
+++ b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java
@@ -28,8 +28,8 @@ import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.core.server.impl.ServerSessionImpl;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.UUIDGenerator;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
/**
* MQTTConnectionMananager is responsible for handle Connect and Disconnect packets and any resulting behaviour of these
diff --git a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTRetainMessageManager.java b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTRetainMessageManager.java
index d0a3c070c3..a7381ea8df 100644
--- a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTRetainMessageManager.java
+++ b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTRetainMessageManager.java
@@ -25,7 +25,7 @@ import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.RoutingContext;
import org.apache.activemq.artemis.core.server.impl.RoutingContextImpl;
import org.apache.activemq.artemis.core.transaction.Transaction;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
public class MQTTRetainMessageManager {
diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java
index 60876b9519..c63d26611e 100644
--- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java
+++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java
@@ -77,8 +77,8 @@ import org.apache.activemq.artemis.spi.core.protocol.AbstractRemotingConnection;
import org.apache.activemq.artemis.spi.core.protocol.ConnectionEntry;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.UUIDGenerator;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQMessage;
import org.apache.activemq.command.ActiveMQTempQueue;
diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireMessageConverter.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireMessageConverter.java
index f578ac808c..dd7879c9b0 100644
--- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireMessageConverter.java
+++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireMessageConverter.java
@@ -44,8 +44,8 @@ import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.reader.MessageUtil;
import org.apache.activemq.artemis.spi.core.protocol.MessageConverter;
import org.apache.activemq.artemis.utils.DataConstants;
-import org.apache.activemq.artemis.utils.TypedProperties;
import org.apache.activemq.artemis.utils.UUIDGenerator;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.apache.activemq.command.ActiveMQBytesMessage;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQMapMessage;
diff --git a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAConnectionManager.java b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAConnectionManager.java
index f895b59f09..bfdd0c9d49 100644
--- a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAConnectionManager.java
+++ b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAConnectionManager.java
@@ -22,7 +22,7 @@ import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionFactory;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
/**
* The connection manager used in non-managed environments.
diff --git a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/recovery/RecoveryManager.java b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/recovery/RecoveryManager.java
index 0e72780ff3..0abde971d4 100644
--- a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/recovery/RecoveryManager.java
+++ b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/recovery/RecoveryManager.java
@@ -25,7 +25,7 @@ import org.apache.activemq.artemis.ra.ActiveMQRALogger;
import org.apache.activemq.artemis.service.extensions.xa.recovery.ActiveMQRegistry;
import org.apache.activemq.artemis.service.extensions.xa.recovery.ActiveMQRegistryImpl;
import org.apache.activemq.artemis.service.extensions.xa.recovery.XARecoveryConfig;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
public final class RecoveryManager {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
index ad906272d4..faa25cca37 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
@@ -48,6 +48,7 @@ import java.util.stream.Collectors;
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.ActiveMQAddressDoesNotExistException;
import org.apache.activemq.artemis.api.core.ActiveMQException;
+import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl;
@@ -84,7 +85,6 @@ import org.apache.activemq.artemis.core.server.Consumer;
import org.apache.activemq.artemis.core.server.DivertConfigurationRoutingType;
import org.apache.activemq.artemis.core.server.JournalType;
import org.apache.activemq.artemis.core.server.Queue;
-import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.ServerConsumer;
import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.core.server.cluster.ClusterConnection;
@@ -107,7 +107,7 @@ import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.utils.JsonLoader;
import org.apache.activemq.artemis.utils.ListUtil;
import org.apache.activemq.artemis.utils.SecurityFormatter;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
public class ActiveMQServerControlImpl extends AbstractControl implements ActiveMQServerControl, NotificationEmitter, org.apache.activemq.artemis.core.server.management.NotificationListener {
// Constants -----------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/QueueControlImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/QueueControlImpl.java
index 6ed4f5b345..0297ba5f49 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/QueueControlImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/QueueControlImpl.java
@@ -59,7 +59,7 @@ import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.utils.Base64;
import org.apache.activemq.artemis.utils.JsonLoader;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
public class QueueControlImpl extends AbstractControl implements QueueControl {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PageIterator.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PageIterator.java
index af6ed4021d..173213361c 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PageIterator.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PageIterator.java
@@ -17,7 +17,7 @@
package org.apache.activemq.artemis.core.paging.cursor;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
public interface PageIterator extends LinkedListIterator {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PageSubscription.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PageSubscription.java
index 6e569c1d5e..93e2a8439e 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PageSubscription.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PageSubscription.java
@@ -23,7 +23,7 @@ import org.apache.activemq.artemis.core.paging.PagingStore;
import org.apache.activemq.artemis.core.paging.impl.Page;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.transaction.Transaction;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
public interface PageSubscription {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/impl/PageSubscriptionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/impl/PageSubscriptionImpl.java
index ab10eb470f..f346dc04e8 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/impl/PageSubscriptionImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/impl/PageSubscriptionImpl.java
@@ -55,8 +55,8 @@ import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.core.transaction.TransactionOperationAbstract;
import org.apache.activemq.artemis.core.transaction.TransactionPropertyIndexes;
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.FutureLatch;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;
final class PageSubscriptionImpl implements PageSubscription {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/Page.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/Page.java
index 7d21316392..38732929de 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/Page.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/Page.java
@@ -35,8 +35,8 @@ import org.apache.activemq.artemis.core.persistence.StorageManager;
import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.LargeServerMessage;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.DataConstants;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;
public final class Page implements Comparable {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/PagingManagerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/PagingManagerImpl.java
index e036c16101..44e806742f 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/PagingManagerImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/PagingManagerImpl.java
@@ -37,7 +37,7 @@ import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.files.FileStoreMonitor;
import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;
public final class PagingManagerImpl implements PagingManager {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/LargeServerMessageImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/LargeServerMessageImpl.java
index 7d652c92f2..5ebcb568e4 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/LargeServerMessageImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/LargeServerMessageImpl.java
@@ -30,7 +30,7 @@ import org.apache.activemq.artemis.core.message.impl.CoreMessage;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.LargeServerMessage;
import org.apache.activemq.artemis.utils.DataConstants;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
public final class LargeServerMessageImpl extends CoreMessage implements LargeServerMessage {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java
index a927768479..4627325d4e 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java
@@ -82,8 +82,8 @@ import org.apache.activemq.artemis.core.transaction.TransactionOperation;
import org.apache.activemq.artemis.core.transaction.TransactionOperationAbstract;
import org.apache.activemq.artemis.core.transaction.TransactionPropertyIndexes;
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
-import org.apache.activemq.artemis.utils.TypedProperties;
import org.apache.activemq.artemis.utils.UUIDGenerator;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/invm/InVMAcceptor.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/invm/InVMAcceptor.java
index 398baa4b2f..5cae1e51f0 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/invm/InVMAcceptor.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/invm/InVMAcceptor.java
@@ -39,7 +39,7 @@ import org.apache.activemq.artemis.spi.core.remoting.ServerConnectionLifeCycleLi
import org.apache.activemq.artemis.utils.ConfigurationHelper;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.OrderedExecutorFactory;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
public final class InVMAcceptor extends AbstractAcceptor {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java
index 0f714c269f..fa2723c5f8 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java
@@ -82,7 +82,7 @@ import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.activemq.artemis.spi.core.remoting.ServerConnectionLifeCycleListener;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.ConfigurationHelper;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/replication/ReplicationEndpoint.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/replication/ReplicationEndpoint.java
index 4bf2726adf..6f899f33cc 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/replication/ReplicationEndpoint.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/replication/ReplicationEndpoint.java
@@ -371,7 +371,7 @@ public final class ReplicationEndpoint implements ChannelHandler, ActiveMQCompon
* @throws Exception
*/
private void handleReplicationSynchronization(ReplicationSyncFileMessage msg) throws Exception {
- Long id = Long.valueOf(msg.getId());
+ long id = msg.getId();
byte[] data = msg.getData();
SequentialFile channel1;
switch (msg.getFileType()) {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
index e6c8e4e80c..2f5f0d5c9a 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
@@ -36,8 +36,8 @@ import org.apache.activemq.artemis.core.settings.HierarchicalRepositoryChangeLis
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager2;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager3;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/Queue.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/Queue.java
index d7b70a374f..340463926d 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/Queue.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/Queue.java
@@ -29,8 +29,8 @@ import org.apache.activemq.artemis.core.filter.Filter;
import org.apache.activemq.artemis.core.paging.cursor.PageSubscription;
import org.apache.activemq.artemis.core.server.impl.AckReason;
import org.apache.activemq.artemis.core.transaction.Transaction;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
import org.apache.activemq.artemis.utils.ReferenceCounter;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
public interface Queue extends Bindable {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/ClusterManager.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/ClusterManager.java
index 70edb68aa4..a3f9a05ca4 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/ClusterManager.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/ClusterManager.java
@@ -62,9 +62,9 @@ import org.apache.activemq.artemis.core.server.impl.Activation;
import org.apache.activemq.artemis.core.server.management.ManagementService;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.Acceptor;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.FutureLatch;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/BridgeImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/BridgeImpl.java
index c1a0ccc815..1e5a92bb76 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/BridgeImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/BridgeImpl.java
@@ -61,8 +61,8 @@ import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
import org.apache.activemq.artemis.utils.FutureLatch;
import org.apache.activemq.artemis.utils.ReusableLatch;
-import org.apache.activemq.artemis.utils.TypedProperties;
import org.apache.activemq.artemis.utils.UUID;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/BroadcastGroupImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/BroadcastGroupImpl.java
index 4700b6de65..e216a63ecb 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/BroadcastGroupImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/BroadcastGroupImpl.java
@@ -34,8 +34,8 @@ import org.apache.activemq.artemis.core.server.NodeManager;
import org.apache.activemq.artemis.core.server.cluster.BroadcastGroup;
import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.core.server.management.NotificationService;
-import org.apache.activemq.artemis.utils.TypedProperties;
import org.apache.activemq.artemis.utils.UUIDGenerator;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/ClusterConnectionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/ClusterConnectionImpl.java
index a4dbc24a1b..d7fcf29b73 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/ClusterConnectionImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/impl/ClusterConnectionImpl.java
@@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration;
import org.apache.activemq.artemis.api.core.Pair;
+import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
@@ -52,7 +53,6 @@ import org.apache.activemq.artemis.core.postoffice.impl.PostOfficeImpl;
import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
-import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.NodeManager;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.cluster.ActiveMQServerSideProtocolManagerFactory;
@@ -70,7 +70,7 @@ import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.FutureLatch;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
public final class ClusterConnectionImpl implements ClusterConnection, AfterConnectInternalListener {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/GroupHandlingAbstract.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/GroupHandlingAbstract.java
index b68b59e89b..4f48eb705b 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/GroupHandlingAbstract.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/GroupHandlingAbstract.java
@@ -30,7 +30,7 @@ import org.apache.activemq.artemis.core.server.group.GroupingHandler;
import org.apache.activemq.artemis.core.server.group.UnproposalListener;
import org.apache.activemq.artemis.core.server.management.ManagementService;
import org.apache.activemq.artemis.core.server.management.Notification;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
public abstract class GroupHandlingAbstract implements GroupingHandler {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/LocalGroupingHandler.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/LocalGroupingHandler.java
index aa707f71d1..127eaf290d 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/LocalGroupingHandler.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/LocalGroupingHandler.java
@@ -40,7 +40,7 @@ import org.apache.activemq.artemis.core.server.management.ManagementService;
import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.utils.ConcurrentUtil;
import org.apache.activemq.artemis.utils.ExecutorFactory;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/RemoteGroupingHandler.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/RemoteGroupingHandler.java
index 058e897cd9..bd1d931585 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/RemoteGroupingHandler.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/group/impl/RemoteGroupingHandler.java
@@ -34,9 +34,9 @@ import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.management.ManagementService;
import org.apache.activemq.artemis.core.server.management.Notification;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.ExecutorFactory;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
/**
* A remote Grouping handler.
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
index 57ac7bb5e6..71c7c71a7b 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
@@ -16,6 +16,8 @@
*/
package org.apache.activemq.artemis.core.server.impl;
+import javax.management.MBeanServer;
+import javax.security.cert.X509Certificate;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
@@ -46,9 +48,6 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-import javax.management.MBeanServer;
-import javax.security.cert.X509Certificate;
-
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.ActiveMQDeleteAddressException;
import org.apache.activemq.artemis.api.core.Pair;
@@ -165,13 +164,13 @@ import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.ActiveMQThreadPoolExecutor;
import org.apache.activemq.artemis.utils.CertificateUtil;
import org.apache.activemq.artemis.utils.CompositeAddress;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.OrderedExecutorFactory;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.apache.activemq.artemis.utils.SecurityFormatter;
import org.apache.activemq.artemis.utils.TimeUtils;
import org.apache.activemq.artemis.utils.VersionLoader;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java
index 8a0cda04a9..002e511bed 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java
@@ -84,15 +84,15 @@ 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.TransactionImpl;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.Env;
import org.apache.activemq.artemis.utils.FutureLatch;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
-import org.apache.activemq.artemis.utils.PriorityLinkedList;
-import org.apache.activemq.artemis.utils.PriorityLinkedListImpl;
import org.apache.activemq.artemis.utils.ReferenceCounter;
import org.apache.activemq.artemis.utils.ReusableLatch;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.PriorityLinkedList;
+import org.apache.activemq.artemis.utils.collections.PriorityLinkedListImpl;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ScaleDownHandler.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ScaleDownHandler.java
index bf0ed0bc40..e921cb9946 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ScaleDownHandler.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ScaleDownHandler.java
@@ -60,7 +60,7 @@ import org.apache.activemq.artemis.core.transaction.ResourceManager;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.core.transaction.TransactionOperation;
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.jboss.logging.Logger;
public class ScaleDownHandler {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerConsumerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerConsumerImpl.java
index af8524d198..efddf73730 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerConsumerImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerConsumerImpl.java
@@ -59,8 +59,8 @@ import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
import org.apache.activemq.artemis.spi.core.protocol.SessionCallback;
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
import org.apache.activemq.artemis.utils.FutureLatch;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
/**
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java
index 724584313a..83ff64885d 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java
@@ -16,8 +16,10 @@
*/
package org.apache.activemq.artemis.core.server.impl;
-import static org.apache.activemq.artemis.api.core.JsonUtil.nullSafe;
-
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObjectBuilder;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.Xid;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -29,11 +31,6 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
-import javax.json.JsonArrayBuilder;
-import javax.json.JsonObjectBuilder;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.Xid;
-
import org.apache.activemq.artemis.Closeable;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQIOErrorException;
@@ -89,9 +86,11 @@ import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.protocol.SessionCallback;
import org.apache.activemq.artemis.utils.JsonLoader;
import org.apache.activemq.artemis.utils.PrefixUtil;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
+import static org.apache.activemq.artemis.api.core.JsonUtil.nullSafe;
+
/**
* Server side Session implementation
*/
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/impl/ManagementServiceImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/impl/ManagementServiceImpl.java
index f45aea7c5e..54be380202 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/impl/ManagementServiceImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/impl/ManagementServiceImpl.java
@@ -86,8 +86,8 @@ import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.core.transaction.ResourceManager;
import org.apache.activemq.artemis.spi.core.remoting.Acceptor;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
-import org.apache.activemq.artemis.utils.TypedProperties;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.TypedProperties;
import org.jboss.logging.Logger;
public class ManagementServiceImpl implements ManagementService {
diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/list/PriorityLinkedListTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/list/PriorityLinkedListTest.java
index d464410eef..d26868ca54 100644
--- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/list/PriorityLinkedListTest.java
+++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/list/PriorityLinkedListTest.java
@@ -16,8 +16,8 @@
*/
package org.apache.activemq.artemis.core.list;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
-import org.apache.activemq.artemis.utils.PriorityLinkedListImpl;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.PriorityLinkedListImpl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/group/impl/ClusteredResetMockTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/group/impl/ClusteredResetMockTest.java
index 2f18c21f6d..6a2dd15f01 100644
--- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/group/impl/ClusteredResetMockTest.java
+++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/group/impl/ClusteredResetMockTest.java
@@ -58,8 +58,8 @@ import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.core.transaction.ResourceManager;
import org.apache.activemq.artemis.spi.core.remoting.Acceptor;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.ReusableLatch;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.junit.Assert;
import org.junit.Test;
diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/impl/ScheduledDeliveryHandlerTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/impl/ScheduledDeliveryHandlerTest.java
index 5cea833d0d..6b5eb9abe1 100644
--- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/impl/ScheduledDeliveryHandlerTest.java
+++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/impl/ScheduledDeliveryHandlerTest.java
@@ -47,10 +47,10 @@ import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.RoutingContext;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.apache.activemq.artemis.utils.ReferenceCounter;
import org.apache.activemq.artemis.utils.UUID;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.junit.Assert;
import org.junit.Test;
diff --git a/etc/findbugs-exclude.xml b/etc/findbugs-exclude.xml
index 8ec9284699..147a8e0309 100644
--- a/etc/findbugs-exclude.xml
+++ b/etc/findbugs-exclude.xml
@@ -91,7 +91,7 @@ under the License.
so methods are passed null arguments to trigger the exact same exceptions.
-->
-
+
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/ConsumerTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/ConsumerTest.java
index 28200cf981..3b2c272cb0 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/ConsumerTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/ConsumerTest.java
@@ -59,7 +59,7 @@ import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.utils.ByteUtil;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.apache.qpid.jms.JmsConnectionFactory;
import org.junit.Assert;
import org.junit.Before;
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/SlowConsumerTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/SlowConsumerTest.java
index c81c24c3dd..7552caa9b7 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/SlowConsumerTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/SlowConsumerTest.java
@@ -27,6 +27,7 @@ import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.activemq.artemis.api.core.ActiveMQObjectClosedException;
+import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
@@ -39,14 +40,13 @@ import org.apache.activemq.artemis.api.core.management.CoreNotificationType;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
-import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.core.settings.impl.SlowConsumerPolicy;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.apache.activemq.artemis.utils.TimeUtils;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Before;
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/bridge/BridgeTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/bridge/BridgeTest.java
index b0f03d41d8..2084796c40 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/bridge/BridgeTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/bridge/BridgeTest.java
@@ -38,7 +38,7 @@ import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.Interceptor;
import org.apache.activemq.artemis.api.core.Message;
-
+import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
@@ -68,7 +68,6 @@ import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.Queue;
-import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.cluster.Bridge;
import org.apache.activemq.artemis.core.server.cluster.Transformer;
import org.apache.activemq.artemis.core.server.cluster.impl.BridgeImpl;
@@ -78,9 +77,9 @@ import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.tests.integration.IntegrationTestLogger;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.apache.activemq.artemis.utils.ReusableLatch;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/imported/MQTTFQQNTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/imported/MQTTFQQNTest.java
index a1fa0071b3..4f0b22951f 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/imported/MQTTFQQNTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/imported/MQTTFQQNTest.java
@@ -27,7 +27,7 @@ import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.core.protocol.mqtt.MQTTConnectionManager;
import org.apache.activemq.artemis.core.protocol.mqtt.MQTTSession;
import org.apache.activemq.artemis.core.server.QueueQueryResult;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/imported/MQTTTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/imported/MQTTTest.java
index 28b7984767..09477f36fa 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/imported/MQTTTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/imported/MQTTTest.java
@@ -45,7 +45,7 @@ import org.apache.activemq.artemis.core.protocol.mqtt.MQTTUtil;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.tests.util.Wait;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.fusesource.mqtt.client.BlockingConnection;
import org.fusesource.mqtt.client.MQTT;
import org.fusesource.mqtt.client.MQTTException;
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/paging/PagingSendTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/paging/PagingSendTest.java
index 3675416e0a..530877bfb4 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/paging/PagingSendTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/paging/PagingSendTest.java
@@ -40,7 +40,7 @@ import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/MqttPluginTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/MqttPluginTest.java
index 5e7f12706f..660df34f3e 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/MqttPluginTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/MqttPluginTest.java
@@ -16,6 +16,22 @@
*/
package org.apache.activemq.artemis.tests.integration.plugin;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.activemq.artemis.core.protocol.mqtt.MQTTConnectionManager;
+import org.apache.activemq.artemis.core.protocol.mqtt.MQTTSession;
+import org.apache.activemq.artemis.tests.integration.mqtt.imported.MQTTClientProvider;
+import org.apache.activemq.artemis.tests.integration.mqtt.imported.MQTTTestSupport;
+import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
+import org.junit.Before;
+import org.junit.Test;
+
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.AFTER_CLOSE_CONSUMER;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.AFTER_CLOSE_SESSION;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.AFTER_CREATE_CONNECTION;
@@ -39,22 +55,6 @@ import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledV
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.MESSAGE_ACKED;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.MESSAGE_EXPIRED;
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.activemq.artemis.core.protocol.mqtt.MQTTConnectionManager;
-import org.apache.activemq.artemis.core.protocol.mqtt.MQTTSession;
-import org.apache.activemq.artemis.tests.integration.mqtt.imported.MQTTClientProvider;
-import org.apache.activemq.artemis.tests.integration.mqtt.imported.MQTTTestSupport;
-import org.apache.activemq.artemis.utils.ConcurrentHashSet;
-import org.junit.Before;
-import org.junit.Test;
-
public class MqttPluginTest extends MQTTTestSupport {
diff --git a/tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/journal/JournalCleanupCompactStressTest.java b/tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/journal/JournalCleanupCompactStressTest.java
index c08f1dddd6..7493949999 100644
--- a/tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/journal/JournalCleanupCompactStressTest.java
+++ b/tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/journal/JournalCleanupCompactStressTest.java
@@ -18,7 +18,6 @@ package org.apache.activemq.artemis.tests.stress.journal;
import java.io.File;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -238,12 +237,15 @@ public class JournalCleanupCompactStressTest extends ActiveMQTestBase {
reloadJournal();
- Collection records = journal.getRecords().keySet();
-
System.out.println("Deleting everything!");
- for (Long delInfo : records) {
- journal.appendDeleteRecord(delInfo, false);
- }
+
+ journal.getRecords().forEach((id, record) -> {
+ try {
+ journal.appendDeleteRecord(id, false);
+ } catch (Exception e) {
+ new RuntimeException(e);
+ }
+ });
journal.forceMoveNextFile();
diff --git a/tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/paging/PageCursorStressTest.java b/tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/paging/PageCursorStressTest.java
index 61c8d30c99..b6afd2c61c 100644
--- a/tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/paging/PageCursorStressTest.java
+++ b/tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/paging/PageCursorStressTest.java
@@ -48,8 +48,8 @@ import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
import org.apache.activemq.artemis.tests.unit.core.postoffice.impl.FakeQueue;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
import org.apache.activemq.artemis.utils.RandomUtil;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/FakeQueue.java b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/FakeQueue.java
index 66bdddbdf0..efb9e7706f 100644
--- a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/FakeQueue.java
+++ b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/FakeQueue.java
@@ -22,8 +22,8 @@ import java.util.Set;
import java.util.concurrent.Executor;
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
-
import org.apache.activemq.artemis.api.core.Message;
+import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.filter.Filter;
import org.apache.activemq.artemis.core.paging.cursor.PageSubscription;
@@ -31,11 +31,10 @@ import org.apache.activemq.artemis.core.server.Consumer;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.RoutingContext;
-import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.impl.AckReason;
import org.apache.activemq.artemis.core.transaction.Transaction;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
import org.apache.activemq.artemis.utils.ReferenceCounter;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
public class FakeQueue implements Queue {
diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/server/impl/QueueImplTest.java b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/server/impl/QueueImplTest.java
index 0a08eb6078..b64ff03411 100644
--- a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/server/impl/QueueImplTest.java
+++ b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/server/impl/QueueImplTest.java
@@ -49,7 +49,7 @@ import org.apache.activemq.artemis.tests.unit.core.server.impl.fakes.FakePostOff
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.FutureLatch;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/LinkedListTest.java b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/LinkedListTest.java
index 1b7010ed69..e7c3eba29e 100644
--- a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/LinkedListTest.java
+++ b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/LinkedListTest.java
@@ -23,8 +23,8 @@ import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
-import org.apache.activemq.artemis.utils.LinkedListImpl;
-import org.apache.activemq.artemis.utils.LinkedListIterator;
+import org.apache.activemq.artemis.utils.collections.LinkedListImpl;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.junit.Before;
import org.junit.Test;