No effective change - format and organise imports

This commit is contained in:
Robin Bygrave
2015-08-21 18:31:55 +12:00
parent 547fa342c4
commit 394cb3854a
19 changed files with 816 additions and 821 deletions
@@ -1,7 +1,5 @@
package com.avaje.ebeaninternal.server.transaction;
import java.sql.Connection;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.api.SpiTransaction;
@@ -9,6 +7,8 @@ import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import java.sql.Connection;
/**
* AutoCommit based TransactionManager.
* <p>
@@ -17,8 +17,8 @@ import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
public class AutoCommitTransactionManager extends TransactionManager {
public AutoCommitTransactionManager(ClusterManager clusterManager, BackgroundExecutor backgroundExecutor,
ServerConfig config, BeanDescriptorManager descMgr, BootupClasses bootupClasses) {
ServerConfig config, BeanDescriptorManager descMgr, BootupClasses bootupClasses) {
super(clusterManager, backgroundExecutor, config, descMgr, bootupClasses);
}
@@ -27,10 +27,8 @@ public class AutoCommitTransactionManager extends TransactionManager {
*/
@Override
protected SpiTransaction createTransaction(boolean explicit, Connection c, long id) {
return new AutoCommitJdbcTransaction(prefix + id, explicit, c, this);
}
}
@@ -1,11 +1,5 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
@@ -13,86 +7,92 @@ import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class BeanDelta {
private final List<BeanDeltaProperty> properties;
private final BeanDescriptor<?> beanDescriptor;
private final Object id;
public BeanDelta(BeanDescriptor<?> beanDescriptor, Object id) {
this.beanDescriptor = beanDescriptor;
this.id = id;
this.properties = new ArrayList<BeanDeltaProperty>();
private final List<BeanDeltaProperty> properties;
private final BeanDescriptor<?> beanDescriptor;
private final Object id;
public BeanDelta(BeanDescriptor<?> beanDescriptor, Object id) {
this.beanDescriptor = beanDescriptor;
this.id = id;
this.properties = new ArrayList<BeanDeltaProperty>();
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
public String toString() {
return "BeanDelta[" + beanDescriptor.getName() + ":" + properties + "]";
}
public Object getId() {
return id;
}
public void add(BeanProperty beanProperty, Object value) {
this.properties.add(new BeanDeltaProperty(beanProperty, value));
}
public void add(BeanDeltaProperty propertyDelta) {
this.properties.add(propertyDelta);
}
public void apply(EntityBean bean) {
for (int i = 0; i < properties.size(); i++) {
properties.get(i).apply(bean);
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
/**
* Read and return a BeanDelta from the binary input.
*/
public static BeanDelta readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
String descriptorId = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
Object id = desc.getIdBinder().readData(dataInput);
BeanDelta bp = new BeanDelta(desc, id);
int count = dataInput.readInt();
for (int i = 0; i < count; i++) {
String propName = dataInput.readUTF();
BeanProperty beanProperty = desc.getBeanProperty(propName);
Object value = beanProperty.getScalarType().readData(dataInput);
bp.add(beanProperty, value);
}
public String toString() {
return "BeanDelta[" + beanDescriptor.getName() + ":" + properties + "]";
return bp;
}
/**
* Write this bean delta in binary message format.
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
BinaryMessage m = new BinaryMessage(50);
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANDELTA);
os.writeUTF(beanDescriptor.getDescriptorId());
beanDescriptor.getIdBinder().writeData(os, id);
os.writeInt(properties.size());
for (int i = 0; i < properties.size(); i++) {
properties.get(i).writeBinaryMessage(m);
}
public Object getId() {
return id;
}
public void add(BeanProperty beanProperty, Object value) {
this.properties.add(new BeanDeltaProperty(beanProperty, value));
}
public void add(BeanDeltaProperty propertyDelta) {
this.properties.add(propertyDelta);
}
public void apply(EntityBean bean) {
for (int i = 0; i < properties.size(); i++) {
properties.get(i).apply(bean);
}
}
/**
* Read and return a BeanDelta from the binary input.
*/
public static BeanDelta readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
String descriptorId = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
Object id = desc.getIdBinder().readData(dataInput);
BeanDelta bp = new BeanDelta(desc, id);
int count = dataInput.readInt();
for (int i = 0; i < count; i++) {
String propName = dataInput.readUTF();
BeanProperty beanProperty = desc.getBeanProperty(propName);
Object value = beanProperty.getScalarType().readData(dataInput);
bp.add(beanProperty, value);
}
return bp;
}
/**
* Write this bean delta in binary message format.
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
BinaryMessage m = new BinaryMessage(50);
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANDELTA);
os.writeUTF(beanDescriptor.getDescriptorId());
beanDescriptor.getIdBinder().writeData(os, id);
os.writeInt(properties.size());
for (int i = 0; i < properties.size(); i++) {
properties.get(i).writeBinaryMessage(m);
}
os.flush();
msgList.add(m);
}
os.flush();
msgList.add(m);
}
}
@@ -1,42 +1,42 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
public class BeanDeltaList {
private final BeanDescriptor<?> beanDescriptor;
private final List<BeanDelta> deltaBeans = new ArrayList<BeanDelta>();
private final BeanDescriptor<?> beanDescriptor;
public BeanDeltaList(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
private final List<BeanDelta> deltaBeans = new ArrayList<BeanDelta>();
public String toString() {
return deltaBeans.toString();
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
public BeanDeltaList(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
public void add(BeanDelta b) {
deltaBeans.add(b);
}
public List<BeanDelta> getDeltaBeans() {
return deltaBeans;
}
public String toString() {
return deltaBeans.toString();
}
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
for (int i = 0; i < deltaBeans.size(); i++) {
deltaBeans.get(i).writeBinaryMessage(msgList);
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
public void add(BeanDelta b) {
deltaBeans.add(b);
}
public List<BeanDelta> getDeltaBeans() {
return deltaBeans;
}
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
for (int i = 0; i < deltaBeans.size(); i++) {
deltaBeans.get(i).writeBinaryMessage(msgList);
}
}
}
@@ -1,48 +1,48 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
public class BeanDeltaMap {
private final Map<String,BeanDeltaList> deltaMap = new HashMap<String,BeanDeltaList>();
private final Map<String, BeanDeltaList> deltaMap = new HashMap<String, BeanDeltaList>();
public BeanDeltaMap() {
public BeanDeltaMap() {
}
public BeanDeltaMap(List<BeanDelta> deltaBeans) {
if (deltaBeans != null) {
for (int i = 0; i < deltaBeans.size(); i++) {
BeanDelta deltaBean = deltaBeans.get(i);
addBeanDelta(deltaBean);
}
}
public BeanDeltaMap(List<BeanDelta> deltaBeans) {
if (deltaBeans != null){
for (int i = 0; i < deltaBeans.size(); i++) {
BeanDelta deltaBean = deltaBeans.get(i);
addBeanDelta(deltaBean);
}
}
}
public String toString() {
return deltaMap.values().toString();
}
public void addBeanDelta(BeanDelta beanDelta){
BeanDescriptor<?> d = beanDelta.getBeanDescriptor();
BeanDeltaList list = getDeltaBeanList(d);
list.add(beanDelta);
}
public Collection<BeanDeltaList> deltaLists() {
return deltaMap.values();
}
private BeanDeltaList getDeltaBeanList(BeanDescriptor<?> d) {
BeanDeltaList deltaList = deltaMap.get(d.getFullName());
if (deltaList == null){
deltaList = new BeanDeltaList(d);
deltaMap.put(d.getFullName(), deltaList);
}
return deltaList;
}
public String toString() {
return deltaMap.values().toString();
}
public void addBeanDelta(BeanDelta beanDelta) {
BeanDescriptor<?> d = beanDelta.getBeanDescriptor();
BeanDeltaList list = getDeltaBeanList(d);
list.add(beanDelta);
}
public Collection<BeanDeltaList> deltaLists() {
return deltaMap.values();
}
private BeanDeltaList getDeltaBeanList(BeanDescriptor<?> d) {
BeanDeltaList deltaList = deltaMap.get(d.getFullName());
if (deltaList == null) {
deltaList = new BeanDeltaList(d);
deltaMap.put(d.getFullName(), deltaList);
}
return deltaList;
}
}
@@ -1,12 +1,12 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataOutputStream;
import java.io.IOException;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import java.io.DataOutputStream;
import java.io.IOException;
public class BeanDeltaProperty {
private final BeanProperty beanProperty;
@@ -1,50 +1,50 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
/**
* Organises the individual bean persist requests by type.
*/
public final class BeanPersistIdMap {
private final Map<String,BeanPersistIds> beanMap = new LinkedHashMap<String, BeanPersistIds>();
public String toString() {
return beanMap.toString();
}
private final Map<String, BeanPersistIds> beanMap = new LinkedHashMap<String, BeanPersistIds>();
public boolean isEmpty() {
return beanMap.isEmpty();
}
public String toString() {
return beanMap.toString();
}
public Collection<BeanPersistIds> values() {
return beanMap.values();
}
/**
* Add a Insert Update or Delete payload.
*/
public void add(BeanDescriptor<?> desc, PersistRequest.Type type, Object id) {
BeanPersistIds r = getPersistIds(desc);
r.addId(type, (Serializable)id);
}
private BeanPersistIds getPersistIds(BeanDescriptor<?> desc) {
String beanType = desc.getFullName();
BeanPersistIds r = beanMap.get(beanType);
if (r == null){
r = new BeanPersistIds(desc);
beanMap.put(beanType, r);
}
return r;
public boolean isEmpty() {
return beanMap.isEmpty();
}
public Collection<BeanPersistIds> values() {
return beanMap.values();
}
/**
* Add a Insert Update or Delete payload.
*/
public void add(BeanDescriptor<?> desc, PersistRequest.Type type, Object id) {
BeanPersistIds r = getPersistIds(desc);
r.addId(type, (Serializable) id);
}
private BeanPersistIds getPersistIds(BeanDescriptor<?> desc) {
String beanType = desc.getFullName();
BeanPersistIds r = beanMap.get(beanType);
if (r == null) {
r = new BeanPersistIds(desc);
beanMap.put(beanType, r);
}
return r;
}
}
@@ -1,12 +1,5 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
@@ -15,6 +8,13 @@ import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Wraps the information representing a Inserted Updated or Deleted Bean.
* <p>
@@ -30,243 +30,243 @@ import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
*/
public class BeanPersistIds implements Serializable {
private static final long serialVersionUID = 8389469180931531409L;
private static final long serialVersionUID = 8389469180931531409L;
private transient BeanDescriptor<?> beanDescriptor;
private transient BeanDescriptor<?> beanDescriptor;
private final String descriptorId;
private final String descriptorId;
private ArrayList<Serializable> insertIds;
private ArrayList<Serializable> updateIds;
private ArrayList<Serializable> deleteIds;
private ArrayList<Serializable> insertIds;
private ArrayList<Serializable> updateIds;
private ArrayList<Serializable> deleteIds;
/**
* Create the payload.
*/
public BeanPersistIds(BeanDescriptor<?> desc) {
this.beanDescriptor = desc;
this.descriptorId = desc.getDescriptorId();
/**
* Create the payload.
*/
public BeanPersistIds(BeanDescriptor<?> desc) {
this.beanDescriptor = desc;
this.descriptorId = desc.getDescriptorId();
}
public static BeanPersistIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
String descriptorId = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
BeanPersistIds bp = new BeanPersistIds(desc);
bp.read(dataInput);
return bp;
}
private void read(DataInput dataInput) throws IOException {
IdBinder idBinder = beanDescriptor.getIdBinder();
int iudType = dataInput.readInt();
ArrayList<Serializable> idList = readIdList(dataInput, idBinder);
switch (iudType) {
case 0:
insertIds = idList;
break;
case 1:
updateIds = idList;
break;
case 2:
deleteIds = idList;
break;
default:
throw new RuntimeException("Invalid iudType " + iudType);
}
}
public static BeanPersistIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
/**
* Write the contents into a BinaryMessage form.
* <p>
* For a RemoteBeanPersist with a large number of id's note that this is
* broken up into many BinaryMessages each with a maximum of 100 ids. This
* enables the contents of a large RemoteTransactionEvent to be split up
* across multiple Packets.
* </p>
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
String descriptorId = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
BeanPersistIds bp = new BeanPersistIds(desc);
bp.read(dataInput);
return bp;
writeIdList(beanDescriptor, 0, insertIds, msgList);
writeIdList(beanDescriptor, 1, updateIds, msgList);
writeIdList(beanDescriptor, 2, deleteIds, msgList);
}
private ArrayList<Serializable> readIdList(DataInput dataInput, IdBinder idBinder) throws IOException {
int count = dataInput.readInt();
if (count < 1) {
return null;
}
private void read(DataInput dataInput) throws IOException {
IdBinder idBinder = beanDescriptor.getIdBinder();
int iudType = dataInput.readInt();
ArrayList<Serializable> idList = readIdList(dataInput, idBinder);
switch (iudType) {
case 0:
insertIds = idList;
break;
case 1:
updateIds = idList;
break;
case 2:
deleteIds = idList;
break;
default:
throw new RuntimeException("Invalid iudType "+iudType);
}
ArrayList<Serializable> idList = new ArrayList<Serializable>(count);
for (int i = 0; i < count; i++) {
Object id = idBinder.readData(dataInput);
idList.add((Serializable) id);
}
return idList;
}
/**
* Write the contents into a BinaryMessage form.
* <p>
* For a RemoteBeanPersist with a large number of id's note that this is
* broken up into many BinaryMessages each with a maximum of 100 ids. This
* enables the contents of a large RemoteTransactionEvent to be split up
* across multiple Packets.
* </p>
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
/**
* Write a BinaryMessage containing the descriptorId, iudType and list of Id
* values.
* <p>
* Note that a given BinaryMessage has a maximum of 100 Ids. This is due to
* the limit of UDP packet sizes. We break up the RemoteBeanPersist into
* potentially many smaller BinaryMessages which may be put into multiple
* Packets.
* </p>
*/
private void writeIdList(BeanDescriptor<?> desc, int iudType, ArrayList<Serializable> idList,
BinaryMessageList msgList) throws IOException {
writeIdList(beanDescriptor, 0, insertIds, msgList);
writeIdList(beanDescriptor, 1, updateIds, msgList);
writeIdList(beanDescriptor, 2, deleteIds, msgList);
}
IdBinder idBinder = desc.getIdBinder();
private ArrayList<Serializable> readIdList(DataInput dataInput, IdBinder idBinder) throws IOException {
int count = idList == null ? 0 : idList.size();
if (count > 0) {
int loop = 0;
int i = 0;
int eof = idList.size();
do {
++loop;
int endOfLoop = Math.min(eof, loop * 100);
int count = dataInput.readInt();
if (count < 1) {
return null;
}
ArrayList<Serializable> idList = new ArrayList<Serializable>(count);
for (int i = 0; i < count; i++) {
Object id = idBinder.readData(dataInput);
idList.add((Serializable) id);
}
return idList;
}
BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20);
/**
* Write a BinaryMessage containing the descriptorId, iudType and list of Id
* values.
* <p>
* Note that a given BinaryMessage has a maximum of 100 Ids. This is due to
* the limit of UDP packet sizes. We break up the RemoteBeanPersist into
* potentially many smaller BinaryMessages which may be put into multiple
* Packets.
* </p>
*/
private void writeIdList(BeanDescriptor<?> desc, int iudType, ArrayList<Serializable> idList,
BinaryMessageList msgList) throws IOException {
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANIUD);
os.writeUTF(descriptorId);
os.writeInt(iudType);
os.writeInt(count);
IdBinder idBinder = desc.getIdBinder();
int count = idList == null ? 0 : idList.size();
if (count > 0) {
int loop = 0;
int i = 0;
int eof = idList.size();
do {
++loop;
int endOfLoop = Math.min(eof, loop * 100);
BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20);
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANIUD);
os.writeUTF(descriptorId);
os.writeInt(iudType);
os.writeInt(count);
for (; i < endOfLoop; i++) {
Serializable idValue = idList.get(i);
idBinder.writeData(os, idValue);
}
os.flush();
msgList.add(m);
} while (i < eof);
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDescriptor != null) {
sb.append(beanDescriptor.getFullName());
} else {
sb.append("descId:").append(descriptorId);
}
if (insertIds != null) {
sb.append(" insertIds:").append(insertIds);
}
if (updateIds != null) {
sb.append(" updateIds:").append(updateIds);
}
if (deleteIds != null) {
sb.append(" deleteIds:").append(deleteIds);
}
return sb.toString();
}
public void addId(PersistRequest.Type type, Serializable id) {
switch (type) {
case INSERT:
addInsertId(id);
break;
case UPDATE:
addUpdateId(id);
break;
case DELETE:
addDeleteId(id);
break;
default:
break;
}
}
private void addInsertId(Serializable id) {
if (insertIds == null) {
insertIds = new ArrayList<Serializable>();
}
insertIds.add(id);
}
private void addUpdateId(Serializable id) {
if (updateIds == null) {
updateIds = new ArrayList<Serializable>();
}
updateIds.add(id);
}
private void addDeleteId(Serializable id) {
if (deleteIds == null) {
deleteIds = new ArrayList<Serializable>();
}
deleteIds.add(id);
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
public List<Serializable> getDeleteIds() {
return deleteIds;
}
public void setBeanDescriptor(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
/**
* Notify the cache and local BeanPersistListener of this event that came
* from another server in the cluster.
*/
public void notifyCacheAndListener() {
BeanPersistListener listener = beanDescriptor.getPersistListener();
// any change invalidates the query cache
beanDescriptor.queryCacheClear();
if (insertIds != null) {
if (listener != null) {
// notify listener
for (int i = 0; i < insertIds.size(); i++) {
listener.remoteInsert(insertIds.get(i));
}
}
}
if (updateIds != null) {
for (int i = 0; i < updateIds.size(); i++) {
Serializable id = updateIds.get(i);
// remove from cache
beanDescriptor.cacheBeanRemove(id);
if (listener != null) {
// notify listener
listener.remoteInsert(id);
}
}
}
if (deleteIds != null) {
for (int i = 0; i < deleteIds.size(); i++) {
Serializable id = deleteIds.get(i);
// remove from cache
beanDescriptor.cacheBeanRemove(id);
if (listener != null) {
// notify listener
listener.remoteInsert(id);
}
}
for (; i < endOfLoop; i++) {
Serializable idValue = idList.get(i);
idBinder.writeData(os, idValue);
}
os.flush();
msgList.add(m);
} while (i < eof);
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDescriptor != null) {
sb.append(beanDescriptor.getFullName());
} else {
sb.append("descId:").append(descriptorId);
}
if (insertIds != null) {
sb.append(" insertIds:").append(insertIds);
}
if (updateIds != null) {
sb.append(" updateIds:").append(updateIds);
}
if (deleteIds != null) {
sb.append(" deleteIds:").append(deleteIds);
}
return sb.toString();
}
public void addId(PersistRequest.Type type, Serializable id) {
switch (type) {
case INSERT:
addInsertId(id);
break;
case UPDATE:
addUpdateId(id);
break;
case DELETE:
addDeleteId(id);
break;
default:
break;
}
}
private void addInsertId(Serializable id) {
if (insertIds == null) {
insertIds = new ArrayList<Serializable>();
}
insertIds.add(id);
}
private void addUpdateId(Serializable id) {
if (updateIds == null) {
updateIds = new ArrayList<Serializable>();
}
updateIds.add(id);
}
private void addDeleteId(Serializable id) {
if (deleteIds == null) {
deleteIds = new ArrayList<Serializable>();
}
deleteIds.add(id);
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
public List<Serializable> getDeleteIds() {
return deleteIds;
}
public void setBeanDescriptor(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
/**
* Notify the cache and local BeanPersistListener of this event that came
* from another server in the cluster.
*/
public void notifyCacheAndListener() {
BeanPersistListener listener = beanDescriptor.getPersistListener();
// any change invalidates the query cache
beanDescriptor.queryCacheClear();
if (insertIds != null) {
if (listener != null) {
// notify listener
for (int i = 0; i < insertIds.size(); i++) {
listener.remoteInsert(insertIds.get(i));
}
}
}
if (updateIds != null) {
for (int i = 0; i < updateIds.size(); i++) {
Serializable id = updateIds.get(i);
// remove from cache
beanDescriptor.cacheBeanRemove(id);
if (listener != null) {
// notify listener
listener.remoteInsert(id);
}
}
}
if (deleteIds != null) {
for (int i = 0; i < deleteIds.size(); i++) {
Serializable id = deleteIds.get(i);
// remove from cache
beanDescriptor.cacheBeanRemove(id);
if (listener != null) {
// notify listener
listener.remoteInsert(id);
}
}
}
}
}
@@ -1,62 +1,63 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebean.event.BulkTableEvent;
import com.avaje.ebean.event.BulkTableEventListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import com.avaje.ebean.event.BulkTableEvent;
import com.avaje.ebean.event.BulkTableEventListener;
public class BulkEventListenerMap {
private final HashMap<String,Entry> map = new HashMap<String,Entry>();
public BulkEventListenerMap(List<BulkTableEventListener> listeners) {
if (listeners != null) {
for (BulkTableEventListener l : listeners) {
Set<String> tables = l.registeredTables();
for (String tableName : tables) {
register(tableName, l);
}
}
}
}
public boolean isEmpty() {
return map.isEmpty();
}
public void process(BulkTableEvent event) {
Entry entry = map.get(event.getTableName());
if (entry != null){
entry.process(event);
}
}
private void register(String tableName, BulkTableEventListener l) {
String upperTableName = tableName.trim().toUpperCase();
Entry entry = map.get(upperTableName);
if (entry == null){
entry = new Entry();
map.put(upperTableName, entry);
}
entry.add(l);
}
private final HashMap<String, Entry> map = new HashMap<String, Entry>();
private static class Entry {
public BulkEventListenerMap(List<BulkTableEventListener> listeners) {
if (listeners != null) {
for (BulkTableEventListener l : listeners) {
Set<String> tables = l.registeredTables();
for (String tableName : tables) {
register(tableName, l);
}
}
}
}
public boolean isEmpty() {
return map.isEmpty();
}
public void process(BulkTableEvent event) {
Entry entry = map.get(event.getTableName());
if (entry != null) {
entry.process(event);
}
}
private void register(String tableName, BulkTableEventListener l) {
String upperTableName = tableName.trim().toUpperCase();
Entry entry = map.get(upperTableName);
if (entry == null) {
entry = new Entry();
map.put(upperTableName, entry);
}
entry.add(l);
}
private static class Entry {
final List<BulkTableEventListener> listeners = new ArrayList<BulkTableEventListener>();
private void add(BulkTableEventListener l) {
listeners.add(l);
}
private void process(BulkTableEvent event){
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).process(event);
}
}
}
private void add(BulkTableEventListener l) {
listeners.add(l);
}
private void process(BulkTableEvent event) {
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).process(event);
}
}
}
}
@@ -1,15 +1,14 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebeaninternal.api.Monitor;
import javax.persistence.Entity;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebeaninternal.api.Monitor;
/**
* Default implementation of PersistenceContext.
* <p>
@@ -134,7 +133,7 @@ public final class DefaultPersistenceContext implements PersistenceContext {
}
return classMap;
}
private Class<?> getBeanBaseType(Class<?> beanType) {
Class<?> parent = beanType.getSuperclass();
@@ -206,5 +205,5 @@ public final class DefaultPersistenceContext implements PersistenceContext {
map.remove(id);
}
}
}
@@ -97,20 +97,20 @@ public final class DefaultTransactionThreadLocal {
* <p>
* Designed to be put in a finally block instead of a rollback() in each catch
* block.
*
* <p>
* <pre>
* Ebean.beingTransaction();
* try {
* // ... perform some actions in a single transaction
*
*
* Ebean.commitTransaction();
*
*
* } finally {
* // ensure transaction ended. If some error occurred then rollback()
* Ebean.endTransaction();
* }
* </pre>
*
* <p>
* </p>
*/
public static void end(String serverName) {
@@ -1,14 +1,14 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
/**
* Beans deleted by Id used for updating L2 Cache.
*/
@@ -1,9 +1,8 @@
package com.avaje.ebeaninternal.server.transaction;
import java.sql.Connection;
import javax.persistence.PersistenceException;
import javax.persistence.RollbackException;
import java.sql.Connection;
/**
* Transaction based on a java.sql.Connection supplied by an external
@@ -20,65 +19,65 @@ import javax.persistence.RollbackException;
*/
public class ExternalJdbcTransaction extends JdbcTransaction {
/**
* Create a Transaction that will have no transaction logging support.
* <p>
* You need to create with a TransactionManager to have transaction logging.
* </p>
*/
public ExternalJdbcTransaction(Connection connection) {
super(null, true, connection, null);
}
/**
* Create a Transaction that will have no transaction logging support.
* <p>
* You need to create with a TransactionManager to have transaction logging.
* </p>
*/
public ExternalJdbcTransaction(Connection connection) {
super(null, true, connection, null);
}
/**
* Construct will all explicit parameters.
*/
public ExternalJdbcTransaction(String id, boolean explicit, Connection connection, TransactionManager manager) {
super(id, explicit, connection, manager);
}
/**
* Construct will all explicit parameters.
*/
public ExternalJdbcTransaction(String id, boolean explicit, Connection connection, TransactionManager manager) {
super(id, explicit, connection, manager);
}
/**
* This will always throw a PersistenceException.
* <p>
* Externally created connections should be committed or rolled back externally.
* </p>
*/
@Override
public void commit() throws RollbackException {
throw new PersistenceException("This is an external transaction so must be committed externally");
}
/**
* This will always throw a PersistenceException.
* <p>
* Externally created connections should be committed or rolled back externally.
* </p>
*/
@Override
public void commit() throws RollbackException {
throw new PersistenceException("This is an external transaction so must be committed externally");
}
/**
* This will always throw a PersistenceException.
* <p>
* Externally created connections should be committed or rolled back externally.
* </p>
*/
@Override
public void end() throws PersistenceException {
throw new PersistenceException("This is an external transaction so must be committed externally");
}
/**
* This will always throw a PersistenceException.
* <p>
* Externally created connections should be committed or rolled back externally.
* </p>
*/
@Override
public void end() throws PersistenceException {
throw new PersistenceException("This is an external transaction so must be committed externally");
}
/**
* This will always throw a PersistenceException.
* <p>
* Externally created connections should be committed or rolled back externally.
* </p>
*/
@Override
public void rollback() throws PersistenceException {
throw new PersistenceException("This is an external transaction so must be rolled back externally");
}
/**
* This will always throw a PersistenceException.
* <p>
* Externally created connections should be committed or rolled back externally.
* </p>
*/
@Override
public void rollback() throws PersistenceException {
throw new PersistenceException("This is an external transaction so must be rolled back externally");
}
/**
* This will always throw a PersistenceException.
* <p>
* Externally created connections should be committed or rolled back externally.
* </p>
*/
@Override
public void rollback(Throwable e) throws PersistenceException {
throw new PersistenceException("This is an external transaction so must be rolled back externally");
}
/**
* This will always throw a PersistenceException.
* <p>
* Externally created connections should be committed or rolled back externally.
* </p>
*/
@Override
public void rollback(Throwable e) throws PersistenceException {
throw new PersistenceException("This is an external transaction so must be rolled back externally");
}
}
@@ -8,41 +8,41 @@ import com.avaje.ebeaninternal.api.SpiTransaction;
*/
public class ExternalTransactionScopeManager extends TransactionScopeManager {
final ExternalTransactionManager externalManager;
/**
* Instantiates transaction scope manager.
*
* @param transactionManager the transaction manager
*/
public ExternalTransactionScopeManager(TransactionManager transactionManager, ExternalTransactionManager externalManager) {
super(transactionManager);
this.externalManager = externalManager;
}
final ExternalTransactionManager externalManager;
public void commit() {
DefaultTransactionThreadLocal.commit(serverName);
}
/**
* Instantiates transaction scope manager.
*
* @param transactionManager the transaction manager
*/
public ExternalTransactionScopeManager(TransactionManager transactionManager, ExternalTransactionManager externalManager) {
super(transactionManager);
this.externalManager = externalManager;
}
public void commit() {
DefaultTransactionThreadLocal.commit(serverName);
}
public void end() {
DefaultTransactionThreadLocal.end(serverName);
}
public void end() {
DefaultTransactionThreadLocal.end(serverName);
}
public SpiTransaction get() {
return (SpiTransaction)externalManager.getCurrentTransaction();
}
public SpiTransaction get() {
public void replace(SpiTransaction trans) {
DefaultTransactionThreadLocal.replace(serverName, trans);
}
return (SpiTransaction) externalManager.getCurrentTransaction();
}
public void rollback() {
DefaultTransactionThreadLocal.rollback(serverName);
}
public void replace(SpiTransaction trans) {
DefaultTransactionThreadLocal.replace(serverName, trans);
}
public void set(SpiTransaction trans) {
DefaultTransactionThreadLocal.set(serverName, trans);
}
public void rollback() {
DefaultTransactionThreadLocal.rollback(serverName);
}
public void set(SpiTransaction trans) {
DefaultTransactionThreadLocal.set(serverName, trans);
}
}
@@ -4,7 +4,7 @@ import com.avaje.ebean.bean.PersistenceContext;
/**
* PersistenceContext used with scope of NONE.
* <p/>
* <p>
* When used effectively means no PersistenceContext is used at all. This is not expected to be used much and
* actually is not recommended.
*/
@@ -10,132 +10,132 @@ import java.util.List;
public class RemoteTransactionEvent implements Runnable {
private final List<BeanPersistIds> beanPersistList = new ArrayList<BeanPersistIds>();
private List<TableIUD> tableList;
private final List<BeanPersistIds> beanPersistList = new ArrayList<BeanPersistIds>();
private List<BeanDeltaList> beanDeltaLists;
private BeanDeltaMap beanDeltaMap;
private DeleteByIdMap deleteByIdMap;
private String serverName;
private List<TableIUD> tableList;
private transient SpiEbeanServer server;
public RemoteTransactionEvent(String serverName) {
this.serverName = serverName;
private List<BeanDeltaList> beanDeltaLists;
private BeanDeltaMap beanDeltaMap;
private DeleteByIdMap deleteByIdMap;
private String serverName;
private transient SpiEbeanServer server;
public RemoteTransactionEvent(String serverName) {
this.serverName = serverName;
}
public RemoteTransactionEvent(SpiEbeanServer server) {
this.server = server;
}
public void run() {
server.remoteTransactionEvent(this);
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDeltaMap != null) {
sb.append(beanDeltaMap);
}
public RemoteTransactionEvent(SpiEbeanServer server) {
this.server = server;
sb.append(beanPersistList);
if (tableList != null) {
sb.append(tableList);
}
public void run() {
server.remoteTransactionEvent(this);
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDeltaMap != null){
sb.append(beanDeltaMap);
}
sb.append(beanPersistList);
if (tableList != null){
sb.append(tableList);
}
return sb.toString();
}
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
if (tableList != null){
for (int i = 0; i < tableList.size(); i++) {
tableList.get(i).writeBinaryMessage(msgList);
}
}
if (deleteByIdMap != null){
for (BeanPersistIds deleteIds : deleteByIdMap.values()) {
deleteIds.writeBinaryMessage(msgList);
}
}
if (beanPersistList != null){
for (int i = 0; i < beanPersistList.size(); i++) {
beanPersistList.get(i).writeBinaryMessage(msgList);
}
}
if (beanDeltaLists != null){
for (int i = 0; i < beanDeltaLists.size(); i++) {
beanDeltaLists.get(i).writeBinaryMessage(msgList);
}
}
}
public boolean isEmpty() {
return beanPersistList.isEmpty() && (tableList == null || tableList.isEmpty());
}
public void addBeanPersistIds(BeanPersistIds beanPersist){
beanPersistList.add(beanPersist);
return sb.toString();
}
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
if (tableList != null) {
for (int i = 0; i < tableList.size(); i++) {
tableList.get(i).writeBinaryMessage(msgList);
}
}
public void addTableIUD(TableIUD tableIud){
if (tableList == null){
tableList = new ArrayList<TableIUD>(4);
}
tableList.add(tableIud);
}
public void addBeanDeltaList(BeanDeltaList deltaList){
if (beanDeltaLists == null){
beanDeltaLists = new ArrayList<BeanDeltaList>();
}
beanDeltaLists.add(deltaList);
}
public void addBeanDelta(BeanDelta beanDelta){
if (beanDeltaMap == null){
beanDeltaMap = new BeanDeltaMap();
}
beanDeltaMap.addBeanDelta(beanDelta);
}
public String getServerName() {
return serverName;
}
public SpiEbeanServer getServer() {
return server;
if (deleteByIdMap != null) {
for (BeanPersistIds deleteIds : deleteByIdMap.values()) {
deleteIds.writeBinaryMessage(msgList);
}
}
public void setServer(SpiEbeanServer server) {
this.server = server;
}
public DeleteByIdMap getDeleteByIdMap() {
return deleteByIdMap;
if (beanPersistList != null) {
for (int i = 0; i < beanPersistList.size(); i++) {
beanPersistList.get(i).writeBinaryMessage(msgList);
}
}
public void setDeleteByIdMap(DeleteByIdMap deleteByIdMap) {
this.deleteByIdMap = deleteByIdMap;
if (beanDeltaLists != null) {
for (int i = 0; i < beanDeltaLists.size(); i++) {
beanDeltaLists.get(i).writeBinaryMessage(msgList);
}
}
}
public List<TableIUD> getTableIUDList() {
return tableList;
}
public boolean isEmpty() {
return beanPersistList.isEmpty() && (tableList == null || tableList.isEmpty());
}
public List<BeanPersistIds> getBeanPersistList() {
return beanPersistList;
}
public void addBeanPersistIds(BeanPersistIds beanPersist) {
beanPersistList.add(beanPersist);
}
public List<BeanDeltaList> getBeanDeltaLists() {
if (beanDeltaMap != null){
beanDeltaLists.addAll(beanDeltaMap.deltaLists());
}
return beanDeltaLists;
public void addTableIUD(TableIUD tableIud) {
if (tableList == null) {
tableList = new ArrayList<TableIUD>(4);
}
tableList.add(tableIud);
}
public void addBeanDeltaList(BeanDeltaList deltaList) {
if (beanDeltaLists == null) {
beanDeltaLists = new ArrayList<BeanDeltaList>();
}
beanDeltaLists.add(deltaList);
}
public void addBeanDelta(BeanDelta beanDelta) {
if (beanDeltaMap == null) {
beanDeltaMap = new BeanDeltaMap();
}
beanDeltaMap.addBeanDelta(beanDelta);
}
public String getServerName() {
return serverName;
}
public SpiEbeanServer getServer() {
return server;
}
public void setServer(SpiEbeanServer server) {
this.server = server;
}
public DeleteByIdMap getDeleteByIdMap() {
return deleteByIdMap;
}
public void setDeleteByIdMap(DeleteByIdMap deleteByIdMap) {
this.deleteByIdMap = deleteByIdMap;
}
public List<TableIUD> getTableIUDList() {
return tableList;
}
public List<BeanPersistIds> getBeanPersistList() {
return beanPersistList;
}
public List<BeanDeltaList> getBeanDeltaLists() {
if (beanDeltaMap != null) {
beanDeltaLists.addAll(beanDeltaMap.deltaLists());
}
return beanDeltaLists;
}
}
@@ -113,7 +113,7 @@ public class TransactionManager {
List<TransactionEventListener> transactionEventListeners = bootupClasses.getTransactionEventListeners();
this.transactionEventListeners = transactionEventListeners.toArray(new
TransactionEventListener[transactionEventListeners.size()]);
TransactionEventListener[transactionEventListeners.size()]);
this.prefix = "";
this.externalTransPrefix = "e";
@@ -175,8 +175,7 @@ public class TransactionManager {
if (OnQueryOnly.CLOSE.equals(dbPlatformOnQueryOnly)) {
// check for read committed isolation level
if (!isReadCommittedIsolation(ds)) {
logger.warn("Ignoring DatabasePlatform.OnQueryOnly.CLOSE as the transaction Isolation Level is not " +
"READ_COMMITTED");
logger.warn("Ignoring DatabasePlatform.OnQueryOnly.CLOSE as the transaction Isolation Level is not READ_COMMITTED");
// we will just use ROLLBACK and ignore the desired optimisation
return OnQueryOnly.ROLLBACK;
} else {
@@ -1,118 +1,117 @@
package com.avaje.ebeaninternal.server.transaction;
import java.util.HashMap;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.api.SpiTransaction;
import javax.persistence.PersistenceException;
import java.util.HashMap;
/**
* Current transactions mapped by server name.
* Current transactions mapped by server name.
*/
public class TransactionMap {
/**
* Map of State by serverName.
*/
private final HashMap<String,State> map = new HashMap<String, State>();
/**
* Map of State by serverName.
*/
private final HashMap<String, State> map = new HashMap<String, State>();
public String toString() {
return map.toString();
}
public boolean isEmpty() {
return map.isEmpty();
}
/**
* Return the State for a given serverName.
*/
public State getState(String serverName) {
return map.get(serverName);
}
/**
* Return the State for a given serverName.
*/
public State getStateWithCreate(String serverName) {
State state = map.get(serverName);
if (state == null) {
state = new State();
map.put(serverName, state);
}
return state;
}
/**
* Remove and return the State for a given serverName.
*/
public State removeState(String serverName) {
return map.remove(serverName);
}
/**
* The transaction and whether it is active.
*/
public static class State {
SpiTransaction transaction;
public String toString() {
return map.toString();
return "txn[" + transaction + "]";
}
public boolean isEmpty() {
return map.isEmpty();
public SpiTransaction get() {
return transaction;
}
/**
* Return the State for a given serverName.
* Set the transaction. This will now be the current transaction.
*/
public State getState(String serverName) {
return map.get(serverName);
public void set(SpiTransaction trans) {
if (transaction != null && transaction.isActive()) {
String m = "The existing transaction is still active?";
throw new PersistenceException(m);
}
transaction = trans;
}
/**
* Return the State for a given serverName.
* Commit the transaction.
*/
public State getStateWithCreate(String serverName) {
State state = map.get(serverName);
if (state == null){
state = new State();
map.put(serverName, state);
}
return state;
public void commit() {
transaction.commit();
transaction = null;
}
/**
* Remove and return the State for a given serverName.
* Rollback the transaction.
*/
public State removeState(String serverName) {
return map.remove(serverName);
public void rollback() {
transaction.rollback();
transaction = null;
}
/**
* The transaction and whether it is active.
* End the transaction.
*/
public static class State {
SpiTransaction transaction;
public String toString() {
return "txn["+transaction+"]";
}
public SpiTransaction get() {
return transaction;
}
/**
* Set the transaction. This will now be the current transaction.
*/
public void set(SpiTransaction trans) {
if (transaction != null && transaction.isActive()){
String m = "The existing transaction is still active?";
throw new PersistenceException(m);
}
transaction = trans;
}
/**
* Commit the transaction.
*/
public void commit() {
transaction.commit();
transaction = null;
}
/**
* Rollback the transaction.
*/
public void rollback() {
transaction.rollback();
transaction = null;
}
/**
* End the transaction.
*/
public void end() {
if (transaction != null){
transaction.end();
transaction = null;
}
}
/**
* Used to replace transaction with a proxy.
*/
public void replace(SpiTransaction trans) {
transaction = trans;
}
public void end() {
if (transaction != null) {
transaction.end();
transaction = null;
}
}
/**
* Used to replace transaction with a proxy.
*/
public void replace(SpiTransaction trans) {
transaction = trans;
}
}
}
@@ -8,51 +8,51 @@ import com.avaje.ebeaninternal.api.SpiTransactionScopeManager;
*/
public abstract class TransactionScopeManager implements SpiTransactionScopeManager {
protected final TransactionManager transactionManager;
protected final String serverName;
protected final TransactionManager transactionManager;
public TransactionScopeManager(TransactionManager transactionManager){
this.transactionManager = transactionManager;
this.serverName = transactionManager.getServerName();
}
/**
* Return the current Transaction for this serverName and Thread.
*/
public abstract SpiTransaction get();
protected final String serverName;
/**
* Set a new Transaction for this serverName and Thread.
*/
public abstract void set(SpiTransaction trans);
/**
* Commit the current transaction.
*/
public abstract void commit();
public TransactionScopeManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
this.serverName = transactionManager.getServerName();
}
/**
* Rollback the current transaction.
*/
public abstract void rollback();
/**
* Return the current Transaction for this serverName and Thread.
*/
public abstract SpiTransaction get();
/**
* Set a new Transaction for this serverName and Thread.
*/
public abstract void set(SpiTransaction trans);
/**
* Commit the current transaction.
*/
public abstract void commit();
/**
* Rollback the current transaction.
*/
public abstract void rollback();
/**
* Rollback if required.
*/
public abstract void end();
/**
* Rollback if required.
*/
public abstract void end();
/**
* Replace the current transaction with this one.
* <p>
* Used for Background fetching and Nested transaction scopes.
* </p>
* <p>
* Used for background fetching. Replaces the current transaction with a
* 'dummy' transaction. The current transaction is given to the background
* thread so it can continue the fetch.
* </p>
*/
public abstract void replace(SpiTransaction trans);
/**
* Replace the current transaction with this one.
* <p>
* Used for Background fetching and Nested transaction scopes.
* </p>
* <p>
* Used for background fetching. Replaces the current transaction with a
* 'dummy' transaction. The current transaction is given to the background
* thread so it can continue the fetch.
* </p>
*/
public abstract void replace(SpiTransaction trans);
}
@@ -1,13 +1,13 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE>Transaction implementation</TITLE>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE>Transaction implementation</TITLE>
</HEAD>
<Body BGCOLOR="#ffffff">
Transaction implementation
<p>
Implementation of the transaction functions.
Implementation of the transaction functions.
</p>
</Body>