You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicemix.apache.org by gn...@apache.org on 2009/08/26 13:19:20 UTC
svn commit: r807962 [2/2] - in /servicemix/sandbox/karaf/nmr:
assembly/src/main/descriptors/ assembly/src/main/filtered-resources/
assembly/src/main/filtered-resources/etc/ jbi/osgi/
jbi/osgi/src/main/java/org/apache/servicemix/jbi/osgi/ jbi/osgi/src/m...
Added: servicemix/sandbox/karaf/nmr/transaction/src/main/java/org/apache/servicemix/transaction/TransactionManagerService.java
URL: http://svn.apache.org/viewvc/servicemix/sandbox/karaf/nmr/transaction/src/main/java/org/apache/servicemix/transaction/TransactionManagerService.java?rev=807962&view=auto
==============================================================================
--- servicemix/sandbox/karaf/nmr/transaction/src/main/java/org/apache/servicemix/transaction/TransactionManagerService.java (added)
+++ servicemix/sandbox/karaf/nmr/transaction/src/main/java/org/apache/servicemix/transaction/TransactionManagerService.java Wed Aug 26 11:19:19 2009
@@ -0,0 +1,220 @@
+/*
+ * 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 with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.transaction;
+
+import java.util.Dictionary;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Properties;
+import java.io.File;
+import java.io.IOException;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.UserTransaction;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationException;
+import org.apache.geronimo.transaction.manager.GeronimoTransactionManager;
+import org.apache.geronimo.transaction.manager.TransactionLog;
+import org.apache.geronimo.transaction.manager.XidFactory;
+import org.apache.geronimo.transaction.manager.XidFactoryImpl;
+import org.apache.geronimo.transaction.manager.RecoverableTransactionManager;
+import org.apache.geronimo.transaction.log.HOWLLog;
+import org.apache.geronimo.transaction.log.UnrecoverableLog;
+import org.objectweb.howl.log.LogConfigurationException;
+
+/**
+ */
+public class TransactionManagerService {
+
+ public static final String TRANSACTION_TIMEOUT = "felix.transaction.timeout";
+ public static final String RECOVERABLE = "felix.transaction.recoverable";
+ public static final String HOWL_BUFFER_CLASS_NAME = "felix.transaction.howl.bufferClassName";
+ public static final String HOWL_BUFFER_SIZE = "felix.transaction.howl.bufferSize";
+ public static final String HOWL_CHECKSUM_ENABLED = "felix.transaction.howl.checksumEnabled";
+ public static final String HOWL_ADLER32_CHECKSUM = "felix.transaction.howl.adler32Checksum";
+ public static final String HOWL_FLUSH_SLEEP_TIME = "felix.transaction.howl.flushSleepTime";
+ public static final String HOWL_LOG_FILE_EXT = "felix.transaction.howl.logFileExt";
+ public static final String HOWL_LOG_FILE_NAME = "felix.transaction.howl.logFileName";
+ public static final String HOWL_MAX_BLOCKS_PER_FILE = "felix.transaction.howl.maxBlocksPerFile";
+ public static final String HOWL_MAX_LOG_FILES = "felix.transaction.howl.maxLogFiles";
+ public static final String HOWL_MAX_BUFFERS = "felix.transaction.howl.maxBuffers";
+ public static final String HOWL_MIN_BUFFERS = "felix.transaction.howl.minBuffers";
+ public static final String HOWL_THREADS_WAITING_FORCE_THRESHOLD = "felix.transaction.howl.threadsWaitingForceThreshold";
+ public static final String HOWL_LOG_FILE_DIR = "felix.transaction.howl.logFileDir";
+
+ public static final int DEFAULT_TRANSACTION_TIMEOUT = 600; // 600 seconds -> 10 minutes
+ public static final boolean DEFAULT_RECOVERABLE = false; // not recoverable by default
+
+ private static final String PLATFORM_TRANSACTION_MANAGER_CLASS = "org.springframework.transaction.PlatformTransactionManager";
+
+ private final String pid;
+ private final Dictionary properties;
+ private final BundleContext bundleContext;
+ private boolean useSpring;
+ private GeronimoTransactionManager transactionManager;
+ private TransactionLog transactionLog;
+ private ServiceRegistration serviceRegistration;
+
+ public TransactionManagerService(String pid, Dictionary properties, BundleContext bundleContext) throws ConfigurationException {
+ this.pid = pid;
+ this.properties = properties;
+ this.bundleContext = bundleContext;
+ // Transaction timeout
+ int transactionTimeout = getInt(TRANSACTION_TIMEOUT, DEFAULT_TRANSACTION_TIMEOUT);
+ if (transactionTimeout <= 0) {
+ throw new ConfigurationException(TRANSACTION_TIMEOUT, "Property " + TRANSACTION_TIMEOUT + " must be > 0");
+ }
+ // XID factory
+ XidFactory xidFactory = new XidFactoryImpl(pid.getBytes());
+ // Transaction log
+ if (getBool(RECOVERABLE, DEFAULT_RECOVERABLE)) {
+ String bufferClassName = getString(HOWL_BUFFER_CLASS_NAME, "org.objectweb.howl.log.BlockLogBuffer");
+ int bufferSizeKBytes = getInt(HOWL_BUFFER_SIZE, 32);
+ if (bufferSizeKBytes < 1 || bufferSizeKBytes > 32) {
+ throw new ConfigurationException(HOWL_BUFFER_SIZE, "bufferSize must be between 1 and 32");
+ }
+ boolean checksumEnabled = getBool(HOWL_CHECKSUM_ENABLED, true);
+ boolean adler32Checksum = getBool(HOWL_ADLER32_CHECKSUM, true);
+ int flushSleepTimeMilliseconds = getInt(HOWL_FLUSH_SLEEP_TIME, 50);
+ String logFileExt = getString(HOWL_LOG_FILE_EXT, "log");
+ String logFileName = getString(HOWL_LOG_FILE_NAME, "transaction");
+ int maxBlocksPerFile = getInt(HOWL_MAX_BLOCKS_PER_FILE, -1);
+ int maxLogFiles = getInt(HOWL_MAX_LOG_FILES, 2);
+ int minBuffers = getInt(HOWL_MIN_BUFFERS, 4);
+ if (minBuffers < 0) {
+ throw new ConfigurationException(HOWL_MIN_BUFFERS, "minBuffers must be > 0");
+ }
+ int maxBuffers = getInt(HOWL_MAX_BUFFERS, 0);
+ if (maxBuffers > 0 && minBuffers < maxBuffers) {
+ throw new ConfigurationException(HOWL_MAX_BUFFERS, "minBuffers must be <= maxBuffers");
+ }
+ int threadsWaitingForceThreshold = getInt(HOWL_THREADS_WAITING_FORCE_THRESHOLD, -1);
+ String logFileDir = getString(HOWL_LOG_FILE_DIR, null);
+ if (logFileDir == null || logFileDir.length() == 0 || !new File(logFileDir).isAbsolute()) {
+ throw new ConfigurationException(HOWL_LOG_FILE_DIR, "Property should be set to an absolute directory");
+ }
+ try {
+ transactionLog = new HOWLLog(bufferClassName,
+ bufferSizeKBytes,
+ checksumEnabled,
+ adler32Checksum,
+ flushSleepTimeMilliseconds,
+ logFileDir,
+ logFileExt,
+ logFileName,
+ maxBlocksPerFile,
+ maxBuffers,
+ maxLogFiles,
+ minBuffers,
+ threadsWaitingForceThreshold,
+ xidFactory != null ? xidFactory : new XidFactoryImpl(),
+ null);
+ } catch (LogConfigurationException e) {
+ // This should not really happen as we've checked properties earlier
+ throw new ConfigurationException(null, null, e);
+ } catch (IOException e) {
+ // This should not really happen as we've checked properties earlier
+ throw new ConfigurationException(null, null, e);
+ }
+ } else {
+ transactionLog = new UnrecoverableLog();
+ }
+ // Create transaction manager
+ try {
+ try {
+ transactionManager = new SpringTransactionManagerCreator().create(transactionTimeout, xidFactory, transactionLog);
+ useSpring = true;
+ } catch (NoClassDefFoundError e) {
+ transactionManager = new GeronimoTransactionManager(transactionTimeout, xidFactory, transactionLog);
+ }
+ } catch (XAException e) {
+ throw new RuntimeException("Error recovering transaction log", e);
+ }
+ }
+
+ public void start() throws Exception {
+ if (transactionLog instanceof HOWLLog) {
+ ((HOWLLog) transactionLog).doStart();
+ }
+ List<String> clazzes = new ArrayList<String>();
+ clazzes.add(TransactionManager.class.getName());
+ clazzes.add(TransactionSynchronizationRegistry.class.getName());
+ clazzes.add(UserTransaction.class.getName());
+ clazzes.add(RecoverableTransactionManager.class.getName());
+ if (useSpring) {
+ clazzes.add(PLATFORM_TRANSACTION_MANAGER_CLASS);
+ }
+ serviceRegistration = bundleContext.registerService(clazzes.toArray(new String[clazzes.size()]), transactionManager, new Properties());
+ }
+
+ public void close() throws Exception {
+ if (serviceRegistration != null) {
+ serviceRegistration.unregister();
+ }
+ if (transactionLog instanceof HOWLLog) {
+ ((HOWLLog) transactionLog).doStop();
+ }
+ }
+
+ private String getString(String property, String dflt) throws ConfigurationException {
+ String value = (String) properties.get(property);
+ if (value != null) {
+ return value;
+ }
+ return dflt;
+ }
+
+ private int getInt(String property, int dflt) throws ConfigurationException {
+ String value = (String) properties.get(property);
+ if (value != null) {
+ try {
+ return Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new ConfigurationException(property, "Error parsing " + property + "(" + value + ") property as an integer", e);
+ }
+ }
+ return dflt;
+ }
+
+ private boolean getBool(String property, boolean dflt) throws ConfigurationException {
+ String value = (String) properties.get(property);
+ if (value != null) {
+ try {
+ return Boolean.parseBoolean(value);
+ } catch (Exception e) {
+ throw new ConfigurationException(property, "Error parsing " + property + "(" + value + ") property as a boolean", e);
+ }
+ }
+ return dflt;
+ }
+
+ /**
+ * We use an inner static class to decouple this class from the spring-tx classes
+ * in order to not have NoClassDefFoundError if those are not present.
+ */
+ public static class SpringTransactionManagerCreator {
+
+ public GeronimoTransactionManager create(int defaultTransactionTimeoutSeconds, XidFactory xidFactory, TransactionLog transactionLog) throws XAException {
+ return new GeronimoPlatformTransactionManager(defaultTransactionTimeoutSeconds, xidFactory, transactionLog);
+ }
+
+ }
+}