Permalink
Browse files

Refactor following introduction of JdbcConnectionUuid. Add type-safe …

…classes to hold keys of schema content, connection definition, and schema.
  • Loading branch information...
1 parent 127aa72 commit 5bd12011bf0e834e4ff027e9622c95d83a552d9b @julianhyde julianhyde committed Sep 21, 2012
@@ -77,6 +77,12 @@
private static final Random metaRandom =
createRandom(MondrianProperties.instance().TestSeed.get());
+ /** Unique id for this JVM instance. Part of a key that ensures that if
+ * two JVMs in the same cluster have a data-source with the same
+ * identity-hash-code, they will be treated as different data-sources,
+ * and therefore caches will not be incorrectly shared. */
+ public static final UUID JVM_INSTANCE_UUID = UUID.randomUUID();
+
/**
* Whether we are running a version of Java before 1.5.
*
@@ -0,0 +1,77 @@
+/*
+// This software is subject to the terms of the Eclipse Public License v1.0
+// Agreement, available at the following URL:
+// http://www.eclipse.org/legal/epl-v10.html.
+// You must accept the terms of that agreement to use this software.
+//
+// Copyright (C) 2012-2012 Pentaho and others
+// All Rights Reserved.
+*/
+package mondrian.rolap;
+
+import mondrian.olap.Util;
+import mondrian.util.*;
+
+import javax.sql.DataSource;
+
+/**
+ * Globally unique identifier for the definition of a JDBC database connection.
+ *
+ * <p>Two connections should have the same connection key if and only if their
+ * databases have the same content.</p>
+ *
+ * @see RolapConnectionProperties#JdbcConnectionUuid
+ *
+ * @author jhyde
+ */
+class ConnectionKey extends StringKey {
+ private ConnectionKey(String s) {
+ super(s);
+ }
+
+ static ConnectionKey create(
+ final String connectionUuidStr,
+ final DataSource dataSource,
+ final String catalogUrl,
+ final String connectionKey,
+ final String jdbcUser,
+ final String dataSourceStr)
+ {
+ String s;
+ if (connectionUuidStr != null
+ && !connectionUuidStr.isEmpty())
+ {
+ s = connectionUuidStr;
+ } else {
+ final StringBuilder buf = new StringBuilder(100);
+ if (dataSource != null) {
+ attributeValue(buf, "jvm", Util.JVM_INSTANCE_UUID);
+ attributeValue(
+ buf, "dataSource", System.identityHashCode(dataSource));
+ } else {
+ attributeValue(buf, "connectionKey", connectionKey);
+ attributeValue(buf, "catalogUrl", catalogUrl);
+ attributeValue(buf, "jdbcUser", jdbcUser);
+ attributeValue(buf, "dataSourceStr", dataSourceStr);
+ }
+ s = new ByteString(Util.digestMd5(buf.toString())).toString();
+ }
+ return new ConnectionKey(s);
+ }
+
+ static void attributeValue(
+ StringBuilder buf, String attribute, Object value)
+ {
+ if (value == null) {
+ return;
+ }
+ if (buf.length() > 0) {
+ buf.append(';');
+ }
+ buf.append(attribute)
+ .append('=');
+ Util.quoteForMdx(buf, value.toString());
+ }
+}
+
+// End ConnectionKey.java
@@ -5,7 +5,7 @@
// You must accept the terms of that agreement to use this software.
//
// Copyright (C) 2003-2005 Julian Hyde
-// Copyright (C) 2005-2010 Pentaho
+// Copyright (C) 2005-2012 Pentaho
// All Rights Reserved.
*/
package mondrian.rolap;
@@ -30,7 +30,7 @@
/**
* The "Jdbc" property is the URL of the JDBC database where the data is
- * stored. You must specify either {@link #DataSource} or {@link #Jdbc}.
+ * stored. You must specify either {@link #DataSource} or {@code #Jdbc}.
*/
Jdbc,
@@ -90,7 +90,7 @@
/**
* The "DataSource" property is the name of a data source class. It must
* implement the {@link javax.sql.DataSource} interface.
- * You must specify either {@link #DataSource} or {@link #Jdbc}.
+ * You must specify either {@code DataSource} or {@link #Jdbc}.
*/
DataSource,
@@ -168,9 +168,10 @@
Instance,
/**
- * The "JdbcConnectionUuid" is the unique identifier for the connection.
- * If defined, Mondrian will assume that two connections bearing the same JdbcConnectionUuid
- * point to perfectly identical databases without looking at any other properties.
+ * The "JdbcConnectionUuid" property is the unique identifier for the
+ * underlying JDBC connection. If defined, Mondrian will assume that two
+ * connections bearing the same JdbcConnectionUuid point to identical
+ * databases without looking at any other properties.
*/
JdbcConnectionUuid;
@@ -104,8 +104,6 @@
private ByteString md5Bytes;
- private final boolean useContentChecksum;
-
/**
* A schema's aggregation information
*/
@@ -115,7 +113,7 @@
* This is basically a unique identifier for this RolapSchema instance
* used it its equals and hashCode methods.
*/
- final String key;
+ final SchemaKey key;
/**
* Maps {@link String names of roles} to {@link Role roles with those names}.
@@ -170,7 +168,7 @@
* @param useContentChecksum Whether to use content checksum
*/
private RolapSchema(
- final String key,
+ final SchemaKey key,
final Util.PropertyList connectInfo,
final DataSource dataSource,
final ByteString md5Bytes,
@@ -179,8 +177,9 @@ private RolapSchema(
this.id = Util.generateUuidString();
this.key = key;
this.md5Bytes = md5Bytes;
- this.useContentChecksum = useContentChecksum;
- assert !(useContentChecksum && md5Bytes == null);
+ if (useContentChecksum && md5Bytes == null) {
+ throw new AssertionError();
+ }
// the order of the next two lines is important
this.defaultRole = Util.createRootRole(this);
@@ -206,7 +205,7 @@ private RolapSchema(
* @param connectInfo Connection properties
*/
RolapSchema(
- String key,
+ SchemaKey key,
ByteString md5Bytes,
String catalogUrl,
String catalogStr,
@@ -576,7 +575,7 @@ private void load(MondrianDef.Schema xmlSchema) {
} else {
// At this stage, the only roles in mapNameToRole are
// RoleImpl roles so it is safe to case.
- defaultRole = (RoleImpl) role;
+ defaultRole = role;
}
}
}
@@ -1218,7 +1217,8 @@ public SchemaReader getSchemaReader() {
}
/**
- * Creates a {@link DataSourceChangeListener} with which to detect changes to datasources.
+ * Creates a {@link DataSourceChangeListener} with which to detect changes
+ * to datasources.
*/
private DataSourceChangeListener createDataSourceChangeListener(
Util.PropertyList connectInfo)
@@ -1231,23 +1231,12 @@ private DataSourceChangeListener createDataSourceChangeListener(
String dataSourceChangeListenerStr = connectInfo.get(
RolapConnectionProperties.DataSourceChangeListener.name());
- if (! Util.isEmpty(dataSourceChangeListenerStr)) {
+ if (!Util.isEmpty(dataSourceChangeListenerStr)) {
try {
Class<?> clazz = Class.forName(dataSourceChangeListenerStr);
Constructor<?> constructor = clazz.getConstructor();
changeListener =
(DataSourceChangeListener) constructor.newInstance();
-
-/*
- final Class<DataSourceChangeListener> clazz =
- (Class<DataSourceChangeListener>)
- Class.forName(dataSourceChangeListenerStr);
- final Constructor<DataSourceChangeListener> ctor =
- clazz.getConstructor();
- changeListener = ctor.newInstance();
-*/
- changeListener =
- (DataSourceChangeListener) constructor.newInstance();
} catch (Exception e) {
throw Util.newError(
e,
Oops, something went wrong.

0 comments on commit 5bd1201

Please sign in to comment.