package org.deuce.transaction.estmmvcc; import org.deuce.transaction.estmmvcc.field.WriteFieldAccess; import org.deuce.transaction.estmmvcc.field.ReadFieldAccess.Field.Type; import org.deuce.transaction.estmmvcc.Context.LockTable; import org.deuce.transform.Exclude; import org.deuce.trove.THashMap; /** * @author Vincent Gramoli */ @Exclude final public class WriteSet { private static final int DEFAULT_CAPACITY = 16; final private THashMap<Integer, WriteFieldAccess> entries; private boolean empty = true; public WriteSet(int initialCapacity) { entries = new THashMap<Integer, WriteFieldAccess>(initialCapacity); } public WriteSet() { this(DEFAULT_CAPACITY); } public int size() { return entries.size(); } public void clear() { entries.clear(); empty = true; } public boolean isEmpty() { return empty; } /** * Indicates whether the given field corresponds * to an existing write entry of the read set * * @param hash the identifier of the field * @param obj its object * @param field the protected field * @return the value if owned, null otherwise */ public Object getValue(int hash, Object obj, long field) { WriteFieldAccess w = this.get(hash, obj, field); return (w != null) ? w.getValue() : null; } /** * Returns the corresponding write entry * * @param hash the identifier of the field * @param obj its object * @param field the protected field * @return the value if owned, null otherwise */ public WriteFieldAccess get(int hash, Object obj, long field) { // Return value from existing entry WriteFieldAccess w = entries.get(hash); while (w != null) { // Check if we have already written that field if (w.getField() == field && w.getReference() == obj) return w; w = w.getNext(); } return null; } public void append(int hash, Object obj, long field, Object value, Type type) { // Append to existing entry WriteFieldAccess w = entries.get(hash); while (w != null) { // Check if we have already written that field if (w.getField() == field && w.getReference() == obj) { // Update written value w.setValue(value); return; } WriteFieldAccess next = w.getNext(); if (next == null) { // We did not write this field (we must add it to write set) w.setNext(new WriteFieldAccess(obj, field, type, value, hash, 0)); return; } w = next; } } public void add(int hash, Object obj, long field, Object value, Type type, int timestamp) { // Add new entry entries.put(hash, new WriteFieldAccess(obj, field, type, value, hash, timestamp)); empty = false; } public void commit(int timestamp, int id) { // Write values and release locks for (WriteFieldAccess w : entries.values()) { int hash = w.getHash(); assert w.getLock() >= 0; do { w.writeOldField(hash, id); w.writeField(); w = w.getNext(); } while (w != null); LockTable.setAndReleaseLock(hash, timestamp); } } public void rollback() { // Release locks for (WriteFieldAccess w : entries.values()) { assert w.getLock() >= 0; //w.resetOldField(); LockTable.setAndReleaseLock(w.getHash(), w.getLock()); } } }