
com.spikeify.BigMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core Show documentation
Show all versions of core Show documentation
Simple ORM for Aerospike
package com.spikeify;
import com.aerospike.client.AerospikeClient;
import com.aerospike.client.AerospikeException;
import com.aerospike.client.Key;
import com.aerospike.client.Value;
import com.aerospike.client.async.IAsyncClient;
import com.aerospike.client.large.LargeList;
import com.aerospike.client.policy.RecordExistsAction;
import com.aerospike.client.policy.WritePolicy;
import com.spikeify.annotations.AsJson;
import com.spikeify.commands.InfoFetcher;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A type-safe wrapper for a native {@link LargeList}, exposed as a Map.
*
* @param the type of keys in this map
* @param the type of values in this map
*/
public class BigMap extends BigDatatypeWrapper {
protected Type keyType;
protected Type valueType;
protected IAsyncClient asynClient;
protected WritePolicy wp;
protected Key key;
protected String binName;
/**
* Internal function - must be called before this LDT can be used.
* This function is called during a setup of mapping relation between this class and mapped field.
*
* @param client The underlying Aerospike client
* @param key The record key under which this list is saved in DB
* @param binName The bin name under which this list is saved in DB
* @param field The field in the object to which this list is assigned
*/
public void init(IAsyncClient client, Key key, String binName, Field field) {
this.binName = binName;
this.asynClient = client;
this.key = key;
this.keyType = TypeUtils.getBigMapKeyType(field);
if (keyType != null) {
Class keyClass = (Class) keyType;
if (keyClass.isAnnotationPresent(AsJson.class)) {
throw new SpikeifyError("Error: @AsJson is not supported on BigMap key type argument.");
}
}
valueType = TypeUtils.getBigMapValueType(field);
setConverterForValueType(field, valueType);
this.wp = new WritePolicy();
wp.recordExistsAction = RecordExistsAction.UPDATE;
// need to set timeout for operations with a lot of records, e.g. getAll();
wp.timeout = 10_000; // 10s
// retards from AS
inner = new LargeList((AerospikeClient) asynClient, wp, key, binName);
if (!(new InfoFetcher(client).isUDFEnabled(key.namespace))) {
throw new SpikeifyError("Error: LDT support not enabled on namespace '" + key.namespace + "'. Please add 'ldt-enabled true' to namespace section in your aerospike.conf file.");
}
try {
inner.size();
} catch (AerospikeException ae) {
if (ae.getResultCode() == 1417) {
isEmpty = true;
}
}
}
/**
* Returns true if this map contains a mapping for the specified key.
*
* @param key key whose presence in this map is to be tested
* @return if this map contains a mapping for the specified key
*/
public boolean containsKey(K key) {
try {
return inner.exists(Value.get(key));
} catch (AerospikeException ae) {
if (ae.getResultCode() == 1417) {
isEmpty = true;
}
}
return false;
}
/**
* Inserts a value into the map and associate it with provided key. If the map previously contained a mapping for
* the key, the old value is replaced by the specified value.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
*/
@SuppressWarnings("unchecked")
public void put(K key, V value) {
if (value == null) {
throw new IllegalArgumentException("Can not add 'null' to BigList.");
}
Map valMap = new HashMap<>(2);
valMap.put("key", key);
valMap.put("value", converter == null ? value : converter.fromField(value));
inner.update(Value.get(valMap));
isEmpty = false;
}
/**
* Copies all of the mappings from the specified map to this map.
* This is equivalent as calling {@link #put(Object, Object)} for each mapping of specified map.
*
* @param map mappings to be stored in this map
*/
@SuppressWarnings("unchecked")
public void putAll(Map map) {
if (map == null) {
throw new IllegalArgumentException("Can not add 'null' to BigMap.");
}
if (map.isEmpty()) {
return;
}
List values = new ArrayList<>(map.size());
int inLoop = 0;
for (Map.Entry entry : map.entrySet()) {
K key = entry.getKey();
V value = entry.getValue();
inLoop++;
Map valMap = new HashMap<>(2);
valMap.put("key", key);
valMap.put("value", converter == null ? value : converter.fromField(value));
values.add(Value.get(valMap));
if (inLoop % step == 0) {
addTransactionally(values); // add in chunks
values.clear();
}
}
if (!values.isEmpty()) {
addTransactionally(values); // add remaining chunk
}
}
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* @param key the key whose associated value is to be returned
* @return the value to which the specified key is mapped, or
* {@code null} if this map contains no mapping for the key
*/
@SuppressWarnings("unchecked")
public V get(K key) {
List found = inner.find(Value.get(key));
if (found == null || found.isEmpty()) {
return null;
}
if (found.size() > 1) {
throw new IllegalStateException("List consistency error: list should only contain one value for each index.");
}
if (converter != null) {
return (V) converter.fromProperty(((Map) found.get(0)).get("value"));
} else {
return (V) ((Map) found.get(0)).get("value");
}
}
/**
* Returns a map of all keys, values.
*
* @return A map of all keys, values.
*/
@SuppressWarnings("unchecked")
public Map getAll() {
List found = null;
try {
found = inner.scan();
} catch (AerospikeException ae) {
if (ae.getResultCode() == 1417) {
return new HashMap<>(0);
}
throw ae;
}
return toTypedResults(found);
}
/**
* Returns a range of values between from an to positions.
*
* @param from Starting position
* @param to Ending position
* @return A map of key, values between requested key positions.
*/
@SuppressWarnings("unchecked")
public Map range(K from, K to) {
Value fromValue = Value.get(from);
Value toValue = Value.get(to);
List found = null;
try {
found = inner.range(fromValue, toValue);
} catch (AerospikeException ae) {
if (ae.getResultCode() == 1417) {
return new HashMap<>(0);
}
throw ae;
}
return toTypedResults(found);
}
/**
* Returns a count of key, values from the last position.
*
* @param count maximum number of values to return
* @return A map of key, values from the last key value
*/
@SuppressWarnings("unchecked")
public Map findLast(int count) {
List found = null;
try {
found = inner.findLast(count);
} catch (AerospikeException ae) {
if (ae.getResultCode() == 1417) {
return new HashMap<>(0);
}
throw ae;
}
return toTypedResults(found);
}
/**
* Returns a count of key, values from the last position.
*
* @param count maximum number of values to return
* @return A map of key, values from the last key value
*/
@SuppressWarnings("unchecked")
public Map findFirst(int count) {
List found = null;
try {
found = inner.findFirst(count);
} catch (AerospikeException ae) {
if (ae.getResultCode() == 1417) {
return new HashMap<>(0);
}
throw ae;
}
return toTypedResults(found);
}
private Map toTypedResults(List untyped) {
if (untyped == null || untyped.isEmpty()) {
return new HashMap<>(0); // return empty list if no results
}
Map results = new HashMap<>(untyped.size());
for (Object obj : untyped) {
K key = (K) ((Map) obj).get("key");
V val = (V) ((Map) obj).get("value");
if (converter != null) {
results.put(key, (V) converter.fromProperty(val));
} else {
results.put(key, val);
}
}
return results;
}
/**
* Removes the mapping for a key from this map if it is present.
*
* @param key key whose mapping is to be removed from the map
*/
public void remove(K key) {
inner.remove(Value.get(key));
}
/**
* Removes the mappings for a list keys from this map for each mapping that is present.
*
* @param keys a list of keys whose mapping is to be removed from the map
*/
public void remove(List keys) {
// no need to use Value.get(keys) as this is already done by the underlying client
inner.remove(keys);
}
/**
* Removes all values.
*/
public void removeAll() {
// destroy LDT field...
inner.destroy();
// re-initialize
inner = new LargeList((AerospikeClient) asynClient, wp, key, binName);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy