/** * Makes a deep copy of a {@link State} map, optionally thread-safe. * * @param threadSafe if {@code true}, then thread-safe datastructures are used */ public static State deepCopy(State state, boolean threadSafe) { State copy = new State(state.size(), threadSafe); for (Entry<String, Serializable> en : state.entrySet()) { copy.put(en.getKey(), deepCopy(en.getValue(), threadSafe)); } return copy; }
@Override public State readPartialState(String id, Collection<String> keys) { if (id == null) { return null; } State state = states.get(id); if (state != null) { if (keys != null && !keys.isEmpty()) { State partialState = new State(); for (String key : keys) { Serializable value = state.get(key); if (value != null) { partialState.put(key, value); } } state = partialState; } if (log.isTraceEnabled()) { log.trace("Mem: READ " + id + ": " + state); } } return state; }
protected String getIdFromState(State state) { String idFieldName = getPrefixedIdField(); if (!state.containsKey(idFieldName)) { idFieldName = getIdField(); } return String.valueOf(state.get(idFieldName)); }
/** * Compares two {@link State}s. */ public static boolean equalsStrict(State a, State b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.size() != b.size()) { return false; } if (!a.keySet().equals(b.keySet())) { return false; } for (Entry<String, Serializable> en : a.entrySet()) { String key = en.getKey(); Serializable va = en.getValue(); Serializable vb = b.get(key); if (!equalsStrict(va, vb)) { return false; } } return true; }
@Override public Object[] getArray(String name) { Serializable object = get(name); if (object == null) { return null; } else if (object instanceof Object[]) { return (Object[]) object; } else { // data migration not done in database, return an array anyway return new Object[] { object }; } }
@Override public synchronized Lock setLock(String id, Lock lock) { State state = states.get(id); if (state == null) { // document not found throw new DocumentNotFoundException(id); } String owner = (String) state.get(KEY_LOCK_OWNER); if (owner != null) { // return old lock Calendar created = (Calendar) state.get(KEY_LOCK_CREATED); return new Lock(owner, created); } state.put(KEY_LOCK_OWNER, lock.getOwner()); state.put(KEY_LOCK_CREATED, lock.getCreated()); return null; }
b = State.EMPTY; for (Entry<String, Serializable> en : a.entrySet()) { Serializable va = en.getValue(); if (va == null) { Serializable vb = b.get(key); if (!equalsLoose(va, vb)) { return false; for (Entry<String, Serializable> en : b.entrySet()) { String key = en.getKey(); Serializable va = a.get(key); if (va != null) {
/** * Changes the deltas stored into actual full values. * * @since 6.0 */ public static void resetDeltas(State state) { if (Boolean.parseBoolean(Framework.getProperty(DISABLED_DELTA_PROP, "false"))) { return; } for (Entry<String, Serializable> en : state.entrySet()) { Serializable value = en.getValue(); if (value instanceof State) { resetDeltas((State) value); } else if (value instanceof Delta) { state.put(en.getKey(), ((Delta) value).getFullValue()); } } }
public State bsonToState(Document doc) { if (doc == null) { return null; } State state = new State(doc.keySet().size()); for (String key : doc.keySet()) { if (idKey == null && MONGODB_ID.equals(key)) { // skip native id if it's not mapped to something continue; } state.put(bsonToKey(key), bsonToValue(doc.get(key))); } return state; }
public Document stateToBson(State state) { Document doc = new Document(); for (Entry<String, Serializable> en : state.entrySet()) { Object val = valueToBson(en.getValue()); if (val != null) { doc.put(keyToBson(en.getKey()), val); } } return doc; }
@Override public void setArray(String name, Object[] value) { put(name, value); }
/** * Constructor for a given default size, optionally thread-safe. * * @param threadSafe if {@code true}, then a {@link ConcurrentHashMap} is used */ public State(int size, boolean threadSafe) { if (threadSafe) { map = new ConcurrentHashMap<String, Serializable>(initialCapacity(size)); } else { if (size > ARRAY_MAX) { map = new HashMap<>(initialCapacity(size)); } else { keys = new ArrayList<String>(size); values = new ArrayList<Serializable>(size); } } }
protected static boolean hasAncestor(State state, String id) { Object[] array = (Object[]) state.get(KEY_ANCESTOR_IDS); return array == null ? false : Arrays.asList(array).contains(id); }
@Override public synchronized Lock removeLock(String id, String owner) { State state = states.get(id); if (state == null) { // document not found throw new DocumentNotFoundException(id); } String oldOwner = (String) state.get(KEY_LOCK_OWNER); if (oldOwner == null) { // no previous lock return null; } Calendar oldCreated = (Calendar) state.get(KEY_LOCK_CREATED); if (!LockManager.canLockBeRemoved(oldOwner, owner)) { // existing mismatched lock, flag failure return new Lock(oldOwner, oldCreated, true); } // remove lock state.put(KEY_LOCK_OWNER, null); state.put(KEY_LOCK_CREATED, null); // return old lock return new Lock(oldOwner, oldCreated); }
for (Entry<String, Serializable> es : state.entrySet()) { fieldMap.put(es.getKey(), es.getValue());
@Override public void setSingle(String name, Object value) { put(name, (Serializable) value); }
protected void putEvenIfNull(String key, Serializable value) { if (map != null) { map.put(key, value); } else { int i = keys.indexOf(key); if (i >= 0) { // existing key values.set(i, value); } else { // new key if (keys.size() < ARRAY_MAX) { keys.add(key); values.add(value); } else { // upgrade to a full HashMap map = new HashMap<>(initialCapacity(keys.size() + 1)); for (int j = 0; j < keys.size(); j++) { map.put(keys.get(j), values.get(j)); } map.put(key, value); keys = null; values = null; } } } }
Serializable old = state.get(key); if (old == null) { old = new State(true); // thread-safe state.put(key, old); state.put(key, applyDiff(state.get(key), (ListDiff) value)); } else if (value instanceof Delta) { Delta delta = (Delta) value; Number oldValue = (Number) state.get(key); Number newValue; if (oldValue == null) { newValue = delta.add(oldValue); state.put(key, newValue); } else { state.put(key, StateHelper.deepCopy(value, true)); // thread-safe