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: + *

    + *
  1. No boxing/unboxing from long -> Long + *
  2. 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;