/** * Try to set or remove the value. When updating only unchanged entries, then the value is only * changed if it was not changed after opening the map. * * @param key the key * @param value the new value (null to remove the value) * @param onlyIfUnchanged only set the value if it was not changed (by this or another * transaction) since the map was opened * @return true if the value was set */ public boolean trySet(K key, V value, boolean onlyIfUnchanged) { Object[] current = map.get(key); if (onlyIfUnchanged) { Object[] old = getArray(key, readLogId); if (!map.areValuesEqual(old, current)) { long tx = (Long) current[0]; if (tx == transaction.transactionId) { if (value == null) { // ignore removing an entry // if it was added or changed // in the same statement return true; } else if (current[2] == null) { // add an entry that was removed // in the same statement } else { return false; } } else { return false; } } } int opType; if (current == null || current[2] == null) { if (value == null) { // remove a removed value opType = Transaction.OP_SET; } else { opType = Transaction.OP_ADD; } } else { if (value == null) { opType = Transaction.OP_REMOVE; } else { opType = Transaction.OP_SET; } } Object[] newValue = {transaction.transactionId, transaction.logId, value}; if (current == null) { // a new value Object[] old = map.putIfAbsent(key, newValue); if (old == null) { transaction.log(opType, mapId, key, current); return true; } return false; } long tx = (Long) current[0]; if (tx == transaction.transactionId) { // added or updated by this transaction if (map.replace(key, current, newValue)) { transaction.log(opType, mapId, key, current); return true; } // strange, somebody overwrite the value // even thought the change was not committed return false; } // added or updated by another transaction boolean open = transaction.store.openTransactions.containsKey(tx); if (!open) { // the transaction is committed: // overwrite the value if (map.replace(key, current, newValue)) { transaction.log(opType, mapId, key, current); return true; } // somebody else was faster return false; } // the transaction is not yet committed return false; }