diff --git a/pom.xml b/pom.xml
index ea2d842ca..5412a74c6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,14 +99,14 @@
+ * Provides configuration for cluster communication (if clustering is used). The cluster communication is + * used to invalidate appropriate parts of the L2 cache across the cluster. + */ +public class ContainerConfig { + + /** + * Communication mode used for clustering. + */ + public enum ClusterMode { + + /** + * No clustering. + */ + NONE, + + /** + * Use Multicast networking for cluster wide communication. + */ + MULTICAST, + + /** + * Use TCP Sockets for cluster wide communication. + */ + SOCKET + } + + /** + * The cluster mode to use. + */ + ClusterMode mode = ClusterMode.NONE; + + /** + * Configuration if using TCP sockets for clustering communication. + */ + SocketConfig socketConfig = new SocketConfig(); + + /** + * Configuration if using Multicast for clustering communication. + */ + MulticastConfig multicastConfig = new MulticastConfig(); + + + // ------------------------------------------------------------------------------------------- + // MulticastConfig + + /** + * The configuration for clustering using Multicast networking. + */ + public static class MulticastConfig { + + int managerSleepMillis = 80; + int lastSendTimeFreqSecs = 300;//5mins + int lastStatusTimeFreqSecs = 600;//10mins + int maxResendOutgoingAttempts = 200; + int maxResendIncomingRequests = 50; + + int listenPort; + String listenAddress; + int sendPort; + String sendAddress; + + // Note 1500 is Ethernet MTU and this must be less than UDP max packet size of 65507 + int maxSendPacketSize = 1500; + + // Whether to send packets even when there are no other members online + boolean sendWithNoMembers = true; + + // When multiple instances are on same box you need to broadcast back locally + boolean disableLoopback; + int listenTimeToLive = -1; + int listenTimeout = 1000; + int listenBufferSize = 65500; + // For multihomed environment the address the listener should bind to + String listenBindAddress; + + /** + * Return the manager sleep millis. + */ + public int getManagerSleepMillis() { + return managerSleepMillis; + } + + /** + * Set the manager sleep millis. + */ + public void setManagerSleepMillis(int managerSleepMillis) { + this.managerSleepMillis = managerSleepMillis; + } + + /** + * Return the last send time frequency. + */ + public int getLastSendTimeFreqSecs() { + return lastSendTimeFreqSecs; + } + + /** + * Set the last send time frequency. + */ + public void setLastSendTimeFreqSecs(int lastSendTimeFreqSecs) { + this.lastSendTimeFreqSecs = lastSendTimeFreqSecs; + } + + /** + * Return the last status time frequency. + */ + public int getLastStatusTimeFreqSecs() { + return lastStatusTimeFreqSecs; + } + + /** + * Set the last status time frequency. + */ + public void setLastStatusTimeFreqSecs(int lastStatusTimeFreqSecs) { + this.lastStatusTimeFreqSecs = lastStatusTimeFreqSecs; + } + + /** + * Return the maximum number of times we will try to re-send a given packet before giving up sending + */ + public int getMaxResendOutgoingAttempts() { + return maxResendOutgoingAttempts; + } + + /** + * Set the maximum retry attempts for outgoing messages. + */ + public void setMaxResendOutgoingAttempts(int maxResendOutgoingAttempts) { + this.maxResendOutgoingAttempts = maxResendOutgoingAttempts; + } + + /** + * Return the maximum number of times we will ask for a packet to be resent to us before giving up asking. + */ + public int getMaxResendIncomingRequests() { + return maxResendIncomingRequests; + } + + /** + * Set the maximum retry attempts for incoming messages. + */ + public void setMaxResendIncomingRequests(int maxResendIncomingRequests) { + this.maxResendIncomingRequests = maxResendIncomingRequests; + } + + /** + * Return the listen port. + */ + public int getListenPort() { + return listenPort; + } + + /** + * Set the listen port. + */ + public void setListenPort(int port) { + this.listenPort = port; + } + + /** + * Return the listen address. + */ + public String getListenAddress() { + return listenAddress; + } + + /** + * Set the listen address. + */ + public void setListenAddress(String listenAddress) { + this.listenAddress = listenAddress; + } + + /** + * Return the send port. + */ + public int getSendPort() { + return sendPort; + } + + /** + * Set the send port. + */ + public void setSendPort(int sendPort) { + this.sendPort = sendPort; + } + + /** + * Return the send address. + */ + public String getSendAddress() { + return sendAddress; + } + + /** + * Set the send address. + */ + public void setSendAddress(String sendAddress) { + this.sendAddress = sendAddress; + } + + /** + * Return the maximum send packet size. + */ + public int getMaxSendPacketSize() { + return maxSendPacketSize; + } + + /** + * Set the maximum send packet size. Note 1500 is Ethernet MTU and this must be less than UDP max packet size of 65507. + */ + public void setMaxSendPacketSize(int maxSendPacketSize) { + this.maxSendPacketSize = maxSendPacketSize; + } + + /** + * Return true if send messages when no other members in the cluster are up. + */ + public boolean isSendWithNoMembers() { + return sendWithNoMembers; + } + + /** + * Set true if send messages when no other members in the cluster are up. + */ + public void setSendWithNoMembers(boolean sendWithNoMembers) { + this.sendWithNoMembers = sendWithNoMembers; + } + + /** + * Return true if loopback is disabled. When multiple instances are on same box you need to broadcast back locally. + */ + public boolean isDisableLoopback() { + return disableLoopback; + } + + /** + * Set if loopback is disabled. When multiple instances are on same box you need to broadcast back locally. + */ + public void setDisableLoopback(boolean disableLoopback) { + this.disableLoopback = disableLoopback; + } + + /** + * Return the listen time to live. + */ + public int getListenTimeToLive() { + return listenTimeToLive; + } + + /** + * Set the listen time to live. + */ + public void setListenTimeToLive(int listenTimeToLive) { + this.listenTimeToLive = listenTimeToLive; + } + + /** + * Return the listen timeout. + */ + public int getListenTimeout() { + return listenTimeout; + } + + /** + * set the listen timeout. + */ + public void setListenTimeout(int listenTimeout) { + this.listenTimeout = listenTimeout; + } + + /** + * Return the listen buffer size. + */ + public int getListenBufferSize() { + return listenBufferSize; + } + + /** + * Set the listen buffer size. + */ + public void setListenBufferSize(int listenBufferSize) { + this.listenBufferSize = listenBufferSize; + } + + /** + * Return the listener bind address (optional). For multihomed environment the address the listener should bind to. + */ + public String getListenBindAddress() { + return listenBindAddress; + } + + /** + * Set the listener bind address (optional). For multihomed environment the address the listener should bind to. + */ + public void setListenBindAddress(String listenBindAddress) { + this.listenBindAddress = listenBindAddress; + } + } + + // ------------------------------------------------------------------------------------------- + // SocketConfig + + /** + * Configuration for clustering using TCP sockets. + *
+ * This is good for when there are relatively small number of cluster members.
+ */
+ public static class SocketConfig {
+
+ /**
+ * This local server in host:port format.
+ */
+ String localHostPort;
+
+ /**
+ * All the cluster members in host:port format.
+ */
+ List
+ * You can use this when you have your own properties to use for configuration.
+ *
- * This will evaluate expressions using first environment variables, than java
- * system variables and lastly properties in ebean.properties - in that order.
- *
- * Expressions start with "${" and end with "}".
- *
+ * Ebean has historically ignored the case of keys hence returning the Properties with all the keys lower cased.
+ *
+ * This performs a search using the prefix and server name (if supplied) to search for the property
+ * value in order based on:
+ * {@code
+ * prefix.serverName.key
+ * prefix.key
+ * key
+ * }
+ *
+ * {@code
* ServerConfig c = new ServerConfig();
- * c.setName("ordh2");
+ * c.setName("ordh2");
*
* // read the ebean.properties and load
* // those settings into this serverConfig object
@@ -43,18 +43,18 @@ import java.util.List;
* c.setDdlRun(true);
*
* // add any classes found in the app.data package
- * c.addPackage("app.data");
+ * c.addPackage("app.data");
*
* // add the names of Jars that contain entities
- * c.addJar("myJarContainingEntities.jar");
- * c.addJar("someOtherJarContainingEntities.jar");
+ * c.addJar("myJarContainingEntities.jar");
+ * c.addJar("someOtherJarContainingEntities.jar");
*
* // register as the 'Default' server
* c.setDefaultServer(true);
*
* EbeanServer server = EbeanServerFactory.create(c);
*
- *
+ * }
*
* @see EbeanServerFactory
*
@@ -62,17 +62,14 @@ import java.util.List;
* @author rbygrave
*/
public class ServerConfig {
-
- /**
- * The Constant DEFAULT_QUERY_BATCH_SIZE. Default: 100
- */
- private final static int DEFAULT_QUERY_BATCH_SIZE = 100;
/**
* The EbeanServer name.
*/
private String name;
+ private ContainerConfig containerConfig;
+
/**
* The resource directory.
*/
@@ -111,6 +108,11 @@ public class ServerConfig {
*/
private List
@@ -1049,6 +1319,23 @@ public class ServerConfig {
this.searchJars = searchJars;
}
+ /**
+ * Return the class name of a classPathReader implementation.
+ */
+ public String getClassPathReaderClassName() {
+ return classPathReaderClassName;
+ }
+
+ /**
+ * Set the class name of a classPathReader implementation.
+ *
+ * Refer to server.util.ClassPathReader, this should really by a plugin but doing this for now
+ * to be relatively compatible with current implementation.
+ */
+ public void setClassPathReaderClassName(String classPathReaderClassName) {
+ this.classPathReaderClassName = classPathReaderClassName;
+ }
+
/**
* Set the list of classes (entities, listeners, scalarTypes etc) that should
* be used for this server.
@@ -1334,44 +1621,26 @@ public class ServerConfig {
}
/**
- * Load the settings from the ebean.properties file.
+ * Load settings from ebean.properties.
*/
public void loadFromProperties() {
- ConfigPropertyMap p = new ConfigPropertyMap(name);
+ loadFromProperties(PropertyMap.defaultProperties());
+ }
+
+ /**
+ * Load the settings from the given properties
+ */
+ public void loadFromProperties(Properties properties) {
+ PropertiesWrapper p = new PropertiesWrapper("ebean", name, properties);
loadSettings(p);
}
- /**
- * Return a PropertySource for this server.
- */
- public PropertySource getPropertySource() {
- return GlobalProperties.getPropertySource(name);
- }
-
- /**
- * Return a configuration property using a default value.
- */
- public String getProperty(String propertyName, String defaultValue) {
- PropertySource p = new ConfigPropertyMap(name);
- return p.get(propertyName, defaultValue);
- }
-
- /**
- * Return a configuration property.
- */
- public String getProperty(String propertyName) {
- return getProperty(propertyName, null);
- }
@SuppressWarnings("unchecked")
- private
@@ -33,563 +33,542 @@ import org.slf4j.LoggerFactory; * Other threads call {@link #broadcast(RemoteTransactionEvent)} to send * transaction even information. *
- * - * @author rbygrave */ public class McastClusterManager implements ClusterBroadcast, Runnable { - private static final Logger logger = LoggerFactory.getLogger(McastClusterManager.class); + private static final Logger logger = LoggerFactory.getLogger(McastClusterManager.class); - private ClusterManager clusterManager; + private ClusterManager clusterManager; - private final Thread managerThread; + private final Thread managerThread; - /** - * Helps co-ordinate packet information (Acks, Missing Packets etc). - */ - private final McastPacketControl packageControl; + /** + * Helps co-ordinate packet information (Acks, Missing Packets etc). + */ + private final McastPacketControl packageControl; - /** - * Listeners for incoming packets. - */ - private final McastListener listener; + /** + * Listeners for incoming packets. + */ + private final McastListener listener; - /** - * Sends packets out to the cluster. - */ - private final McastSender localSender; + /** + * Sends packets out to the cluster. + */ + private final McastSender localSender; - /** - * The localSenderHostPort is used to identify this instance in the cluster. - */ - private final String localSenderHostPort; - - /** - * Creates the Packets (byte[]) from Messages and RemoteTransactionEvent. - */ - private final PacketWriter packetWriter; - - /** - * List of Re-send messages that the managerThread needs to process. - */ - private final ArrayList- * Generally speaking we only care if the groupSize == 0 meaning there are no other - * members of the cluster that are online. In this case we can potentially not send - * the packets out (depending on sendWithNoMembers) and not cache them (for re-sending - * if they where not ACK'ed). - *
- */ - private int currentGroupSize = -1; - - /** - * The last time a packet was sent from this node. - */ - private long lastSendTime; + /** + * The last ACK we sent out to other members of the cluster. + */ + private final IncomingPacketsLastAck incomingPacketsLastAck = new IncomingPacketsLastAck(); - /** - * The max time we go without sending any packets. - */ - private int lastSendTimeFreqMillis; + /** + * A limit of the number of times we will try to send out a given packet. + * Once this is exceeded we will just drop that packet. Hopefully this does + * not happen but we don't want to keep trying forever producing network + * traffic. + */ + private final int maxResendOutgoing; - /** - * The last time the cluster status was logged. - */ - private long lastStatusTime = System.currentTimeMillis(); - - /** - * The max time we go before logging the cluster status. - */ - private int lastStatusTimeFreqMillis; - - - private long totalTxnEventsSent; - private long totalTxnEventsReceived; - - private long totalPacketsSent; - private long totalBytesSent; - - private long totalPacketsResent; - private long totalBytesResent; - - private long totalPacketsReceived; - private long totalBytesReceived; + /** + * Instead of ACK'ing immediately we periodically wake up and in a single + * packet (typically) ACK all members of the cluster everything we got since + * the last sleep time. More frequent ACK's means less memory consumption as + * Packets are cleared from the outgoingPacketsCache quicker at the cost of + * sending more packets. + */ + private long managerSleepMillis; + + /** + * When true then packets are still sent out even when the cluster has no other online members. + */ + private boolean sendWithNoMembers; + + /** + * The current minAcked packetId processed by the managerThread. + * All packets before this have been ACK'ed by everyone in the cluster. + */ + private long minAcked; + + /** + * The min packetId that has been ACKed by all the members of the cluster according + * to the McastListener. This will increase as the Listener receives ACK's and means + * we can trim out Packets from the sent cache. + */ + private long minAckedFromListener; + + /** + * Start the groupSize at -1 so we have to wait until the Listener times out or gets + * a control messages (Ping, PingResponse, Join, Leave etc) before we know how many + * members of the group the listener knows about. + *+ * Generally speaking we only care if the groupSize == 0 meaning there are no other + * members of the cluster that are online. In this case we can potentially not send + * the packets out (depending on sendWithNoMembers) and not cache them (for re-sending + * if they where not ACK'ed). + *
+ */ + private int currentGroupSize = -1; + + /** + * The last time a packet was sent from this node. + */ + private long lastSendTime; + + /** + * The max time we go without sending any packets. + */ + private int lastSendTimeFreqMillis; + + /** + * The last time the cluster status was logged. + */ + private long lastStatusTime = System.currentTimeMillis(); + + /** + * The max time we go before logging the cluster status. + */ + private int lastStatusTimeFreqMillis; - public McastClusterManager() { + private long totalTxnEventsSent; + private long totalTxnEventsReceived; - this.managerSleepMillis = GlobalProperties.getInt("ebean.cluster.mcast.managerSleepMillis", 80); - this.lastSendTimeFreqMillis = 1000*GlobalProperties.getInt("ebean.cluster.mcast.pingFrequencySecs", 300);//5mins - this.lastStatusTimeFreqMillis = 1000*GlobalProperties.getInt("ebean.cluster.mcast.statusFrequencySecs", 600);//10mins - - // the maximum number of times we will try to re-send a given packet before giving up sending - this.maxResendOutgoing = GlobalProperties.getInt("ebean.cluster.mcast.maxResendOutgoing", 200); - // the maximum number of times we will ask for a packet to be resent to us before giving up asking - int maxResendIncoming = GlobalProperties.getInt("ebean.cluster.mcast.maxResendIncoming", 50); - - - int port = GlobalProperties.getInt("ebean.cluster.mcast.listen.port", 0); - String addr = GlobalProperties.get("ebean.cluster.mcast.listen.address", null); + private long totalPacketsSent; + private long totalBytesSent; - int sendPort = GlobalProperties.getInt("ebean.cluster.mcast.send.port", 0); - String sendAddr = GlobalProperties.get("ebean.cluster.mcast.send.address", null); + private long totalPacketsResent; + private long totalBytesResent; - // Sender options - // Note 1500 is Ethernet MTU and this must be less than UDP max packet size of 65507 - int maxSendPacketSize = GlobalProperties.getInt("ebean.cluster.mcast.send.maxPacketSize", 1500); - // Whether to send packets even when there are no other members online - this.sendWithNoMembers = GlobalProperties.getBoolean("ebean.cluster.mcast.send.sendWithNoMembers", true); - - // Listener options - // When multiple instances are on same box you need to broadcast back locally - boolean disableLoopback = GlobalProperties.getBoolean("ebean.cluster.mcast.listen.disableLoopback", false); - int ttl = GlobalProperties.getInt("ebean.cluster.mcast.listen.ttl", -1); - int timeout = GlobalProperties.getInt("ebean.cluster.mcast.listen.timeout", 1000); - int bufferSize = GlobalProperties.getInt("ebean.cluster.mcast.listen.bufferSize", 65500); - // For multihomed environment the address the listener should bind to - String mcastAddr = GlobalProperties.get("ebean.cluster.mcast.listen.mcastAddress", null); + private long totalPacketsReceived; + private long totalBytesReceived; - InetAddress mcastAddress = null; - if (mcastAddr != null) { - try { - mcastAddress = InetAddress.getByName(mcastAddr); - } catch (UnknownHostException e) { - String msg = "Error getting Multicast InetAddress for " + mcastAddr; - throw new RuntimeException(msg, e); - } - } - if (port == 0 || addr == null) { - String msg = "One of these Multicast settings has not been set. " + "ebean.cluster.mcast.listen.port=" - + port + ", ebean.cluster.mcast.listen.address=" + addr; + public McastClusterManager(ContainerConfig containerConfig) { - throw new IllegalArgumentException(msg); - } + ContainerConfig.MulticastConfig config = containerConfig.getMulticastConfig(); - this.managerThread = new Thread(this, "EbeanClusterMcastManager"); + this.managerSleepMillis = config.getManagerSleepMillis(); + this.lastSendTimeFreqMillis = 1000 * config.getLastSendTimeFreqSecs(); + this.lastStatusTimeFreqMillis = 1000 * config.getLastStatusTimeFreqSecs(); - this.packetWriter = new PacketWriter(maxSendPacketSize); - this.localSender = new McastSender(port, addr, sendPort, sendAddr); - this.localSenderHostPort = localSender.getSenderHostPort(); + // the maximum number of times we will try to re-send a given packet before giving up sending + this.maxResendOutgoing = config.getMaxResendOutgoingAttempts(); + // the maximum number of times we will ask for a packet to be resent to us before giving up asking + int maxResendIncoming = config.getMaxResendIncomingRequests(); - this.packageControl = new McastPacketControl(this, localSenderHostPort, maxResendIncoming); - - this.listener = new McastListener(this, packageControl, port, addr, bufferSize, timeout, localSenderHostPort, - disableLoopback, ttl, mcastAddress); + + int port = config.getListenPort(); + String addr = config.getListenAddress(); + + int sendPort = config.getSendPort(); + String sendAddr = config.getSendAddress(); + + // Sender options + // Note 1500 is Ethernet MTU and this must be less than UDP max packet size of 65507 + int maxSendPacketSize = config.getMaxSendPacketSize(); + // Whether to send packets even when there are no other members online + this.sendWithNoMembers = config.isSendWithNoMembers(); + + // Listener options + // When multiple instances are on same box you need to broadcast back locally + boolean disableLoopback = config.isDisableLoopback(); + int ttl = config.getListenTimeToLive(); + int timeout = config.getListenTimeout(); + int bufferSize = config.getListenBufferSize(); + // For multihomed environment the address the listener should bind to + String mcastAddr = config.getListenBindAddress(); + + InetAddress mcastBindAddress = null; + if (mcastAddr != null) { + try { + mcastBindAddress = InetAddress.getByName(mcastAddr); + } catch (UnknownHostException e) { + String msg = "Error getting Multicast InetAddress for " + mcastAddr; + throw new RuntimeException(msg, e); + } } + if (port == 0 || addr == null) { + String msg = "One of these Multicast settings has not been set. " + "ebean.cluster.mcast.listen.port=" + + port + ", ebean.cluster.mcast.listen.address=" + addr; - /** - * The McastListener tells us there are no other members of the cluster that - * are currently online. - */ - protected void fromListenerTimeoutNoMembers() { - synchronized (managerThread) { - this.currentGroupSize = 0; - } - } - - /** - * McastListener calls this method to get the manager to process messages. - * - * @param newMinAcked - * the minAcked packetId according to the listener - * @param msgControl - * a control message to process - * @param msgResend - * a Please re-send message to process - * @param groupSize - * the number of other online members - */ - protected void fromListener(long newMinAcked, MessageControl msgControl, MessageResend msgResend, - int groupSize, long totalPacketsReceived, long totalBytesReceived, long totalTxnEventsReceived) { - - synchronized (managerThread) { - if (newMinAcked > minAckedFromListener){ - minAckedFromListener = newMinAcked; - } - if (msgControl != null){ - controlMessages.add(msgControl); - } - if (msgResend != null){ - resendMessages.add(msgResend); - } - // mostly interested when groupSize hits 0 (we are the only instance online). - this.currentGroupSize = groupSize; - - // and some stats so we know how busy the listener has been - this.totalPacketsReceived = totalPacketsReceived; - this.totalBytesReceived = totalBytesReceived; - this.totalTxnEventsReceived = totalTxnEventsReceived; - } - } - - /** - * Get the overall status and activity of this cluster node. - */ - public McastStatus getStatus(boolean reset) { - synchronized (managerThread) { - - long currentPacketId = packetWriter.currentPacketId(); - String lastAcks = incomingPacketsLastAck.toString(); - - return new McastStatus(currentGroupSize, outgoingPacketsCache.size(), currentPacketId, minAcked, lastAcks, - totalTxnEventsSent, totalTxnEventsReceived, totalPacketsSent, totalPacketsResent, totalPacketsReceived, - totalBytesSent, totalBytesResent, totalBytesReceived); - - } - } - - /** - * Periodically send out Ack, Re-send and Control messages. - */ - public void run() { - while (true) { - try { - // sleep for a little bit as we ACK packets periodically - // rather than immediately. We will typically ACK many - // messages from all cluster members in a single Packet - Thread.sleep(managerSleepMillis); - - synchronized (managerThread) { - - handleControlMessages(); - - handleResendMessages(); - - if (currentGroupSize == 0){ - // no members online so trim the entire outgoing packets cache - int trimmedCount = outgoingPacketsCache.trimAll(); - if (trimmedCount > 0){ - logger.debug("Cluster has no other members. Trimmed "+trimmedCount); - } - - } else if (minAckedFromListener > minAcked){ - // ACKs have come back so trim send packets cache - outgoingPacketsCache.trimAcknowledgedMessages(minAckedFromListener); - minAcked = minAckedFromListener; - } - - // Get list of all the ACK messages required to sent since the last time. - // This is effectively one ACK message per member of the cluster. The ACK - // message covers all the packets received from the member up to - // the gotAllPoint. - // Also get any RESEND messages asking for packets that we have not - // received between the gotAllPoint and the gotMaxPoint. - AckResendMessages ackResendMessages = packageControl.getAckResendMessages(incomingPacketsLastAck); - - if (ackResendMessages.size() > 0){ - // send the ACK and RESEND messages for all members of the - // cluster typically in a single Packet - if (sendMessages(false, ackResendMessages.getMessages())) { - // update the last Ack position - incomingPacketsLastAck.updateLastAck(ackResendMessages); - } - } - - if (lastSendTime < System.currentTimeMillis() - lastSendTimeFreqMillis){ - // been quite for too long - send a Ping out - sendPing(); - } - - if (lastStatusTimeFreqMillis > 0){ - if (lastStatusTime < System.currentTimeMillis() - lastStatusTimeFreqMillis){ - McastStatus status = getStatus(false); - logger.info("Cluster Status: "+status.getSummary()); - lastStatusTime = System.currentTimeMillis(); - } - } - - } - } catch (Exception e){ - String msg = "Error with Cluster Mcast Manager thread"; - logger.error(msg, e); - } - } + throw new IllegalArgumentException(msg); } - /** - * We have been asked to Re-send some packets. - */ - private void handleResendMessages() { + this.managerThread = new Thread(this, "EbeanClusterMcastManager"); - if (resendMessages.size() > 0){ - - TreeSet- * Initialise the properties file using SystemProperties.initWebapp(); - * and start Ebean. - *
+ * Do nothing on startup. */ public void contextInitialized(ServletContextEvent event) { - try { - ServletContext servletContext = event.getServletContext(); - GlobalProperties.setServletContext(servletContext); - - if (servletContext != null) { - String servletRealPath = servletContext.getRealPath(""); - GlobalProperties.put("servlet.realpath", servletRealPath); - logger.info("servlet.realpath=[" + servletRealPath + "]"); - } - - Ebean.getServer(null); - - } catch (Exception ex) { - ex.printStackTrace(); - } } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/TraditionalBackgroundExecutor.java b/src/main/java/com/avaje/ebeaninternal/server/core/TraditionalBackgroundExecutor.java deleted file mode 100644 index a8b3bb2bd..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/core/TraditionalBackgroundExecutor.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.avaje.ebeaninternal.server.core; - -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.avaje.ebeaninternal.api.SpiBackgroundExecutor; -import com.avaje.ebeaninternal.server.lib.DaemonScheduleThreadPool; -import com.avaje.ebeaninternal.server.lib.thread.ThreadPool; - -/** - * BackgroundExecutor using my traditional ThreadPool that will grow and trim. - * - * @author rbygrave - */ -public class TraditionalBackgroundExecutor implements SpiBackgroundExecutor { - - private static Logger logger = LoggerFactory.getLogger(TraditionalBackgroundExecutor.class); - - private final ThreadPool pool; - - private final DaemonScheduleThreadPool schedulePool; - - /** - * Construct the default implementation of BackgroundExecutor. - */ - public TraditionalBackgroundExecutor(ThreadPool pool, int schedulePoolSize, int shutdownWaitSeconds, String namePrefix) { - this.pool = pool; - this.schedulePool = new DaemonScheduleThreadPool(schedulePoolSize, shutdownWaitSeconds, namePrefix+"-periodic-"); - } - - /** - * Execute a Runnable using a background thread. - */ - public void execute(Runnable r) { - pool.assign(r, true); - } - - public void executePeriodically(Runnable r, long delay, TimeUnit unit) { - if (logger.isDebugEnabled()) { - logger.debug("Registering for executePeriodically {} delay:{} {}",r, delay, unit); - } - schedulePool.scheduleWithFixedDelay(r, delay, delay, unit); - } - - public void shutdown() { - if (logger.isDebugEnabled()) { - logger.debug("Shutting down"); - } - pool.shutdown(); - schedulePool.shutdown(); - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java index 8370f33d6..8099ffe9d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java @@ -1,25 +1,5 @@ package com.avaje.ebeaninternal.server.deploy; -import java.io.Serializable; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.persistence.MappedSuperclass; -import javax.persistence.PersistenceException; -import javax.persistence.Transient; -import javax.sql.DataSource; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.avaje.ebean.BackgroundExecutor; import com.avaje.ebean.Model; import com.avaje.ebean.RawSql; @@ -29,7 +9,6 @@ import com.avaje.ebean.bean.EntityBean; import com.avaje.ebean.cache.ServerCacheManager; import com.avaje.ebean.config.EncryptKey; import com.avaje.ebean.config.EncryptKeyManager; -import com.avaje.ebean.config.GlobalProperties; import com.avaje.ebean.config.NamingConvention; import com.avaje.ebean.config.dbplatform.DatabasePlatform; import com.avaje.ebean.config.dbplatform.DbIdentity; @@ -38,35 +17,31 @@ import com.avaje.ebean.config.dbplatform.IdType; import com.avaje.ebean.event.BeanFinder; import com.avaje.ebeaninternal.api.SpiEbeanServer; import com.avaje.ebeaninternal.api.TransactionEventTable; -import com.avaje.ebeaninternal.server.core.BootupClasses; -import com.avaje.ebeaninternal.server.core.InternString; -import com.avaje.ebeaninternal.server.core.InternalConfiguration; -import com.avaje.ebeaninternal.server.core.Message; -import com.avaje.ebeaninternal.server.core.XmlConfig; +import com.avaje.ebeaninternal.server.core.*; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType; import com.avaje.ebeaninternal.server.deploy.id.IdBinder; import com.avaje.ebeaninternal.server.deploy.id.IdBinderEmbedded; import com.avaje.ebeaninternal.server.deploy.id.IdBinderFactory; -import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor; -import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; -import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc; -import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany; -import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne; -import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanTable; -import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin; -import com.avaje.ebeaninternal.server.deploy.parse.DeployBeanInfo; -import com.avaje.ebeaninternal.server.deploy.parse.DeployCreateProperties; -import com.avaje.ebeaninternal.server.deploy.parse.DeployInherit; -import com.avaje.ebeaninternal.server.deploy.parse.DeployUtil; -import com.avaje.ebeaninternal.server.deploy.parse.ReadAnnotations; -import com.avaje.ebeaninternal.server.deploy.parse.TransientProperties; +import com.avaje.ebeaninternal.server.deploy.meta.*; +import com.avaje.ebeaninternal.server.deploy.parse.*; import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator; import com.avaje.ebeaninternal.server.lib.util.Dnode; +import com.avaje.ebeaninternal.server.properties.BeanPropertiesReader; import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo; import com.avaje.ebeaninternal.server.properties.BeanPropertyInfoFactory; -import com.avaje.ebeaninternal.server.properties.BeanPropertiesReader; import com.avaje.ebeaninternal.server.properties.EnhanceBeanPropertyInfoFactory; import com.avaje.ebeaninternal.server.type.TypeManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.persistence.MappedSuperclass; +import javax.persistence.PersistenceException; +import javax.persistence.Transient; +import javax.sql.DataSource; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.*; /** * Creates BeanDescriptors. @@ -153,6 +128,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap { private final BeanLifecycleAdapterFactory beanLifecycleAdapterFactory; + private final boolean eagerFetchLobs; + /** * Create for a given database dbConfig. */ @@ -167,6 +144,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap { this.encryptKeyManager = config.getServerConfig().getEncryptKeyManager(); this.databasePlatform = config.getServerConfig().getDatabasePlatform(); this.idBinderFactory = new IdBinderFactory(databasePlatform.isIdInExpandedForm()); + this.eagerFetchLobs = config.getServerConfig().isEagerFetchLobs(); this.bootupClasses = config.getBootupClasses(); this.createProperties = config.getDeployCreateProperties(); @@ -397,12 +375,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap { String msg = "SERIOUS ERROR: The hashCode() and equals() methods *MUST* be implemented "; msg += "on Embedded bean " + idType + " as it is used as an Id for " + beanType; - - if (GlobalProperties.getBoolean("ebean.strict", true)) { - throw new PersistenceException(msg, source); - } else { - logger.error(msg, source); - } + throw new PersistenceException(msg, source); } /** @@ -1017,7 +990,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap { DeployBeanInfo@@ -33,12 +31,9 @@ public final class ShutdownManager { static BootupEbeanManager serverFactory; - static boolean whyShutdown; - static { // Register the Shutdown hook registerShutdownHook(); - whyShutdown = GlobalProperties.getBoolean("debug.shutdown.why",false); } /** @@ -118,19 +113,11 @@ public final class ShutdownManager { logger.debug("Shutting down"); } - if (whyShutdown) { - try { - throw new RuntimeException("debug.shutdown.why=true ..."); - } catch (Throwable e) { - logger.warn("Stacktrace showing why shutdown was fired", e); - } - } - stopping = true; deregisterShutdownHook(); - String shutdownRunner = GlobalProperties.get("system.shutdown.runnable", null); + String shutdownRunner = System.getProperty("ebean.shutdown.runnable"); if (shutdownRunner != null) { try { // A custom runnable executed at the start of shutdown @@ -157,7 +144,7 @@ public final class ShutdownManager { } } - if (GlobalProperties.getBoolean("datasource.deregisterAllDrivers", false)) { + if ("true".equalsIgnoreCase(System.getProperty("ebean.datasource.deregisterAllDrivers", "false"))) { deregisterAllJdbcDrivers(); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/SimpleDataSourceAlert.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/SimpleDataSourceAlert.java index 17ff55537..694103be9 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/SimpleDataSourceAlert.java +++ b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/SimpleDataSourceAlert.java @@ -1,13 +1,11 @@ package com.avaje.ebeaninternal.server.lib.sql; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.avaje.ebean.config.GlobalProperties; import com.avaje.ebeaninternal.server.lib.util.MailEvent; import com.avaje.ebeaninternal.server.lib.util.MailListener; import com.avaje.ebeaninternal.server.lib.util.MailMessage; import com.avaje.ebeaninternal.server.lib.util.MailSender; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A simple smtp email alert that sends a email message on dataSourceDown and @@ -23,7 +21,11 @@ public class SimpleDataSourceAlert implements DataSourceAlert, MailListener { private static final Logger logger = LoggerFactory.getLogger(SimpleDataSourceAlert.class); - // boolean sendInBackGround = true; + private static String alertMailServerName = System.getProperty("ebean.datasource.alert.mailserver"); + + private static String fromUser = System.getProperty("ebean.datasource.alert.fromUser"); + private static String fromEmail = System.getProperty("ebean.datasource.alert.fromEmail"); + private static String toEmail = System.getProperty("ebean.datasource.alert.toEmail"); /** * Create a SimpleAlerter. @@ -79,15 +81,10 @@ public class SimpleDataSourceAlert implements DataSourceAlert, MailListener { private void sendMessage(String subject, String msg) { - String mailServerName = GlobalProperties.get("datasource.alert.mailserver", null); - if (mailServerName == null) { + if (alertMailServerName == null) { return; } - String fromUser = GlobalProperties.get("datasource.alert.fromuser", null); - String fromEmail = GlobalProperties.get("datasource.alert.fromemail", null); - String toEmail = GlobalProperties.get("datasource.alert.toemail", null); - MailMessage data = new MailMessage(); data.setSender(fromUser, fromEmail); data.addBodyLine(msg); @@ -95,15 +92,15 @@ public class SimpleDataSourceAlert implements DataSourceAlert, MailListener { String[] toList = toEmail.split(","); if (toList.length == 0) { - throw new RuntimeException("alert.toemail has not been set?"); + logger.error("alert.toemail has not been set?"); + } else { + for (int i = 0; i < toList.length; i++) { + data.addRecipient(null, toList[i].trim()); + } + MailSender sender = new MailSender(alertMailServerName); + sender.setMailListener(this); + sender.sendInBackground(data); } - for (int i = 0; i < toList.length; i++) { - data.addRecipient(null, toList[i].trim()); - } - - MailSender sender = new MailSender(mailServerName); - sender.setMailListener(this); - sender.sendInBackground(data); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/thread/PooledThread.java b/src/main/java/com/avaje/ebeaninternal/server/lib/thread/PooledThread.java deleted file mode 100644 index 201231152..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/lib/thread/PooledThread.java +++ /dev/null @@ -1,278 +0,0 @@ -package com.avaje.ebeaninternal.server.lib.thread; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A thread that belongs to a ThreadPool. It will return to the Threadpool when - * it has finished its assigned task. - */ -public class PooledThread implements Runnable { - - private static final Logger logger = LoggerFactory.getLogger(PooledThread.class); - - /** - * Flag to indicate that the thread was interrupted. - */ - private boolean wasInterrupted; - - /** - * The time the thread was last used. - */ - private long lastUsedTime; - - /** - * The work to run - */ - private Work work; - - /** - * Set to indicate the thread is stopping. - */ - private boolean isStopping; - - /** - * Set when the thread has stopped. - */ - private boolean isStopped; - /** - * The background thread. - */ - private Thread thread; - - /** - * The pool this worker belongs to. - */ - private ThreadPool threadPool; - - /** - * The name of the Thread - */ - private String name; - - /** - * The thread synchronization object. - */ - private Object threadMonitor = new Object(); - - /** - * The monitor for work notification. - */ - private Object workMonitor = new Object(); - - /** - * Total number of work performed. - */ - private int totalWorkCount; - - /** - * Total work execution time. - */ - private long totalWorkExecutionTime; - - /** - * Create the PooledThread. - */ - protected PooledThread(ThreadPool threadPool, String name, boolean isDaemon, Integer threadPriority) { - - this.name = name; - this.threadPool = threadPool; - this.lastUsedTime = System.currentTimeMillis(); - - thread = new Thread(this, name); - thread.setDaemon(isDaemon); - - if (threadPriority != null) { - thread.setPriority(threadPriority.intValue()); - } - } - - public String toString() { - return name; - } - - protected void start() { - thread.start(); - } - - /** - * Assign work to this thread. The thread will notify the listener when it has - * finished the work. - */ - public boolean assignWork(Work work) { - synchronized (workMonitor) { - this.work = work; - workMonitor.notifyAll(); - } - return true; - } - - /** - * process any assigned work until stopped or interrupted. - */ - public void run() { - // process assigned work until we receive a shutdown signal - synchronized (workMonitor) { - while (!isStopping) { - try { - if (work == null) { - workMonitor.wait(); - } - } catch (InterruptedException e) { - } - doTheWork(); - } - } - - // Tell stop() we have shut ourselves down successfully - synchronized (threadMonitor) { - threadMonitor.notifyAll(); - } - if (logger.isTraceEnabled()) { - logger.trace("PooledThread [" + getName() + "] finished "); - } - isStopped = true; - } - - /** - * Actually do the work and gather the appropriate measures. - */ - private void doTheWork() { - if (isStopping) { - return; - } - - long startTime = System.currentTimeMillis(); - if (work == null) { - // probably shutting down the thread - - } else { - try { - if (logger.isTraceEnabled()) { - logger.trace("start work "+work); - } - - work.setStartTime(startTime); - work.getRunnable().run(); - - if (logger.isTraceEnabled()) { - logger.trace("finished work "+work); - } - - } catch (Throwable ex) { - logger.error(null, ex); - - if (wasInterrupted) { - this.isStopping = true; - threadPool.removeThread(this); - if (logger.isInfoEnabled()) { - logger.info("PooledThread [" + name + "] removed due to interrupt"); - } - try { - thread.interrupt(); - } catch (Exception e) { - logger.error("Error interrupting PooledThead[" + name + "]", e); - } - return; - } - } - } - lastUsedTime = System.currentTimeMillis(); - totalWorkCount++; - totalWorkExecutionTime = totalWorkExecutionTime + lastUsedTime - startTime; - this.work = null; - threadPool.returnThread(this); - - } - - /** - * Try to interrupt the thread. - *
- * If the Thread was interrupted then it will be removed from the pool. - *
- */ - public void interrupt() { - - // set a flag so doTheWork knows that it was interrupted - // and removes rather than returns - wasInterrupted = true; - try { - if (logger.isTraceEnabled()) { - logger.trace("interrupt()"); - } - thread.interrupt(); - - } catch (SecurityException ex) { - wasInterrupted = false; - throw ex; - } - } - - /** - * Returns true if the thread has finished. - */ - public boolean isStopped() { - return isStopped; - } - - /** - * Stop the thread relatively nicely. It will wait a maximum of 10 seconds for - * it to complete any existing work. - */ - protected void stop() { - isStopping = true; - - synchronized (threadMonitor) { - - assignWork(null); - if (logger.isTraceEnabled()) { - logger.trace("stopping thread ["+name+"]"); - } - try { - threadMonitor.wait(10000); - } catch (InterruptedException e) { - ; - } - - } - - thread = null; - threadPool.removeThread(this); - } - - /** - * return the name of the thread. - */ - public String getName() { - return name; - } - - /** - * Returns the currently executing work, otherwise null. - */ - public Work getWork() { - return work; - } - - /** - * The total number of jobs this thread has run. - */ - public int getTotalWorkCount() { - return totalWorkCount; - } - - /** - * The total time for performing all assigned work. - */ - public long getTotalWorkExecutionTime() { - return totalWorkExecutionTime; - } - - /** - * Returns the time this thread was last used. - */ - public long getLastUsedTime() { - return lastUsedTime; - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/thread/ThreadPool.java b/src/main/java/com/avaje/ebeaninternal/server/lib/thread/ThreadPool.java deleted file mode 100644 index 76b123c12..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/lib/thread/ThreadPool.java +++ /dev/null @@ -1,502 +0,0 @@ -package com.avaje.ebeaninternal.server.lib.thread; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.avaje.ebean.config.GlobalProperties; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Vector; - -/** - * This is a pool of threads which can be assigned work. - *- * The Pool will automatically grow as required up to its maximum pool size. The - * Pool will be automatically shrink by trimming threads that have been idle for - * some time. - *
- */ -public class ThreadPool { - - private static final Logger logger = LoggerFactory.getLogger(ThreadPool.class); - - /** - * The max idle time used to trim idle threads from the pool. - */ - private long maxIdleTime; - - /** - * The name of the pool - */ - private String poolName; - - /** - * The initial pool size. - */ - private int minSize; - - /** - * Whether or not the threads are going to be Daemon threads. - */ - private boolean isDaemon; - - /** - * The priority or the threads. Can be null, in which case the threads have - * the default priority. - */ - private Integer threadPriority; - - /** - * Incrementing int for thread name. NB: currentThreadCount will go up and - * down as the pool grows and shrinks. - */ - private int uniqueThreadID; - - /** - * The maximum number of threads to grow to. Hitting this limit will have - * performance ramifications. - */ - private int maxSize = 100; - - /** - * Flag that the pool should terminate all the threads and stop. - */ - private boolean stopThePool; - - /** - * Flag to indicate that the pool is being shutdown. - */ - private boolean isStopping; - - /** - * List of PooledThread that are free for work. - */ - private Vector- * When the pool is fully busy... - *
- *
- * addToQueue=true -> work is added to queue, returns false
- * addToQueue=false -> work is not done or queued, returns false
- *
- * Returns the thread that was interrupted or null if the thread was not - * found. If the thread was interrupted then it will automatically be stopped - * and removed from the pool. - *
- *- * Note that it may take some time to actually interrupt the thread so an - * immediate test to see if the thread stopped will probably be wrong. - * - *
- *
- * ThreadPool test = ThreadPoolManager.getThreadPool("test");
- * PooledThread pt = test.interrupt("test.1");
- * if (pt == null) {
- * // the thread was not found, perhaps finished?
- * } else {
- * // give interrupt a little time to execute
- * Thread.sleep(1000);
- * boolean hasStopped = pt.isStopped();
- * //..
- * }
- *
- *
- *
- *
- *
- * @return the thread that was interrupted
- */
- public PooledThread interrupt(String threadName) {
- PooledThread thread = getBusyThread(threadName);
- if (thread != null) {
- thread.interrupt();
- return thread;
- }
- return null;
- }
-
- /**
- * Find a thread using its name from the busy list. Returns null if the thread
- * is not found in the busy list.
- */
- public PooledThread getBusyThread(String threadName) {
- synchronized (freeList) {
- IteratorUsed to maintains some useful times about the Runnable in terms of when - * it was queued and then eventually run.
- */ -public class Work { - - /** - * Create a Runnable Work. - */ - public Work(Runnable runnable) { - this.runnable = runnable; - } - - /** - * Return the associated Runnable object. - */ - public Runnable getRunnable() { - return runnable; - } - - /** - * Return the time this work actually started. - */ - public long getStartTime() { - return startTime; - } - - /** - * Sets the time this work actually started. - */ - public void setStartTime(long startTime) { - this.startTime = startTime; - } - - /** - * Return the time this entered the queue. - */ - public long getEnterQueueTime() { - return enterQueueTime; - } - - /** - * Set the time this entered the queue. - */ - public void setEnterQueueTime(long enterQueueTime) { - this.enterQueueTime = enterQueueTime; - } - - /** - * Return the time this left the queue. - */ - public long getExitQueueTime() { - return exitQueueTime; - } - - /** - * Set the time this work left the queue. - */ - public void setExitQueueTime(long exitQueueTime) { - this.exitQueueTime = exitQueueTime; - } - - /** - * The same as getDescription(). - */ - public String toString() { - return getDescription(); - } - - /** - * Return a description of this work. - */ - public String getDescription() { - - StringBuffer sb = new StringBuffer(); - sb.append("Work["); - if (runnable != null){ - sb.append(runnable.toString()); - } - sb.append("]"); - return sb.toString(); - } - - private Runnable runnable; - - private long exitQueueTime; - private long enterQueueTime; - private long startTime; - -}; diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/thread/package.html b/src/main/java/com/avaje/ebeaninternal/server/lib/thread/package.html deleted file mode 100644 index c4e83e0d0..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/lib/thread/package.html +++ /dev/null @@ -1,12 +0,0 @@ - - - --Service providing thread pooling for executing background tasks. -
- - \ No newline at end of file diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersistExecute.java b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersistExecute.java index 82bcd209b..76607d7ad 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersistExecute.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersistExecute.java @@ -1,13 +1,8 @@ package com.avaje.ebeaninternal.server.persist; -import com.avaje.ebean.config.GlobalProperties; import com.avaje.ebean.event.BeanPersistController; import com.avaje.ebeaninternal.api.SpiTransaction; -import com.avaje.ebeaninternal.server.core.PersistRequestBean; -import com.avaje.ebeaninternal.server.core.PersistRequestCallableSql; -import com.avaje.ebeaninternal.server.core.PersistRequestOrmUpdate; -import com.avaje.ebeaninternal.server.core.PersistRequestUpdateSql; -import com.avaje.ebeaninternal.server.core.PstmtBatch; +import com.avaje.ebeaninternal.server.core.*; import com.avaje.ebeaninternal.server.deploy.BeanManager; /** @@ -32,19 +27,17 @@ public final class DefaultPersistExecute implements PersistExecute { /** * Default for whether to call getGeneratedKeys after batch insert. */ - private final boolean defaultBatchGenKeys; + private final boolean defaultBatchGenKeys = true; /** * Construct this DmlPersistExecute. */ - public DefaultPersistExecute(Binder binder, PstmtBatch pstmtBatch) { + public DefaultPersistExecute(Binder binder, PstmtBatch pstmtBatch, int defaultBatchSize) { this.exeOrmUpdate = new ExeOrmUpdate(binder, pstmtBatch); this.exeUpdateSql = new ExeUpdateSql(binder, pstmtBatch); this.exeCallableSql = new ExeCallableSql(binder, pstmtBatch); - - this.defaultBatchGenKeys = GlobalProperties.getBoolean("batch.getgeneratedkeys", true); - this.defaultBatchSize = GlobalProperties.getInt("batch.size", 20); + this.defaultBatchSize = defaultBatchSize; } public BatchControl createBatchControl(SpiTransaction t) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java index b77f424b7..c7d3a076c 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java @@ -79,7 +79,7 @@ public final class DefaultPersister implements Persister { this.server = server; this.updatesDeleteMissingChildren = server.getServerConfig().isUpdatesDeleteMissingChildren(); this.beanDescriptorManager = descMgr; - this.persistExecute = new DefaultPersistExecute(binder, pstmtBatch); + this.persistExecute = new DefaultPersistExecute(binder, pstmtBatch, server.getServerConfig().getPersistBatchSize()); } /** @@ -182,7 +182,6 @@ public final class DefaultPersister implements Persister { } req.commitTransIfRequired(); - return; } catch (RuntimeException ex) { req.rollbackTransIfRequired(); @@ -469,7 +468,7 @@ public final class DefaultPersister implements Persister { int rows = executeSqlUpdate(deleteById, t); // Delete from the persistence context so that it can't be fetched again later - PersistenceContext persistenceContext = ((SpiTransaction)t).getPersistenceContext(); + PersistenceContext persistenceContext = t.getPersistenceContext(); if (idList != null) { for (Object idValue : idList) { persistenceContext.deleted(descriptor.getBeanType(), idValue); @@ -879,7 +878,7 @@ public final class DefaultPersister implements Persister { Collection> additions = null; Collection> deletions = null; - boolean vanillaCollection = (value instanceof BeanCollection> == false); + boolean vanillaCollection = !(value instanceof BeanCollection>); if (vanillaCollection || deleteMissingChildren) { // delete all intersection rows and then treat all diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java index e1341b3a8..6c0855ed1 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java @@ -2,7 +2,6 @@ package com.avaje.ebeaninternal.server.query; import com.avaje.ebean.QueryIterator; import com.avaje.ebean.bean.*; -import com.avaje.ebean.config.GlobalProperties; import com.avaje.ebeaninternal.api.SpiExpressionList; import com.avaje.ebeaninternal.api.SpiQuery; import com.avaje.ebeaninternal.api.SpiQuery.Mode; @@ -45,7 +44,7 @@ public class CQuery@@ -50,7 +46,7 @@ public class ResourceManagerFactory { String dir = null; if (serverConfig.getAutofetchConfig() != null) { - dir = serverConfig.getAutofetchConfig().getLogDirectoryWithEval(); + dir = serverConfig.getAutofetchConfig().getLogDirectory(); } if (dir != null) { return new File(dir); @@ -75,18 +71,7 @@ public class ResourceManagerFactory { // default for web application, override this for file system String defaultDir = serverConfig.getResourceDirectory(); - - - // the default... check if a webapp first... - ServletContext sc = GlobalProperties.getServletContext(); - if (sc != null) { - // servlet container so use ServletContext.getResource() - if (defaultDir == null) { - defaultDir = "WEB-INF/ebean"; - } - return new UrlResourceSource(sc, defaultDir); - } // use File System directory return createFileSource(defaultDir); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/IndexEvent.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/IndexEvent.java deleted file mode 100644 index 9a42063fe..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/IndexEvent.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.DataInput; -import java.io.DataOutputStream; -import java.io.IOException; - -import com.avaje.ebeaninternal.server.cluster.BinaryMessage; -import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; - -public class IndexEvent { - - public static final int COMMIT_EVENT = 1; - public static final int OPTIMISE_EVENT = 2; - - private final int eventType; - private final String indexName; - - public IndexEvent(int eventType, String indexName) { - this.eventType = eventType; - this.indexName = indexName; - } - - public int getEventType() { - return eventType; - } - - public String getIndexName() { - return indexName; - } - - public static IndexEvent readBinaryMessage(DataInput dataInput) throws IOException { - - int eventType = dataInput.readInt(); - String indexName = dataInput.readUTF(); - return new IndexEvent(eventType, indexName); - } - - public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { - - BinaryMessage msg = new BinaryMessage(indexName.length()+10); - DataOutputStream os = msg.getOs(); - os.writeInt(BinaryMessage.TYPE_INDEX); - os.writeInt(eventType); - os.writeUTF(indexName); - - msgList.add(msg); - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/IndexInvalidate.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/IndexInvalidate.java deleted file mode 100644 index 1f3ca7c7d..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/IndexInvalidate.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.DataInput; -import java.io.DataOutputStream; -import java.io.IOException; - -import com.avaje.ebeaninternal.server.cluster.BinaryMessage; -import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; - -public class IndexInvalidate { - - private final String indexName; - - public IndexInvalidate(String indexName) { - this.indexName = indexName; - } - - public String getIndexName() { - return indexName; - } - - @Override - public int hashCode() { - int hc = IndexInvalidate.class.hashCode(); - hc = hc * 31 + indexName.hashCode(); - return hc; - } - - @Override - public boolean equals(Object o){ - if (o instanceof IndexInvalidate == false){ - return false; - } - return indexName.equals(((IndexInvalidate)o).indexName); - } - - public static IndexInvalidate readBinaryMessage(DataInput dataInput) throws IOException { - - - String indexName = dataInput.readUTF(); - return new IndexInvalidate(indexName); - } - - public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { - - BinaryMessage msg = new BinaryMessage(indexName.length()+10); - DataOutputStream os = msg.getOs(); - os.writeInt(BinaryMessage.TYPE_INDEX_INVALIDATE); - os.writeUTF(indexName); - - msgList.add(msg); - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/PostCommitProcessing.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/PostCommitProcessing.java index b8523d0d3..2243ca4ef 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/PostCommitProcessing.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/PostCommitProcessing.java @@ -1,9 +1,5 @@ package com.avaje.ebeaninternal.server.transaction; -import java.util.List; -import java.util.Set; - -import com.avaje.ebeaninternal.api.SpiTransaction; import com.avaje.ebeaninternal.api.TransactionEvent; import com.avaje.ebeaninternal.api.TransactionEventBeans; import com.avaje.ebeaninternal.api.TransactionEventTable; @@ -14,6 +10,8 @@ import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; + /** * Performs post commit processing using a background thread. *
@@ -36,8 +34,6 @@ public final class PostCommitProcessing {
private final BeanPersistIdMap beanPersistIdMap;
-// private final BeanDeltaMap beanDeltaMap;
-
private final RemoteTransactionEvent remoteTransactionEvent;
private final DeleteByIdMap deleteByIdMap;
@@ -45,7 +41,7 @@ public final class PostCommitProcessing {
/**
* Create for a TransactionManager and event.
*/
- public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, SpiTransaction transaction, TransactionEvent event) {
+ public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, TransactionEvent event) {
this.clusterManager = clusterManager;
this.manager = manager;
@@ -53,10 +49,7 @@ public final class PostCommitProcessing {
this.event = event;
this.deleteByIdMap = event.getDeleteByIdMap();
this.persistBeanRequests = createPersistBeanRequests();
-
this.beanPersistIdMap = createBeanPersistIdMap();
- //this.beanDeltaMap = new BeanDeltaMap(event.getBeanDeltas());
-
this.remoteTransactionEvent = createRemoteTransactionEvent();
}
@@ -87,8 +80,8 @@ public final class PostCommitProcessing {
public void notifyCluster() {
if (remoteTransactionEvent != null && !remoteTransactionEvent.isEmpty()) {
// send the interesting events to the cluster
- if (manager.getClusterDebugLevel() > 0 || logger.isDebugEnabled()) {
- logger.info("Cluster Send: " + remoteTransactionEvent.toString());
+ if (logger.isDebugEnabled()) {
+ logger.debug("Cluster Send: {}", remoteTransactionEvent);
}
clusterManager.broadcast(remoteTransactionEvent);
@@ -147,12 +140,6 @@ public final class PostCommitProcessing {
RemoteTransactionEvent remoteTransactionEvent = new RemoteTransactionEvent(serverName);
-// if (beanDeltaMap != null) {
-// for (BeanDeltaList deltaList : beanDeltaMap.deltaLists()) {
-// remoteTransactionEvent.addBeanDeltaList(deltaList);
-// }
-// }
-
if (beanPersistIdMap != null) {
for (BeanPersistIds beanPersist : beanPersistIdMap.values()) {
remoteTransactionEvent.addBeanPersistIds(beanPersist);
@@ -170,13 +157,6 @@ public final class PostCommitProcessing {
}
}
- Set