You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by da...@apache.org on 2013/10/23 21:44:00 UTC
[43/47] git commit: updated refs/heads/master to c910196
Merge remote-tracking branch 'origin/spring-modularization'
Conflicts:
client/tomcatconf/applicationContext.xml.in
client/tomcatconf/nonossComponentContext.xml.in
client/tomcatconf/simulatorComponentContext.xml.in
framework/db/src/com/cloud/utils/db/Transaction.java
plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java
server/src/com/cloud/api/ApiServer.java
server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/e3280bdb
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e3280bdb
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e3280bdb
Branch: refs/heads/master
Commit: e3280bdba2ecfe1c1c2265b02502fef32695c2e6
Parents: 80509f9 d769a73
Author: Darren Shepherd <da...@gmail.com>
Authored: Wed Oct 23 11:14:42 2013 -0700
Committer: Darren Shepherd <da...@gmail.com>
Committed: Wed Oct 23 11:14:42 2013 -0700
----------------------------------------------------------------------
.../cloudstack/api-planner/module.properties | 2 +
.../api-planner/spring-api-planner-context.xml | 34 +
.../apache/cloudstack/context/CallContext.java | 2 +-
client/WEB-INF/web.xml | 6 +-
client/pom.xml | 56 +-
.../cloudstack/webApplicationContext.xml | 32 +
client/tomcatconf/applicationContext.xml.in | 956 -------------------
client/tomcatconf/componentContext.xml.in | 324 -------
client/tomcatconf/log4j-cloud.xml.in | 8 +
client/tomcatconf/nonossComponentContext.xml.in | 422 --------
.../tomcatconf/simulatorComponentContext.xml.in | 284 ------
.../cloudstack/allocator/module.properties | 2 +
.../allocator/spring-core-allocator-context.xml | 32 +
...-lifecycle-allocator-context-inheritable.xml | 42 +
.../META-INF/cloudstack/api/module.properties | 2 +
...g-core-lifecycle-api-context-inheritable.xml | 53 +
.../cloudstack/backend/module.properties | 2 +
.../cloudstack/bootstrap/module.properties | 1 +
.../spring-bootstrap-context-inheritable.xml | 39 +
.../bootstrap/spring-bootstrap-context.xml | 32 +
.../cloudstack/compute/module.properties | 2 +
...re-lifecycle-compute-context-inheritable.xml | 45 +
.../META-INF/cloudstack/core/module.properties | 2 +
.../cloudstack/core/spring-core-context.xml | 36 +
...-core-lifecycle-core-context-inheritable.xml | 41 +
.../core/spring-core-registry-core-context.xml | 197 ++++
.../cloudstack/discoverer/module.properties | 2 +
...lifecycle-discoverer-context-inheritable.xml | 35 +
.../cloudstack/network/module.properties | 2 +
...re-lifecycle-network-context-inheritable.xml | 58 ++
.../cloudstack/planner/module.properties | 2 +
...re-lifecycle-planner-context-inheritable.xml | 41 +
.../cloudstack/storage/module.properties | 2 +
...ng-lifecycle-storage-context-inheritable.xml | 74 ++
.../cloudstack/system/module.properties | 2 +
.../spring-core-system-context-inheritable.xml | 54 ++
.../system/spring-core-system-context.xml | 50 +
.../core/spring-engine-api-core-context.xml | 44 +
...pring-engine-components-api-core-context.xml | 30 +
...spring-engine-orchestration-core-context.xml | 71 ++
.../spring-engine-schema-core-daos-context.xml | 321 +++++++
...ng-engine-schema-system-checkers-context.xml | 34 +
.../cloud/upgrade/DatabaseUpgradeChecker.java | 3 +
...spring-engine-storage-cache-core-context.xml | 38 +
...g-engine-storage-datamotion-core-context.xml | 35 +
...ngine-storage-datamotion-storage-context.xml | 34 +
.../storage/motion/DataMotionServiceImpl.java | 7 +-
...spring-engine-storage-image-core-context.xml | 45 +
.../core/spring-engine-storage-core-context.xml | 63 ++
.../storage-allocator/module.properties | 2 +
...engine-storage-storage-allocator-context.xml | 49 +
...ing-engine-storage-snapshot-core-context.xml | 41 +
...-engine-storage-snapshot-storage-context.xml | 33 +
.../provider/DataStoreProviderManagerImpl.java | 112 ++-
...pring-engine-storage-volume-core-context.xml | 49 +
.../spring-framework-cluster-core-context.xml | 36 +
...mework-config-system-context-inheritable.xml | 38 +
.../spring-framework-config-system-context.xml | 51 +
.../framework/config/ConfigDepotAdmin.java | 2 +
.../config/dao/ConfigurationDaoImpl.java | 9 +
.../framework/config/impl/ConfigDepotImpl.java | 98 +-
.../config/impl/ConfigDepotAdminTest.java | 1 +
.../spring-framework-db-system-context.xml | 32 +
.../utils/db/TransactionContextInterceptor.java | 39 +
.../utils/db/TransactionContextListener.java | 41 +
.../com/cloud/utils/db/TransactionLegacy.java | 4 +-
.../core/spring-framework-ipc-core-context.xml | 59 ++
.../core/spring-framework-jobs-core-context.xml | 48 +
framework/pom.xml | 2 +
framework/spring/lifecycle/pom.xml | 34 +
.../spring/lifecycle/AbstractBeanCollector.java | 113 +++
.../lifecycle/AbstractSmartLifeCycle.java | 53 +
.../lifecycle/CloudStackExtendedLifeCycle.java | 169 ++++
.../CloudStackExtendedLifeCycleStart.java | 49 +
.../spring/lifecycle/CloudStackLog4jSetup.java | 56 ++
.../spring/lifecycle/ConfigDepotLifeCycle.java | 47 +
.../spring/lifecycle/registry/DumpRegistry.java | 77 ++
.../lifecycle/registry/ExtensionRegistry.java | 245 +++++
.../registry/PluggableServiceLifecycle.java | 53 +
.../lifecycle/registry/RegistryLifecycle.java | 144 +++
framework/spring/module/pom.xml | 50 +
.../context/ResourceApplicationContext.java | 55 ++
.../module/factory/CloudStackSpringContext.java | 137 +++
.../factory/ModuleBasedContextFactory.java | 84 ++
.../module/locator/ModuleDefinitionLocator.java | 36 +
.../impl/ClasspathModuleDefinitionLocator.java | 62 ++
.../spring/module/model/ModuleDefinition.java | 48 +
.../module/model/ModuleDefinitionSet.java | 32 +
.../model/impl/DefaultModuleDefinition.java | 167 ++++
.../model/impl/DefaultModuleDefinitionSet.java | 243 +++++
.../cloudstack/spring/module/util/Main.java | 58 ++
.../spring/module/util/ModuleLocationUtils.java | 53 +
.../web/CloudStackContextLoaderListener.java | 75 ++
.../module/model/impl/defaults-context.xml | 28 +
.../spring/module/factory/InitTest.java | 39 +
.../factory/ModuleBasedContextFactoryTest.java | 121 +++
...ClasspathModuleDefinitionSetLocatorTest.java | 40 +
.../model/impl/DefaultModuleDefinitionTest.java | 131 +++
.../resources/testfiles/all/defaults.properties | 18 +
.../testfiles/all/empty-context-inheritable.xml | 26 +
.../resources/testfiles/all/empty-context.xml | 26 +
.../all/empty2-context-inheritable.xml | 26 +
.../resources/testfiles/all/empty2-context.xml | 26 +
.../resources/testfiles/all/module.properties | 17 +
.../testfiles/all/test2-defaults.properties | 17 +
.../testfiles/badname/module.properties | 17 +
.../testfiles/blankname/module.properties | 18 +
.../resources/testfiles/good/empty-context.xml | 26 +
.../resources/testfiles/good/module.properties | 17 +
.../testfiles/missingname/module.properties | 17 +
.../testfiles/wrongname/module.properties | 17 +
.../testhierarchy/base/module.properties | 17 +
.../base/test-context-inheritable.xml | 28 +
.../testhierarchy/base/test-context.xml | 34 +
.../testhierarchy/child1-1/module.properties | 18 +
.../testhierarchy/child1-1/test-context.xml | 34 +
.../testhierarchy/child1/module.properties | 18 +
.../child1/test-context-override.xml | 30 +
.../testhierarchy/child1/test-context.xml | 38 +
.../testhierarchy/child2/module.properties | 18 +
.../testhierarchy/child2/test-context.xml | 33 +
.../testhierarchy/orphan1/module.properties | 18 +
.../testhierarchy/orphan1/test-context.xml | 30 +
packaging/centos63/cloud.spec | 3 +-
.../acl-static-role-based/module.properties | 2 +
.../spring-acl-static-role-based-context.xml | 34 +
.../explicit-dedication/module.properties | 2 +
.../spring-explicit-dedication-context.xml | 36 +
.../host-anti-affinity/module.properties | 2 +
.../spring-host-anti-affinity-context.xml | 37 +
.../discovery/ApiDiscoveryServiceImpl.java | 65 +-
.../cloudstack/discovery/ApiDiscoveryTest.java | 2 +-
.../cloudstack/rate-limit/module.properties | 2 +
.../rate-limit/spring-rate-limit-context.xml | 32 +
.../spring-dedicated-resources-core-context.xml | 33 +
.../implicit-dedication/module.properties | 2 +
.../spring-implicit-dedication-context.xml | 25 +
.../user-concentrated-pod/module.properties | 2 +
.../spring-user-concentrated-pod-context.xml | 35 +
.../host-allocator-random/module.properties | 2 +
.../spring-host-allocator-random-context.xml | 34 +
.../baremetal-compute/module.properties | 2 +
.../spring-baremetal-compute-context.xml | 35 +
.../baremetal-discoverer/module.properties | 2 +
.../spring-baremetal-discoverer-context.xml | 34 +
.../baremetal-network/module.properties | 2 +
.../spring-baremetal-network-context.xml | 46 +
.../baremetal-planner/module.properties | 2 +
.../spring-baremetal-planner-context.xml | 34 +
.../baremetal-storage/module.properties | 2 +
.../spring-baremetal-storage-context.xml | 32 +
.../core/spring-baremetal-core-context.xml | 42 +
.../cloudstack/kvm-compute/module.properties | 2 +
.../kvm-compute/spring-kvm-compute-context.xml | 34 +
.../cloudstack/ovm-compute/module.properties | 2 +
.../ovm-compute/spring-ovm-compute-context.xml | 39 +
.../cloudstack/ovm-discoverer/module.properties | 2 +
.../spring-ovm-discoverer-context.xml | 34 +
.../core/spring-simulator-core-context.xml | 45 +
.../simulator-compute/module.properties | 2 +
.../spring-simulator-compute-context.xml | 34 +
.../simulator-discoverer/module.properties | 2 +
.../spring-simulator-discover-context.xml | 36 +
.../simulator-planner/module.properties | 2 +
.../simulator-planner/spring-context.xml | 34 +
.../simulator-storage/module.properties | 2 +
.../spring-simulator-storage-context.xml | 33 +
.../agent/manager/MockAgentManagerImpl.java | 72 +-
.../cloudstack/core/spring-ucs-core-context.xml | 35 +
.../core/spring-vmware-core-context.xml | 43 +
.../cloudstack/vmware-compute/module.properties | 2 +
.../spring-vmware-compute-context.xml | 43 +
.../vmware-compute/vmware-defaults.properties | 1 +
.../vmware-discoverer/module.properties | 2 +
.../spring-vmware-discoverer-context.xml | 35 +
.../cloudstack/vmware-network/module.properties | 2 +
.../spring-vmware-network-context.xml | 34 +
.../cloudstack/vmware-storage/module.properties | 2 +
.../spring-vmware-storage-context.xml | 33 +
.../vmware/VmwareServerDiscoverer.java | 33 +-
.../xenserver-compute/module.properties | 2 +
.../spring-xenserver-compute-context.xml | 28 +
.../xenserver-discoverer/module.properties | 2 +
.../spring-xenserver-discoverer-context.xml | 25 +
.../META-INF/cloudstack/vns/module.properties | 2 +
.../cloudstack/vns/spring-vns-context.xml | 36 +
.../META-INF/cloudstack/elb/module.properties | 2 +
.../cloudstack/elb/spring-elb-context.xml | 34 +
.../core/spring-internallb-core-context.xml | 37 +
.../cloudstack/midonet/module.properties | 2 +
.../midonet/spring-midonet-context.xml | 37 +
.../META-INF/cloudstack/nvp/module.properties | 2 +
.../cloudstack/nvp/spring-nvp-context.xml | 40 +
.../META-INF/cloudstack/ovs/module.properties | 2 +
.../cloudstack/ovs/spring-ovs-context.xml | 40 +
.../META-INF/cloudstack/ssp/module.properties | 2 +
.../cloudstack/ssp/spring-ssp-context.xml | 42 +
.../META-INF/cloudstack/vxlan/module.properties | 2 +
.../cloudstack/vxlan/spring-vxlan-context.xml | 34 +
.../storage-image-default/module.properties | 2 +
.../spring-storage-image-default-context.xml | 33 +
.../storage-image-s3/module.properties | 2 +
.../spring-storage-image-s3-context.xml | 34 +
.../storage-image-swift/module.properties | 2 +
.../spring-storage-image-swift-context.xml | 33 +
.../storage-volume-default/module.properties | 2 +
.../spring-storage-volume-default-context.xml | 35 +
.../storage-volume-solidfire/module.properties | 2 +
.../spring-storage-volume-solidfire-context.xml | 33 +
.../META-INF/cloudstack/ldap/module.properties | 2 +
.../cloudstack/ldap/spring-ldap-context.xml | 39 +
.../META-INF/cloudstack/md5/module.properties | 2 +
.../cloudstack/md5/spring-md5-context.xml | 34 +
.../cloudstack/plaintext/module.properties | 2 +
.../plaintext/spring-plaintext-context.xml | 35 +
.../cloudstack/sha256salted/module.properties | 2 +
.../spring-sha256salted-context.xml | 34 +
pom.xml | 15 +-
quickcloud/pom.xml | 30 +
.../spring-quickcloud-core-context-override.xml | 32 +
server/pom.xml | 3 -
.../spring-server-core-managers-context.xml | 216 +++++
.../core/spring-server-core-misc-context.xml | 68 ++
.../module.properties | 2 +
...ing-server-alert-adapter-backend-context.xml | 32 +
.../module.properties | 2 +
...ing-server-alert-adapter-compute-context.xml | 32 +
.../module.properties | 2 +
...ing-server-alert-adapter-storage-context.xml | 32 +
.../server-allocator/module.properties | 2 +
.../spring-server-allocator-context.xml | 48 +
.../cloudstack/server-api/module.properties | 2 +
.../server-api/spring-server-api-context.xml | 33 +
.../cloudstack/server-compute/module.properties | 2 +
.../spring-server-compute-context.xml | 38 +
.../server-discoverer/module.properties | 2 +
.../spring-server-discoverer-context.xml | 45 +
.../cloudstack/server-fencer/module.properties | 2 +
.../spring-server-fencer-context.xml | 37 +
.../server-investigator/module.properties | 2 +
.../spring-server-investigator-context.xml | 46 +
.../cloudstack/server-network/module.properties | 2 +
.../spring-server-network-context.xml | 64 ++
.../cloudstack/server-planner/module.properties | 2 +
.../spring-server-planner-context.xml | 34 +
.../cloudstack/server-storage/module.properties | 2 +
.../spring-server-storage-context.xml | 34 +
.../server-template-adapter/module.properties | 2 +
.../spring-server-template-adapter-context.xml | 32 +
server/src/com/cloud/api/ApiServer.java | 6 +-
.../consoleproxy/StaticConsoleProxyManager.java | 3 +
.../com/cloud/event/ActionEventInterceptor.java | 33 +-
.../com/cloud/network/vpc/VpcManagerImpl.java | 7 +-
.../com/cloud/resource/ResourceManagerImpl.java | 8 +
.../storage/snapshot/SnapshotManagerImpl.java | 14 +-
.../module.properties | 2 +
...ing-secondary-storage-discoverer-context.xml | 36 +
utils/pom.xml | 4 +
.../cloud/utils/component/ComponentContext.java | 27 +-
259 files changed, 8339 insertions(+), 2150 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/api/src/org/apache/cloudstack/context/CallContext.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDaoImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/framework/db/src/com/cloud/utils/db/TransactionLegacy.java
----------------------------------------------------------------------
diff --cc framework/db/src/com/cloud/utils/db/TransactionLegacy.java
index ffa0670,0000000..9cf7c3f
mode 100755,000000..100755
--- a/framework/db/src/com/cloud/utils/db/TransactionLegacy.java
+++ b/framework/db/src/com/cloud/utils/db/TransactionLegacy.java
@@@ -1,1192 -1,0 +1,1194 @@@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.utils.db;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.KeyedObjectPoolFactory;
+import org.apache.commons.pool.impl.GenericObjectPool;
+import org.apache.commons.pool.impl.StackKeyedObjectPoolFactory;
+import org.apache.log4j.Logger;
+import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
+import org.jasypt.properties.EncryptableProperties;
+
+import com.cloud.utils.Pair;
+import com.cloud.utils.PropertiesUtil;
+import com.cloud.utils.crypt.EncryptionSecretKeyChecker;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.mgmt.JmxUtil;
+
+/**
+ * Transaction abstracts away the Connection object in JDBC. It allows the
+ * following things that the Connection object does not.
+ *
+ * 1. Transaction can be started at an entry point and whether the DB
+ * actions should be auto-commit or not determined at that point.
+ * 2. DB Connection is allocated only when it is needed.
+ * 3. Code does not need to know if a transaction has been started or not.
+ * It just starts/ends a transaction and we resolve it correctly with
+ * the previous actions.
+ *
+ * Note that this class is not synchronous but it doesn't need to be because
+ * it is stored with TLS and is one per thread. Use appropriately.
+ */
+public class TransactionLegacy {
+ private static final Logger s_logger = Logger.getLogger(Transaction.class.getName() + "." + "Transaction");
+ private static final Logger s_stmtLogger = Logger.getLogger(Transaction.class.getName() + "." + "Statement");
+ private static final Logger s_lockLogger = Logger.getLogger(Transaction.class.getName() + "." + "Lock");
+ private static final Logger s_connLogger = Logger.getLogger(Transaction.class.getName() + "." + "Connection");
+
+ private static final ThreadLocal<TransactionLegacy> tls = new ThreadLocal<TransactionLegacy>();
+ private static final String START_TXN = "start_txn";
+ private static final String CURRENT_TXN = "current_txn";
+ private static final String CREATE_TXN = "create_txn";
+ private static final String CREATE_CONN = "create_conn";
+ private static final String STATEMENT = "statement";
+ private static final String ATTACHMENT = "attachment";
+
+ public static final short CLOUD_DB = 0;
+ public static final short USAGE_DB = 1;
+ public static final short AWSAPI_DB = 2;
+ public static final short SIMULATOR_DB = 3;
+
+ public static final short CONNECTED_DB = -1;
+
+ private static AtomicLong s_id = new AtomicLong();
+ private static final TransactionMBeanImpl s_mbean = new TransactionMBeanImpl();
+ static {
+ try {
+ JmxUtil.registerMBean("Transaction", "Transaction", s_mbean);
+ } catch (Exception e) {
+ s_logger.error("Unable to register mbean for transaction", e);
+ }
+
+ /* FIXME: We need a better solution for this
+ * Initialize encryption if we need it for db.properties
+ */
+ EncryptionSecretKeyChecker enc = new EncryptionSecretKeyChecker();
+ enc.check();
+ }
+
+ private final LinkedList<StackElement> _stack;
+ private long _id;
+
+ private final LinkedList<Pair<String, Long>> _lockTimes = new LinkedList<Pair<String, Long>>();
+
+ private String _name;
+ private Connection _conn;
+ private boolean _txn;
+ private short _dbId;
+ private long _txnTime;
+ private Statement _stmt;
+ private String _creator;
+
+ private TransactionLegacy _prev = null;
+
+ public static TransactionLegacy currentTxn() {
+ return currentTxn(true);
+ }
+
+ protected static TransactionLegacy currentTxn(boolean check) {
+ TransactionLegacy txn = tls.get();
+ if (check) {
+ assert txn != null : "No Transaction on stack. Did you mark the method with @DB?";
+
+ assert checkAnnotation(4, txn) : "Did you even read the guide to use Transaction...IOW...other people's code? Try method can't be private. What about @DB? hmmm... could that be it? " + txn;
+ }
+ return txn;
+ }
+
+ public static TransactionLegacy open(final short databaseId) {
+ String name = buildName();
+ if (name == null) {
+ name = CURRENT_TXN;
+ }
+ return open(name, databaseId, true);
+ }
+
+ //
+ // Usage of this transaction setup should be limited, it will always open a new transaction context regardless of whether or not there is other
+ // transaction context in the stack. It is used in special use cases that we want to control DB connection explicitly and in the mean time utilize
+ // the existing DAO features
+ //
+ public void transitToUserManagedConnection(Connection conn) {
- assert(_conn == null /*&& _stack.size() <= 1*/) : "Can't change to a user managed connection unless the stack is empty and the db connection is null, you may have forgotten to invoke transitToAutoManagedConnection to close out the DB connection: " + toString();
++ if ( _conn != null )
++ throw new IllegalStateException("Can't change to a user managed connection unless the db connection is null");
++
+ _conn = conn;
+ _dbId = CONNECTED_DB;
+ }
+
+ public void transitToAutoManagedConnection(short dbId) {
+ // assert(_stack.size() <= 1) : "Can't change to auto managed connection unless your stack is empty";
+ _dbId = dbId;
+ _conn = null;
+ }
+
+ public static TransactionLegacy open(final String name) {
+ return open(name, TransactionLegacy.CLOUD_DB, false);
+ }
+
+ public static TransactionLegacy open(final String name, final short databaseId, final boolean forceDbChange) {
+ TransactionLegacy txn = tls.get();
+ boolean isNew = false;
+ if (txn == null) {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Creating the transaction: " + name);
+ }
+ txn = new TransactionLegacy(name, false, databaseId);
+ tls.set(txn);
+ isNew = true;
+ } else if (forceDbChange) {
+ final short currentDbId = txn.getDatabaseId();
+ if (currentDbId != databaseId) {
+ // we need to end the current transaction and switch databases
+ txn.close(txn.getName());
+
+ txn = new TransactionLegacy(name, false, databaseId);
+ tls.set(txn);
+ isNew = true;
+ }
+ }
+
+ txn.takeOver(name, false);
+ if (isNew) {
+ s_mbean.addTransaction(txn);
+ }
+ return txn;
+ }
+
+ protected StackElement peekInStack(Object obj) {
+ final Iterator<StackElement> it = _stack.iterator();
+ while (it.hasNext()) {
+ StackElement next = it.next();
+ if (next.type == obj) {
+ return next;
+ }
+ }
+ return null;
+ }
+
+ public void registerLock(String sql) {
+ if (_txn && s_lockLogger.isDebugEnabled()) {
+ Pair<String, Long> time = new Pair<String, Long>(sql, System.currentTimeMillis());
+ _lockTimes.add(time);
+ }
+ }
+
+ public boolean dbTxnStarted() {
+ return _txn;
+ }
+
+ public static Connection getStandaloneConnectionWithException() throws SQLException {
+ Connection conn = s_ds.getConnection();
+ if (s_connLogger.isTraceEnabled()) {
+ s_connLogger.trace("Retrieving a standalone connection: dbconn" + System.identityHashCode(conn));
+ }
+ return conn;
+ }
+
+ public static Connection getStandaloneConnection() {
+ try {
+ return getStandaloneConnectionWithException();
+ } catch (SQLException e) {
+ s_logger.error("Unexpected exception: ", e);
+ return null;
+ }
+ }
+
+ public static Connection getStandaloneUsageConnection() {
+ try {
+ Connection conn = s_usageDS.getConnection();
+ if (s_connLogger.isTraceEnabled()) {
+ s_connLogger.trace("Retrieving a standalone connection for usage: dbconn" + System.identityHashCode(conn));
+ }
+ return conn;
+ } catch (SQLException e) {
+ s_logger.warn("Unexpected exception: ", e);
+ return null;
+ }
+ }
+
+ public static Connection getStandaloneAwsapiConnection() {
+ try {
+ Connection conn = s_awsapiDS.getConnection();
+ if (s_connLogger.isTraceEnabled()) {
+ s_connLogger.trace("Retrieving a standalone connection for usage: dbconn" + System.identityHashCode(conn));
+ }
+ return conn;
+ } catch (SQLException e) {
+ s_logger.warn("Unexpected exception: ", e);
+ return null;
+ }
+ }
+
+ public static Connection getStandaloneSimulatorConnection() {
+ try {
+ Connection conn = s_simulatorDS.getConnection();
+ if (s_connLogger.isTraceEnabled()) {
+ s_connLogger.trace("Retrieving a standalone connection for simulator: dbconn" + System.identityHashCode(conn));
+ }
+ return conn;
+ } catch (SQLException e) {
+ s_logger.warn("Unexpected exception: ", e);
+ return null;
+ }
+ }
+
+ protected void attach(TransactionAttachment value) {
+ _stack.push(new StackElement(ATTACHMENT, value));
+ }
+
+ protected TransactionAttachment detach(String name) {
+ Iterator<StackElement> it = _stack.descendingIterator();
+ while (it.hasNext()) {
+ StackElement element = it.next();
+ if (element.type == ATTACHMENT) {
+ TransactionAttachment att = (TransactionAttachment)element.ref;
+ if (name.equals(att.getName())) {
+ it.remove();
+ return att;
+ }
+ }
+ }
+ assert false : "Are you sure you attached this: " + name;
+ return null;
+ }
+
+ public static void attachToTxn(TransactionAttachment value) {
+ TransactionLegacy txn = tls.get();
+ assert txn != null && txn.peekInStack(CURRENT_TXN) != null: "Come on....how can we attach something to the transaction if you haven't started it?";
+
+ txn.attach(value);
+ }
+
+ public static TransactionAttachment detachFromTxn(String name) {
+ TransactionLegacy txn = tls.get();
+ assert txn != null : "No Transaction in TLS";
+ return txn.detach(name);
+ }
+
+ protected static boolean checkAnnotation(int stack, TransactionLegacy txn) {
+ final StackTraceElement[] stacks = Thread.currentThread().getStackTrace();
+ StackElement se = txn.peekInStack(CURRENT_TXN);
+ if (se == null) {
+ return false;
+ }
+
+ StringBuffer sb = new StringBuffer();
+ for (; stack < stacks.length; stack++) {
+ String methodName = stacks[stack].getMethodName();
+ sb.append(" ").append(methodName);
+ if (methodName.equals(se.ref)){
+ return true;
+ }
+ }
+
+ // relax stack structure for several places that @DB required injection is not in place
+ s_logger.warn("Non-standard stack context that Transaction context is manaully placed into the calling chain. Stack chain: " + sb);
+ return true;
+ }
+
+ protected static String buildName() {
+ if (s_logger.isDebugEnabled()) {
+ final StackTraceElement[] stacks = Thread.currentThread().getStackTrace();
+ final StringBuilder str = new StringBuilder();
+ int i = 3, j = 3;
+ while (j < 15 && i < stacks.length) {
+ StackTraceElement element = stacks[i];
+ String filename = element.getFileName();
+ String method = element.getMethodName();
+ if ((filename != null && filename.equals("<generated>")) || (method != null && method.equals("invokeSuper"))) {
+ i++;
+ continue;
+ }
+
+ str.append("-").append(stacks[i].getClassName().substring(stacks[i].getClassName().lastIndexOf(".") + 1)).append(".").append(stacks[i].getMethodName()).append(":").append(stacks[i].getLineNumber());
+ j++;
+ i++;
+ }
+ return str.toString();
+ }
+
+ return "";
+ }
+
+ public TransactionLegacy(final String name, final boolean forLocking, final short databaseId) {
+ _name = name;
+ _conn = null;
+ _stack = new LinkedList<StackElement>();
+ _txn = false;
+ _dbId = databaseId;
+ _id = s_id.incrementAndGet();
+ _creator = Thread.currentThread().getName();
+ }
+
+ public String getCreator() {
+ return _creator;
+ }
+
+ public long getId() {
+ return _id;
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public Short getDatabaseId() {
+ return _dbId;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder str = new StringBuilder((_name != null ? _name : ""));
+ str.append(" : ");
+ for (final StackElement se : _stack) {
+ if (se.type == CURRENT_TXN) {
+ str.append(se.ref).append(", ");
+ }
+ }
+
+ return str.toString();
+ }
+
+ protected void mark(final String name) {
+ _stack.push(new StackElement(CURRENT_TXN, name));
+ }
+
+ public boolean lock(final String name, final int timeoutSeconds) {
+ Merovingian2 lockMaster = Merovingian2.getLockMaster();
+ if (lockMaster == null) {
+ throw new CloudRuntimeException("There's no support for locking yet");
+ }
+ return lockMaster.acquire(name, timeoutSeconds);
+ }
+
+ public boolean release(final String name) {
+ Merovingian2 lockMaster = Merovingian2.getLockMaster();
+ if (lockMaster == null) {
+ throw new CloudRuntimeException("There's no support for locking yet");
+ }
+ return lockMaster.release(name);
+ }
+
+ /**
+ * @deprecated Use {@link Transaction} for new code
+ */
+ @Deprecated
+ public void start() {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("txn: start requested by: " + buildName());
+ }
+
+ _stack.push(new StackElement(START_TXN, null));
+
+ if (_txn) {
+ s_logger.trace("txn: has already been started.");
+ return;
+ }
+
+ _txn = true;
+
+ _txnTime = System.currentTimeMillis();
+ if (_conn != null) {
+ try {
+ s_logger.trace("txn: set auto commit to false");
+ _conn.setAutoCommit(false);
+ } catch (final SQLException e) {
+ s_logger.warn("Unable to set auto commit: ", e);
+ throw new CloudRuntimeException("Unable to set auto commit: ", e);
+ }
+ }
+ }
+
+ protected void closePreviousStatement() {
+ if (_stmt != null) {
+ try {
+ if (s_stmtLogger.isTraceEnabled()) {
+ s_stmtLogger.trace("Closing: " + _stmt.toString());
+ }
+ try {
+ ResultSet rs = _stmt.getResultSet();
+ if (rs != null && _stmt.getResultSetHoldability() != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
+ rs.close();
+ }
+ } catch(SQLException e) {
+ s_stmtLogger.trace("Unable to close resultset");
+ }
+ _stmt.close();
+ } catch (final SQLException e) {
+ s_stmtLogger.trace("Unable to close statement: " + _stmt.toString());
+ } finally {
+ _stmt = null;
+ }
+ }
+ }
+
+ /**
+ * Prepares an auto close statement. The statement is closed automatically if it is
+ * retrieved with this method.
+ *
+ * @param sql sql String
+ * @return PreparedStatement
+ * @throws SQLException if problem with JDBC layer.
+ *
+ * @see java.sql.Connection
+ */
+ public PreparedStatement prepareAutoCloseStatement(final String sql) throws SQLException {
+ PreparedStatement stmt = prepareStatement(sql);
+ closePreviousStatement();
+ _stmt = stmt;
+ return stmt;
+ }
+
+ public PreparedStatement prepareStatement(final String sql) throws SQLException {
+ final Connection conn = getConnection();
+ final PreparedStatement pstmt = conn.prepareStatement(sql);
+ if (s_stmtLogger.isTraceEnabled()) {
+ s_stmtLogger.trace("Preparing: " + sql);
+ }
+ return pstmt;
+ }
+
+ /**
+ * Prepares an auto close statement. The statement is closed automatically if it is
+ * retrieved with this method.
+ *
+ * @param sql sql String
+ * @param autoGeneratedKeys keys that are generated
+ * @return PreparedStatement
+ * @throws SQLException if problem with JDBC layer.
+ *
+ * @see java.sql.Connection
+ */
+ public PreparedStatement prepareAutoCloseStatement(final String sql, final int autoGeneratedKeys) throws SQLException {
+ final Connection conn = getConnection();
+ final PreparedStatement pstmt = conn.prepareStatement(sql, autoGeneratedKeys);
+ if (s_stmtLogger.isTraceEnabled()) {
+ s_stmtLogger.trace("Preparing: " + sql);
+ }
+ closePreviousStatement();
+ _stmt = pstmt;
+ return pstmt;
+ }
+
+ /**
+ * Prepares an auto close statement. The statement is closed automatically if it is
+ * retrieved with this method.
+ *
+ * @param sql sql String
+ * @param columnNames names of the columns
+ * @return PreparedStatement
+ * @throws SQLException if problem with JDBC layer.
+ *
+ * @see java.sql.Connection
+ */
+ public PreparedStatement prepareAutoCloseStatement(final String sql, final String[] columnNames) throws SQLException {
+ final Connection conn = getConnection();
+ final PreparedStatement pstmt = conn.prepareStatement(sql, columnNames);
+ if (s_stmtLogger.isTraceEnabled()) {
+ s_stmtLogger.trace("Preparing: " + sql);
+ }
+ closePreviousStatement();
+ _stmt = pstmt;
+ return pstmt;
+ }
+
+ /**
+ * Prepares an auto close statement. The statement is closed automatically if it is
+ * retrieved with this method.
+ *
+ * @param sql sql String
+ * @return PreparedStatement
+ * @throws SQLException if problem with JDBC layer.
+ *
+ * @see java.sql.Connection
+ */
+ public PreparedStatement prepareAutoCloseStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ final Connection conn = getConnection();
+ final PreparedStatement pstmt = conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ if (s_stmtLogger.isTraceEnabled()) {
+ s_stmtLogger.trace("Preparing: " + sql);
+ }
+ closePreviousStatement();
+ _stmt = pstmt;
+ return pstmt;
+ }
+
+ /**
+ * Returns the db connection.
+ *
+ * Note: that you can call getConnection() but beaware that
+ * all prepare statements from the Connection are not garbage
+ * collected!
+ *
+ * @return DB Connection but make sure you understand that
+ * you are responsible for closing the PreparedStatement.
+ * @throws SQLException
+ */
+ public Connection getConnection() throws SQLException {
+ if (_conn == null) {
+ switch (_dbId) {
+ case CLOUD_DB:
+ if(s_ds != null) {
+ _conn = s_ds.getConnection();
+ } else {
+ s_logger.warn("A static-initialized variable becomes null, process is dying?");
+ throw new CloudRuntimeException("Database is not initialized, process is dying?");
+ }
+ break;
+ case USAGE_DB:
+ if(s_usageDS != null) {
+ _conn = s_usageDS.getConnection();
+ } else {
+ s_logger.warn("A static-initialized variable becomes null, process is dying?");
+ throw new CloudRuntimeException("Database is not initialized, process is dying?");
+ }
+ break;
+ case AWSAPI_DB:
+ if(s_awsapiDS != null) {
+ _conn = s_awsapiDS.getConnection();
+ } else {
+ s_logger.warn("A static-initialized variable becomes null, process is dying?");
+ throw new CloudRuntimeException("Database is not initialized, process is dying?");
+ }
+ break;
+
+ case SIMULATOR_DB:
+ if(s_simulatorDS != null) {
+ _conn = s_simulatorDS.getConnection();
+ } else {
+ s_logger.warn("A static-initialized variable becomes null, process is dying?");
+ throw new CloudRuntimeException("Database is not initialized, process is dying?");
+ }
+ break;
+ default:
+
+ throw new CloudRuntimeException("No database selected for the transaction");
+ }
+ _conn.setAutoCommit(!_txn);
+
+ //
+ // MySQL default transaction isolation level is REPEATABLE READ,
+ // to reduce chances of DB deadlock, we will use READ COMMITED isolation level instead
+ // see http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html
+ //
+ _stack.push(new StackElement(CREATE_CONN, null));
+ if (s_connLogger.isTraceEnabled()) {
+ s_connLogger.trace("Creating a DB connection with " + (_txn ? " txn: " : " no txn: ") + " for " + _dbId + ": dbconn" + System.identityHashCode(_conn) + ". Stack: " + buildName());
+ }
+ } else {
+ s_logger.trace("conn: Using existing DB connection");
+ }
+
+ return _conn;
+ }
+
+ protected boolean takeOver(final String name, final boolean create) {
+ if (_stack.size() != 0) {
+ if (!create) {
+ // If it is not a create transaction, then let's just use the current one.
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Using current transaction: " + toString());
+ }
+ mark(name);
+ return false;
+ }
+
+ final StackElement se = _stack.getFirst();
+ if (se.type == CREATE_TXN) {
+ // This create is called inside of another create. Which is ok?
+ // We will let that create be responsible for cleaning up.
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Create using current transaction: " + toString());
+ }
+ mark(name);
+ return false;
+ }
+
+ s_logger.warn("Encountered a transaction that has leaked. Cleaning up. " + toString());
+ cleanup();
+ }
+
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Took over the transaction: " + name);
+ }
+ _stack.push(new StackElement(create ? CREATE_TXN : CURRENT_TXN, name));
+ _name = name;
+ return true;
+ }
+
+ public void cleanup() {
+ closePreviousStatement();
+
+ removeUpTo(null, null);
+ if (_txn) {
+ rollbackTransaction();
+ }
+ _txn = false;
+ _name = null;
+
+ closeConnection();
+
+ _stack.clear();
+ Merovingian2 lockMaster = Merovingian2.getLockMaster();
+ if (lockMaster != null) {
+ lockMaster.cleanupThread();
+ }
+ }
+
+ public void close() {
+ removeUpTo(CURRENT_TXN, null);
+
+ if (_stack.size() == 0) {
+ s_logger.trace("Transaction is done");
+ cleanup();
+ }
+ }
+
+ /**
+ * close() is used by endTxn to close the connection. This method only
+ * closes the connection if the name is the same as what's stored.
+ *
+ * @param name
+ * @return true if this close actually closes the connection. false if not.
+ */
+ public boolean close(final String name) {
+ if (_name == null) { // Already cleaned up.
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Already cleaned up." + buildName());
+ }
+ return true;
+ }
+
+ if (!_name.equals(name)) {
+ close();
+ return false;
+ }
+
+ if (s_logger.isDebugEnabled() && _stack.size() > 2) {
+ s_logger.debug("Transaction is not closed properly: " + toString() + ". Called by " + buildName());
+ }
+
+ cleanup();
+
+ s_logger.trace("All done");
+ return true;
+ }
+
+ protected boolean hasTxnInStack() {
+ return peekInStack(START_TXN) != null;
+ }
+
+ protected void clearLockTimes() {
+ if (s_lockLogger.isDebugEnabled()) {
+ for (Pair<String, Long> time : _lockTimes) {
+ s_lockLogger.trace("SQL " + time.first() + " took " + (System.currentTimeMillis() - time.second()));
+ }
+ _lockTimes.clear();
+ }
+ }
+
+ public boolean commit() {
+ if (!_txn) {
+ s_logger.warn("txn: Commit called when it is not a transaction: " + buildName());
+ return false;
+ }
+
+ Iterator<StackElement> it = _stack.iterator();
+ while (it.hasNext()) {
+ StackElement st = it.next();
+ if (st.type == START_TXN) {
+ it.remove();
+ break;
+ }
+ }
+
+ if (hasTxnInStack()) {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("txn: Not committing because transaction started elsewhere: " + buildName() + " / " + toString());
+ }
+ return false;
+ }
+
+ _txn = false;
+ try {
+ if (_conn != null) {
+ _conn.commit();
+ s_logger.trace("txn: DB Changes committed. Time = " + (System.currentTimeMillis() - _txnTime));
+ clearLockTimes();
+ closeConnection();
+ }
+ return true;
+ } catch (final SQLException e) {
+ rollbackTransaction();
+ throw new CloudRuntimeException("Unable to commit or close the connection. ", e);
+ }
+ }
+
+ protected void closeConnection() {
+ closePreviousStatement();
+
+ if (_conn == null) {
+ return;
+ }
+
+ if (_txn) {
+ s_connLogger.trace("txn: Not closing DB connection because we're still in a transaction.");
+ return;
+ }
+
+ try {
+ // we should only close db connection when it is not user managed
+ if (this._dbId != CONNECTED_DB) {
+ if (s_connLogger.isTraceEnabled()) {
+ s_connLogger.trace("Closing DB connection: dbconn" + System.identityHashCode(_conn));
+ }
+ _conn.close();
+ _conn = null;
+ }
+
+ } catch (final SQLException e) {
+ s_logger.warn("Unable to close connection", e);
+ }
+ }
+
+ protected void removeUpTo(String type, Object ref) {
+ boolean rollback = false;
+ Iterator<StackElement> it = _stack.iterator();
+ while (it.hasNext()) {
+ StackElement item = it.next();
+
+ it.remove();
+
+ try {
+ if (item.type == type && (ref == null || item.ref == ref)) {
+ break;
+ }
+
+ if (item.type == CURRENT_TXN) {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Releasing the current txn: " + (item.ref != null ? item.ref : ""));
+ }
+ } else if (item.type == CREATE_CONN) {
+ closeConnection();
+ } else if (item.type == START_TXN) {
+ if (item.ref == null) {
+ rollback = true;
+ } else {
+ try {
+ _conn.rollback((Savepoint)ref);
+ rollback = false;
+ } catch (final SQLException e) {
+ s_logger.warn("Unable to rollback Txn.", e);
+ }
+ }
+ } else if (item.type == STATEMENT) {
+ try {
+ if (s_stmtLogger.isTraceEnabled()) {
+ s_stmtLogger.trace("Closing: " + ref.toString());
+ }
+ Statement stmt = (Statement)ref;
+ try {
+ ResultSet rs = stmt.getResultSet();
+ if (rs != null) {
+ rs.close();
+ }
+ } catch(SQLException e) {
+ s_stmtLogger.trace("Unable to close resultset");
+ }
+ stmt.close();
+ } catch (final SQLException e) {
+ s_stmtLogger.trace("Unable to close statement: " + item);
+ }
+ } else if (item.type == ATTACHMENT) {
+ TransactionAttachment att = (TransactionAttachment)item.ref;
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Cleaning up " + att.getName());
+ }
+ att.cleanup();
+ }
+ } catch(Exception e) {
+ s_logger.error("Unable to clean up " + item, e);
+ }
+ }
+
+ if (rollback) {
+ rollback();
+ }
+ }
+
+ protected void rollbackTransaction() {
+ closePreviousStatement();
+ if (!_txn) {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Rollback called for " + _name + " when there's no transaction: " + buildName());
+ }
+ return;
+ }
+ assert (!hasTxnInStack()) : "Who's rolling back transaction when there's still txn in stack?";
+ _txn = false;
+ try {
+ if (_conn != null) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Rolling back the transaction: Time = " + (System.currentTimeMillis() - _txnTime) + " Name = " + _name + "; called by " + buildName());
+ }
+ _conn.rollback();
+ }
+ clearLockTimes();
+ closeConnection();
+ } catch(final SQLException e) {
+ s_logger.warn("Unable to rollback", e);
+ }
+ }
+
+ protected void rollbackSavepoint(Savepoint sp) {
+ try {
+ if (_conn != null) {
+ _conn.rollback(sp);
+ }
+ } catch (SQLException e) {
+ s_logger.warn("Unable to rollback to savepoint " + sp);
+ }
+
+ if (!hasTxnInStack()) {
+ _txn = false;
+ closeConnection();
+ }
+ }
+
+ public void rollback() {
+ Iterator<StackElement> it = _stack.iterator();
+ while (it.hasNext()) {
+ StackElement st = it.next();
+ if (st.type == START_TXN) {
+ if (st.ref == null) {
+ it.remove();
+ } else {
+ rollback((Savepoint)st.ref);
+ return;
+ }
+ }
+ }
+
+ rollbackTransaction();
+ }
+
+ public Savepoint setSavepoint() throws SQLException {
+ _txn = true;
+ StackElement st = new StackElement(START_TXN, null);
+ _stack.push(st);
+ final Connection conn = getConnection();
+ final Savepoint sp = conn.setSavepoint();
+ st.ref = sp;
+
+ return sp;
+ }
+
+ public Savepoint setSavepoint(final String name) throws SQLException {
+ _txn = true;
+ StackElement st = new StackElement(START_TXN, null);
+ _stack.push(st);
+ final Connection conn = getConnection();
+ final Savepoint sp = conn.setSavepoint(name);
+ st.ref = sp;
+
+ return sp;
+ }
+
+ public void releaseSavepoint(final Savepoint sp) throws SQLException {
+ removeTxn(sp);
+ if (_conn != null) {
+ _conn.releaseSavepoint(sp);
+ }
+
+ if (!hasTxnInStack()) {
+ _txn = false;
+ closeConnection();
+ }
+ }
+
+ protected boolean hasSavepointInStack(Savepoint sp) {
+ Iterator<StackElement> it = _stack.iterator();
+ while (it.hasNext()) {
+ StackElement se = it.next();
+ if (se.type == START_TXN && se.ref == sp) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected void removeTxn(Savepoint sp) {
+ assert hasSavepointInStack(sp) : "Removing a save point that's not in the stack";
+
+ if (!hasSavepointInStack(sp)) {
+ return;
+ }
+
+ Iterator<StackElement> it = _stack.iterator();
+ while (it.hasNext()) {
+ StackElement se = it.next();
+ if (se.type == START_TXN) {
+ it.remove();
+ if (se.ref == sp) {
+ return;
+ }
+ }
+ }
+ }
+
+ public void rollback(final Savepoint sp) {
+ removeTxn(sp);
+
+ rollbackSavepoint(sp);
+ }
+
+ public Connection getCurrentConnection() {
+ return _conn;
+ }
+
+ public List<StackElement> getStack() {
+ return _stack;
+ }
+
+ protected TransactionLegacy() {
+ _name = null;
+ _conn = null;
+ _stack = null;
+ _txn = false;
+ _dbId = -1;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ if (!(_conn == null && (_stack == null || _stack.size() == 0))) {
+ assert (false) : "Oh Alex oh alex...something is wrong with how we're doing this";
+ s_logger.error("Something went wrong that a transaction is orphaned before db connection is closed");
+ cleanup();
+ }
+ }
+
+ protected class StackElement {
+ public String type;
+ public Object ref;
+
+ public StackElement (String type, Object ref) {
+ this.type = type;
+ this.ref = ref;
+ }
+
+ @Override
+ public String toString() {
+ return type + "-" + ref;
+ }
+ }
+
+ private static DataSource s_ds;
+ private static DataSource s_usageDS;
+ private static DataSource s_awsapiDS;
+ private static DataSource s_simulatorDS;
+
+ static {
+ // Initialize with assumed db.properties file
+ initDataSource("db.properties");
+ }
+
+ public static void initDataSource(String propsFileName) {
+ try {
+ File dbPropsFile = PropertiesUtil.findConfigFile(propsFileName);
+ final Properties dbProps;
+ if (EncryptionSecretKeyChecker.useEncryption()) {
+ StandardPBEStringEncryptor encryptor = EncryptionSecretKeyChecker.getEncryptor();
+ dbProps = new EncryptableProperties(encryptor);
+ } else {
+ dbProps = new Properties();
+ }
+ try {
+ dbProps.load(new FileInputStream(dbPropsFile));
+ } catch (IOException e) {
+ s_logger.fatal("Unable to load db properties file, pl. check the classpath and file path configuration", e);
+ return;
+ } catch (NullPointerException e) {
+ s_logger.fatal("Unable to locate db properties file within classpath or absolute path: " + propsFileName);
+ return;
+ }
+
+ // FIXME: If params are missing...default them????
+ final int cloudMaxActive = Integer.parseInt(dbProps.getProperty("db.cloud.maxActive"));
+ final int cloudMaxIdle = Integer.parseInt(dbProps.getProperty("db.cloud.maxIdle"));
+ final long cloudMaxWait = Long.parseLong(dbProps.getProperty("db.cloud.maxWait"));
+ final String cloudUsername = dbProps.getProperty("db.cloud.username");
+ final String cloudPassword = dbProps.getProperty("db.cloud.password");
+ final String cloudHost = dbProps.getProperty("db.cloud.host");
+ final int cloudPort = Integer.parseInt(dbProps.getProperty("db.cloud.port"));
+ final String cloudDbName = dbProps.getProperty("db.cloud.name");
+ final boolean cloudAutoReconnect = Boolean.parseBoolean(dbProps.getProperty("db.cloud.autoReconnect"));
+ final String cloudValidationQuery = dbProps.getProperty("db.cloud.validationQuery");
+ final String cloudIsolationLevel = dbProps.getProperty("db.cloud.isolation.level");
+
+ int isolationLevel = Connection.TRANSACTION_READ_COMMITTED;
+ if (cloudIsolationLevel == null) {
+ isolationLevel = Connection.TRANSACTION_READ_COMMITTED;
+ } else if (cloudIsolationLevel.equalsIgnoreCase("readcommitted")) {
+ isolationLevel = Connection.TRANSACTION_READ_COMMITTED;
+ } else if (cloudIsolationLevel.equalsIgnoreCase("repeatableread")) {
+ isolationLevel = Connection.TRANSACTION_REPEATABLE_READ;
+ } else if (cloudIsolationLevel.equalsIgnoreCase("serializable")) {
+ isolationLevel = Connection.TRANSACTION_SERIALIZABLE;
+ } else if (cloudIsolationLevel.equalsIgnoreCase("readuncommitted")) {
+ isolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED;
+ } else {
+ s_logger.warn("Unknown isolation level " + cloudIsolationLevel + ". Using read uncommitted");
+ }
+
+ final boolean cloudTestOnBorrow = Boolean.parseBoolean(dbProps.getProperty("db.cloud.testOnBorrow"));
+ final boolean cloudTestWhileIdle = Boolean.parseBoolean(dbProps.getProperty("db.cloud.testWhileIdle"));
+ final long cloudTimeBtwEvictionRunsMillis = Long.parseLong(dbProps.getProperty("db.cloud.timeBetweenEvictionRunsMillis"));
+ final long cloudMinEvcitableIdleTimeMillis = Long.parseLong(dbProps.getProperty("db.cloud.minEvictableIdleTimeMillis"));
+ final boolean cloudPoolPreparedStatements = Boolean.parseBoolean(dbProps.getProperty("db.cloud.poolPreparedStatements"));
+ final String url = dbProps.getProperty("db.cloud.url.params");
+
+ final boolean useSSL = Boolean.parseBoolean(dbProps.getProperty("db.cloud.useSSL"));
+ if (useSSL) {
+ System.setProperty("javax.net.ssl.keyStore", dbProps.getProperty("db.cloud.keyStore"));
+ System.setProperty("javax.net.ssl.keyStorePassword", dbProps.getProperty("db.cloud.keyStorePassword"));
+ System.setProperty("javax.net.ssl.trustStore", dbProps.getProperty("db.cloud.trustStore"));
+ System.setProperty("javax.net.ssl.trustStorePassword", dbProps.getProperty("db.cloud.trustStorePassword"));
+ }
+
+ final GenericObjectPool cloudConnectionPool = new GenericObjectPool(null, cloudMaxActive, GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,
+ cloudMaxWait, cloudMaxIdle, cloudTestOnBorrow, false, cloudTimeBtwEvictionRunsMillis, 1, cloudMinEvcitableIdleTimeMillis, cloudTestWhileIdle);
+
+ final ConnectionFactory cloudConnectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://" + cloudHost + ":" + cloudPort + "/" + cloudDbName +
+ "?autoReconnect=" + cloudAutoReconnect + (url != null ? "&" + url : "") + (useSSL ? "&useSSL=true" : ""), cloudUsername, cloudPassword);
+
+ final KeyedObjectPoolFactory poolableObjFactory = (cloudPoolPreparedStatements ? new StackKeyedObjectPoolFactory() : null);
+
+ final PoolableConnectionFactory cloudPoolableConnectionFactory = new PoolableConnectionFactory(cloudConnectionFactory, cloudConnectionPool, poolableObjFactory,
+ cloudValidationQuery, false, false, isolationLevel);
+
+ // Default Data Source for CloudStack
+ s_ds = new PoolingDataSource(cloudPoolableConnectionFactory.getPool());
+
+ // Configure the usage db
+ final int usageMaxActive = Integer.parseInt(dbProps.getProperty("db.usage.maxActive"));
+ final int usageMaxIdle = Integer.parseInt(dbProps.getProperty("db.usage.maxIdle"));
+ final long usageMaxWait = Long.parseLong(dbProps.getProperty("db.usage.maxWait"));
+ final String usageUsername = dbProps.getProperty("db.usage.username");
+ final String usagePassword = dbProps.getProperty("db.usage.password");
+ final String usageHost = dbProps.getProperty("db.usage.host");
+ final int usagePort = Integer.parseInt(dbProps.getProperty("db.usage.port"));
+ final String usageDbName = dbProps.getProperty("db.usage.name");
+ final boolean usageAutoReconnect = Boolean.parseBoolean(dbProps.getProperty("db.usage.autoReconnect"));
+ final String usageUrl = dbProps.getProperty("db.usage.url.params");
+
+ final GenericObjectPool usageConnectionPool = new GenericObjectPool(null, usageMaxActive, GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,
+ usageMaxWait, usageMaxIdle);
+
+ final ConnectionFactory usageConnectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://" + usageHost + ":" + usagePort + "/" + usageDbName +
+ "?autoReconnect=" + usageAutoReconnect + (usageUrl != null ? "&" + usageUrl : ""), usageUsername, usagePassword);
+
+ final PoolableConnectionFactory usagePoolableConnectionFactory = new PoolableConnectionFactory(usageConnectionFactory, usageConnectionPool,
+ new StackKeyedObjectPoolFactory(), null, false, false);
+
+ // Data Source for usage server
+ s_usageDS = new PoolingDataSource(usagePoolableConnectionFactory.getPool());
+
+ // Configure awsapi db
+ final String awsapiDbName = dbProps.getProperty("db.awsapi.name");
+ final GenericObjectPool awsapiConnectionPool = new GenericObjectPool(null, usageMaxActive, GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,
+ usageMaxWait, usageMaxIdle);
+ final ConnectionFactory awsapiConnectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://" + cloudHost + ":" + cloudPort + "/" + awsapiDbName +
+ "?autoReconnect=" + usageAutoReconnect, cloudUsername, cloudPassword);
+ final PoolableConnectionFactory awsapiPoolableConnectionFactory = new PoolableConnectionFactory(awsapiConnectionFactory, awsapiConnectionPool,
+ new StackKeyedObjectPoolFactory(), null, false, false);
+
+ // Data Source for awsapi
+ s_awsapiDS = new PoolingDataSource(awsapiPoolableConnectionFactory.getPool());
+
+ try {
+ // Configure the simulator db
+ final int simulatorMaxActive = Integer.parseInt(dbProps.getProperty("db.simulator.maxActive"));
+ final int simulatorMaxIdle = Integer.parseInt(dbProps.getProperty("db.simulator.maxIdle"));
+ final long simulatorMaxWait = Long.parseLong(dbProps.getProperty("db.simulator.maxWait"));
+ final String simulatorUsername = dbProps.getProperty("db.simulator.username");
+ final String simulatorPassword = dbProps.getProperty("db.simulator.password");
+ final String simulatorHost = dbProps.getProperty("db.simulator.host");
+ final int simulatorPort = Integer.parseInt(dbProps.getProperty("db.simulator.port"));
+ final String simulatorDbName = dbProps.getProperty("db.simulator.name");
+ final boolean simulatorAutoReconnect = Boolean.parseBoolean(dbProps.getProperty("db.simulator.autoReconnect"));
+
+ final GenericObjectPool simulatorConnectionPool = new GenericObjectPool(null, simulatorMaxActive, GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,
+ simulatorMaxWait, simulatorMaxIdle);
+
+ final ConnectionFactory simulatorConnectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://" + simulatorHost + ":" + simulatorPort + "/" + simulatorDbName +
+ "?autoReconnect=" + simulatorAutoReconnect, simulatorUsername, simulatorPassword);
+
+ final PoolableConnectionFactory simulatorPoolableConnectionFactory = new PoolableConnectionFactory(simulatorConnectionFactory, simulatorConnectionPool,
+ new StackKeyedObjectPoolFactory(), null, false, false);
+ s_simulatorDS = new PoolingDataSource(simulatorPoolableConnectionFactory.getPool());
+ } catch (Exception e) {
+ s_logger.debug("Simulator DB properties are not available. Not initializing simulator DS");
+ }
+ } catch (final Exception e) {
+ s_ds = getDefaultDataSource("cloud");
+ s_usageDS = getDefaultDataSource("cloud_usage");
+ s_simulatorDS = getDefaultDataSource("cloud_simulator");
+ s_logger.warn("Unable to load db configuration, using defaults with 5 connections. Falling back on assumed datasource on localhost:3306 using username:password=cloud:cloud. Please check your configuration", e);
+ }
+ }
+
+ private static DataSource getDefaultDataSource(final String database) {
+ final GenericObjectPool connectionPool = new GenericObjectPool(null, 5);
+ final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
+ "jdbc:mysql://localhost:3306/" + database, "cloud", "cloud");
+ final PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(
+ connectionFactory, connectionPool, null, null, false, true);
+ return new PoolingDataSource(
+ /* connectionPool */poolableConnectionFactory.getPool());
+ }
+
+ /**
+ * Used for unit testing primarily
+ *
+ * @param conn
+ */
+ protected void setConnection(Connection conn) {
+ this._conn = conn;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/packaging/centos63/cloud.spec
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java
----------------------------------------------------------------------
diff --cc plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java
index dec6b38,4075c87..4071aeb
--- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java
+++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java
@@@ -16,6 -16,26 +16,25 @@@
// under the License.
package com.cloud.agent.manager;
+ import java.security.NoSuchAlgorithmException;
+ import java.security.SecureRandom;
+ import java.util.HashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.UUID;
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.LinkedBlockingQueue;
+ import java.util.concurrent.ThreadPoolExecutor;
+ import java.util.concurrent.TimeUnit;
+ import java.util.regex.PatternSyntaxException;
+
+ import javax.ejb.Local;
+ import javax.inject.Inject;
+ import javax.naming.ConfigurationException;
+
-import org.apache.cloudstack.storage.resource.SecondaryStorageDiscoverer;
+ import org.apache.log4j.Logger;
+ import org.springframework.stereotype.Component;
+
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckHealthCommand;
@@@ -41,8 -66,7 +65,7 @@@ import com.cloud.utils.Pair
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
--import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/pom.xml
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/server/pom.xml
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/server/src/com/cloud/api/ApiServer.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/server/src/com/cloud/network/vpc/VpcManagerImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/server/src/com/cloud/resource/ResourceManagerImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index dade983,9337705..c874c48
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@@ -192,10 -193,10 +192,9 @@@ public class SnapshotManagerImpl extend
@Inject VolumeDataFactory volFactory;
@Inject SnapshotDataFactory snapshotFactory;
@Inject EndPointSelector _epSelector;
- @Inject
- private ResourceManager _resourceMgr;
-
- protected List<SnapshotStrategy> snapshotStrategies;
+ @Inject
+ private ResourceManager _resourceMgr;
- @Inject
+ protected List<SnapshotStrategy> snapshotStrategies;
private int _totalRetries;
@@@ -379,11 -344,11 +378,7 @@@
String parent = null;
try {
for (String backupUuid : BackupUuids) {
--<<<<<<< HEAD
-- downloadSnapshotFromSwiftCommand cmd = new downloadSnapshotFromSwiftCommand(swift, secStore.getUri(), dcId, accountId, volumeId, parent, backupUuid, _backupsnapshotwait);
--=======
- DownloadSnapshotFromSwiftCommand cmd = new DownloadSnapshotFromSwiftCommand(swift, secondaryStoragePoolUrl, dcId, accountId, volumeId, parent, backupUuid, _backupsnapshotwait);
->>>>>>> master
+ DownloadSnapshotFromSwiftCommand cmd = new DownloadSnapshotFromSwiftCommand(swift, secondaryStoragePoolUrl, dcId, accountId, volumeId, parent, backupUuid, _backupsnapshotwait);
- >>>>>>> master
Answer answer = _agentMgr.sendToSSVM(dcId, cmd);
if ((answer == null) || !answer.getResult()) {
throw new CloudRuntimeException("downloadSnapshotsFromSwift failed ");
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3280bdb/utils/pom.xml
----------------------------------------------------------------------
diff --cc utils/pom.xml
index 93fa796,3eea8fe..451fcbf
mode 100755,100644..100755
--- a/utils/pom.xml
+++ b/utils/pom.xml