You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by oz...@apache.org on 2004/05/17 15:26:06 UTC
cvs commit: jakarta-commons-sandbox/transaction/src/java/org/apache/commons/transaction/memory TransactionalMapWrapper.java TxLRUObjectCache.java ByteSizeLimitedObjectCache.java
ozeigermann 2004/05/17 06:26:06
Added: transaction/src/java/org/apache/commons/transaction/memory
TransactionalMapWrapper.java
Removed: transaction/src/java/org/apache/commons/transaction/memory
TxLRUObjectCache.java
ByteSizeLimitedObjectCache.java
Log:
Replaced working base with transactional map wrapper
Revision Changes Path
1.1 jakarta-commons-sandbox/transaction/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java
Index: TransactionalMapWrapper.java
===================================================================
/*
* $Header: /home/cvs/jakarta-commons-sandbox/transaction/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java,v 1.1 2004/05/17 13:26:06 ozeigermann Exp $
* $Revision: 1.1 $
* $Date: 2004/05/17 13:26:06 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed 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.commons.transaction.memory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Wrapper that adds transactional control to all kinds of maps that implement the {@link Map} interface.
*
* @author <a href="mailto:ozeigermann@apache.org">Oliver Zeigermann</a>
* @version $Revision: 1.1 $
*/
public class TransactionalMapWrapper implements Map {
protected Map wrapped;
protected Map txBranches = new HashMap();
protected ThreadLocal activeTx = new ThreadLocal();
protected boolean includeBranch = true;
public TransactionalMapWrapper(Map wrapped) {
this.wrapped = wrapped;
}
public synchronized void startTransaction() {
if (getActiveTx() != null) {
throw new IllegalStateException(
"Active thread " + Thread.currentThread() + " already associated with a transaction!");
}
activeTx.set(new TxContext());
}
public synchronized void rollbackTransaction() {
TxContext txContext = getActiveTx();
if (txContext == null) {
throw new IllegalStateException(
"Active thread " + Thread.currentThread() + " not associated with a transaction!");
}
// simply forget about tx
activeTx.set(null);
}
public synchronized void commitTransaction() {
TxContext txContext = getActiveTx();
if (txContext == null) {
throw new IllegalStateException(
"Active thread " + Thread.currentThread() + " not associated with a transaction!");
}
for (Iterator it = txContext.getChanges().entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
wrapped.put(entry.getKey(), entry.getValue());
}
for (Iterator it = txContext.getDeletes().iterator(); it.hasNext();) {
Object key = it.next();
wrapped.remove(key);
}
// now forget about tx
activeTx.set(null);
}
//
// Map methods
//
public synchronized void clear() {
wrapped.clear();
activeTx.set(null);
}
public synchronized int size() {
int size = wrapped.size();
TxContext txContext = getActiveTx();
if (txContext != null) {
size += txContext.getChanges().size();
size -= txContext.deletes.size();
}
return size;
}
public synchronized boolean isEmpty() {
TxContext txContext = getActiveTx();
if (txContext != null) {
return wrapped.isEmpty();
} else {
return (size() > 0);
}
}
public synchronized boolean containsKey(Object key) {
TxContext txContext = getActiveTx();
if (txContext == null) {
return wrapped.containsKey(key);
} else {
return (!txContext.getDeletes().contains(key) && txContext.getChanges().containsKey(key));
}
}
public synchronized boolean containsValue(Object value) {
TxContext txContext = getActiveTx();
if (txContext == null) {
return wrapped.containsValue(value);
} else {
return values().contains(value);
}
}
public synchronized Collection values() {
TxContext txContext = getActiveTx();
if (txContext == null) {
return wrapped.values();
} else {
// XXX expensive :(
Collection values = new ArrayList();
for (Iterator it = keySet().iterator(); it.hasNext();) {
Object key = it.next();
Object value = get(key);
values.add(value);
}
return values;
}
}
public synchronized void putAll(Map map) {
TxContext txContext = getActiveTx();
if (txContext == null) {
wrapped.putAll(map);
} else {
for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
txContext.getChanges().put(entry.getKey(), entry.getValue());
txContext.getDeletes().remove(entry.getKey());
}
}
}
public synchronized Set entrySet() {
TxContext txContext = getActiveTx();
if (txContext == null) {
return wrapped.entrySet();
} else {
Set entrySet = new HashSet();
Set keySet = keySet();
// XXX expensive :(
for (Iterator it = keySet.iterator(); it.hasNext();) {
Object key = it.next();
Object value = get(key);
entrySet.add(new HashEntry(key, value));
}
return entrySet;
}
}
public synchronized Set keySet() {
Set keySet = wrapped.keySet();
TxContext txContext = getActiveTx();
if (txContext != null) {
Set deleteSet = txContext.getDeletes();
keySet.removeAll(deleteSet);
Set changeSet = txContext.getChanges().keySet();
keySet.addAll(changeSet);
}
return keySet;
}
public synchronized Object get(Object key) {
TxContext txContext = getActiveTx();
if (txContext != null) {
if (txContext.getDeletes().contains(key)) {
// reflects that entry has been deleted in this tx
return null;
}
Object changed = txContext.getChanges().get(key);
if (changed != null) {
// if object has been changed in this tx, get the local one
return changed;
}
}
// as fall back return value from global cache (if present)
return wrapped.get(key);
}
public synchronized Object remove(Object key) {
TxContext txContext = getActiveTx();
Object old = null;
if (txContext == null) {
old = wrapped.remove(key);
} else {
old = txContext.getChanges().remove(key);
txContext.getDeletes().add(key);
}
return old;
}
public synchronized Object put(Object key, Object value) {
TxContext txContext = getActiveTx();
Object old = get(key);
if (txContext == null) {
wrapped.put(key, value);
} else {
txContext.getDeletes().remove(key);
txContext.getChanges().put(key, value);
}
return old;
}
protected TxContext getActiveTx() {
return (TxContext) activeTx.get();
}
protected static class TxContext {
protected final Set deletes;
protected final Map changes;
public TxContext() {
deletes = new HashSet();
changes = new HashMap();
}
public Map getChanges() {
return changes;
}
public Set getDeletes() {
return deletes;
}
}
// mostly copied from org.apache.commons.collections.map.AbstractHashedMap
protected static class HashEntry implements Map.Entry {
/** The key */
protected Object key;
/** The value */
protected Object value;
protected HashEntry(Object key, Object value) {
this.key = key;
this.value = value;
}
public Object getKey() {
return key;
}
public Object getValue() {
return value;
}
public Object setValue(Object value) {
Object old = this.value;
this.value = value;
return old;
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Map.Entry)) {
return false;
}
Map.Entry other = (Map.Entry) obj;
return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey()))
&& (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
}
public int hashCode() {
return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode());
}
public String toString() {
return new StringBuffer().append(getKey()).append('=').append(getValue()).toString();
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org