[infinispan-commits] Infinispan SVN: r623 - in trunk: cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary and 8 other directories.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Wed Jul 29 05:02:14 EDT 2009
Author: mircea.markus
Date: 2009-07-29 05:02:14 -0400 (Wed, 29 Jul 2009)
New Revision: 623
Added:
trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/TableNameUniquenessTest.java
trunk/cachestore/jdbc/src/test/resources/binary.xml
trunk/cachestore/jdbc/src/test/resources/mixed.xml
trunk/cachestore/jdbc/src/test/resources/string-based.xml
Modified:
trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/TableManipulation.java
trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStore.java
trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStoreConfig.java
trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStore.java
trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfig.java
trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java
trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreConfig.java
trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/JdbcBinaryCacheStoreTest.java
trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/TableManipulationTest.java
trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfigTest.java
trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest.java
trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest2.java
trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreTest.java
trunk/cachestore/jdbc/src/test/java/org/infinispan/test/fwk/UnitTestDatabaseManager.java
trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsDistSync.java
Log:
[ISPN-106] (JdbcXyzCacheStore should honor cache name) - impemented
Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/TableManipulation.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/TableManipulation.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/TableManipulation.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -29,6 +29,8 @@
private String idColumnName;
private String idColumnType;
private String tableName;
+ private String tableNamePrefix;
+ private String cacheName;
private String dataColumnName;
private String dataColumnType;
private String timestampColumnName;
@@ -53,11 +55,11 @@
private String selectExpiredRowsSql;
private String deleteExpiredRowsSql;
- public TableManipulation(String idColumnName, String idColumnType, String tableName, String dataColumnName,
+ public TableManipulation(String idColumnName, String idColumnType, String tableNamePrefix, String dataColumnName,
String dataColumnType, String timestampColumnName, String timestampColumnType) {
this.idColumnName = idColumnName;
this.idColumnType = idColumnType;
- this.tableName = tableName;
+ this.tableNamePrefix = tableNamePrefix;
this.dataColumnName = dataColumnName;
this.dataColumnType = dataColumnType;
this.timestampColumnName = timestampColumnName;
@@ -68,7 +70,7 @@
}
public boolean tableExists(Connection connection, String tableName) throws CacheLoaderException {
- assrtNotNull(tableName, "table name is mandatory");
+ assrtNotNull(getTableName(), "table name is mandatory");
ResultSet rs = null;
try {
// (a j2ee spec compatible jdbc driver has to fully
@@ -119,7 +121,7 @@
public void createTable(Connection conn) throws CacheLoaderException {
// removed CONSTRAINT clause as this causes problems with some databases, like Informix.
assertMandatoryElemenetsPresent();
- String creatTableDdl = "CREATE TABLE " + tableName + "(" + idColumnName + " " + idColumnType
+ String creatTableDdl = "CREATE TABLE " + getTableName() + "(" + idColumnName + " " + idColumnType
+ " NOT NULL, " + dataColumnName + " " + dataColumnType + ", "
+ timestampColumnName + " " + timestampColumnType +
", PRIMARY KEY (" + idColumnName + "))";
@@ -131,7 +133,8 @@
private void assertMandatoryElemenetsPresent() throws CacheLoaderException {
assrtNotNull(idColumnType, "idColumnType needed in order to create table");
assrtNotNull(idColumnName, "idColumnName needed in order to create table");
- assrtNotNull(tableName, "tableName needed in order to create table");
+ assrtNotNull(tableNamePrefix, "tableNamePrefix needed in order to create table");
+ assrtNotNull(cacheName, "cacheName needed in order to create table");
assrtNotNull(dataColumnName, "dataColumnName needed in order to create table");
assrtNotNull(dataColumnType, "dataColumnType needed in order to create table");
assrtNotNull(timestampColumnName, "timestampColumnName needed in order to create table");
@@ -156,8 +159,8 @@
}
public void dropTable(Connection conn) throws CacheLoaderException {
- String dropTableDdl = "DROP TABLE " + tableName;
- String clearTable = "DELETE FROM " + tableName;
+ String dropTableDdl = "DROP TABLE " + getTableName();
+ String clearTable = "DELETE FROM " + getTableName();
executeUpdateSql(conn, clearTable);
if (log.isTraceEnabled())
log.trace("Dropping table with following DDL '" + dropTableDdl + "\'");
@@ -180,8 +183,8 @@
this.idColumnType = idColumnType;
}
- public void setTableName(String tableName) {
- this.tableName = tableName;
+ public void setTableNamePrefix(String tableNamePrefix) {
+ this.tableNamePrefix = tableNamePrefix;
}
public void setDataColumnName(String dataColumnName) {
@@ -221,7 +224,7 @@
if (isCreateTableOnStart()) {
Connection conn = this.connectionFactory.getConnection();
try {
- if (!tableExists(conn, tableName)) {
+ if (!tableExists(conn, getTableName())) {
createTable(conn);
}
} finally {
@@ -243,42 +246,42 @@
public String getInsertRowSql() {
if (insertRowSql == null) {
- insertRowSql = "INSERT INTO " + tableName + " (" + dataColumnName + ", " + timestampColumnName + ", " + idColumnName + ") VALUES(?,?,?)";
+ insertRowSql = "INSERT INTO " + getTableName() + " (" + dataColumnName + ", " + timestampColumnName + ", " + idColumnName + ") VALUES(?,?,?)";
}
return insertRowSql;
}
public String getUpdateRowSql() {
if (updateRowSql == null) {
- updateRowSql = "UPDATE " + tableName + " SET " + dataColumnName + " = ? , " + timestampColumnName + "=? WHERE " + idColumnName + " = ?";
+ updateRowSql = "UPDATE " + getTableName() + " SET " + dataColumnName + " = ? , " + timestampColumnName + "=? WHERE " + idColumnName + " = ?";
}
return updateRowSql;
}
public String getSelectRowSql() {
if (selectRowSql == null) {
- selectRowSql = "SELECT " + idColumnName + ", " + dataColumnName + " FROM " + tableName + " WHERE " + idColumnName + " = ?";
+ selectRowSql = "SELECT " + idColumnName + ", " + dataColumnName + " FROM " + getTableName() + " WHERE " + idColumnName + " = ?";
}
return selectRowSql;
}
public String getDeleteRowSql() {
if (deleteRowSql == null) {
- deleteRowSql = "DELETE FROM " + tableName + " WHERE " + idColumnName + " = ?";
+ deleteRowSql = "DELETE FROM " + getTableName() + " WHERE " + idColumnName + " = ?";
}
return deleteRowSql;
}
public String getLoadAllRowsSql() {
if (loadAllRowsSql == null) {
- loadAllRowsSql = "SELECT " + dataColumnName + "," + idColumnName + " FROM " + tableName;
+ loadAllRowsSql = "SELECT " + dataColumnName + "," + idColumnName + " FROM " + getTableName();
}
return loadAllRowsSql;
}
public String getDeleteAllRowsSql() {
if (deleteAllRows == null) {
- deleteAllRows = "DELETE FROM " + tableName;
+ deleteAllRows = "DELETE FROM " + getTableName();
}
return deleteAllRows;
}
@@ -292,7 +295,7 @@
public String getDeleteExpiredRowsSql() {
if (deleteExpiredRowsSql == null) {
- deleteExpiredRowsSql = "DELETE FROM " + tableName + " WHERE " + timestampColumnName + "< ? AND " + timestampColumnName + "> 0";
+ deleteExpiredRowsSql = "DELETE FROM " + getTableName() + " WHERE " + timestampColumnName + "< ? AND " + timestampColumnName + "> 0";
}
return deleteExpiredRowsSql;
}
@@ -307,9 +310,19 @@
}
public String getTableName() {
+ if (tableName == null) {
+ if (tableNamePrefix == null || cacheName == null) {
+ throw new IllegalStateException("Both tableNamePrefix and cacheName must be non null at this point!");
+ }
+ tableName = tableNamePrefix + "_" + cacheName;
+ }
return tableName;
}
+ public String getTableNamePrefix() {
+ return tableNamePrefix;
+ }
+
public boolean tableExists(Connection connection) throws CacheLoaderException {
return tableExists(connection, tableName);
}
@@ -369,4 +382,9 @@
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
+
+ public void setCacheName(String cacheName) {
+ this.cacheName = cacheName;
+ this.tableName = null;
+ }
}
Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStore.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStore.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStore.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -53,12 +53,14 @@
private ConnectionFactory connectionFactory;
private TableManipulation tableManipulation;
private DataManiulationHelper dmHelper;
+ private String cacheName;
public void init(CacheLoaderConfig config, Cache cache, Marshaller m) {
if (log.isTraceEnabled())
log.trace("Initializing JdbcBinaryCacheStore " + config);
super.init(config, cache, m);
this.config = (JdbcBinaryCacheStoreConfig) config;
+ this.cacheName = cache.getName();
}
public void start() throws CacheLoaderException {
@@ -345,6 +347,11 @@
public void doConnectionFactoryInitialization(ConnectionFactory connectionFactory) throws CacheLoaderException {
this.connectionFactory = connectionFactory;
tableManipulation = config.getTableManipulation();
+ tableManipulation.setCacheName(cacheName);
tableManipulation.start(connectionFactory);
}
+
+ public TableManipulation getTableManipulation() {
+ return tableManipulation;
+ }
}
Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStoreConfig.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStoreConfig.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStoreConfig.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -55,59 +55,55 @@
/**
* If true, the table will be created when cache store is stopped. Default to <tt>false</tt>.
*/
- @ConfigurationProperty(name="dropTableOnExit",
- parentElement="properties")
+ @ConfigurationProperty(name="dropTableOnExit", parentElement="properties")
public void setDropTableOnExit(boolean dropTableOnExit) {
testImmutability("tableManipulation");
this.tableManipulation.setDropTableOnExit(dropTableOnExit);
}
- @ConfigurationProperty(name="bucketTableName",
- parentElement="properties")
- public void setBucketTableName(String bucketTableName) {
+ /**
+ * Sets the prefix for the name of the table where the data will be stored. "_<cache name>" will be appended
+ * to this prefix in order to enforce unique table names for each cache.
+ */
+ @ConfigurationProperty(name="bucketTableNamePrefix", parentElement="properties")
+ public void setBucketTableNamePrefix(String bucketTableName) {
testImmutability("tableManipulation");
- this.tableManipulation.setTableName(bucketTableName);
+ this.tableManipulation.setTableNamePrefix(bucketTableName);
}
- @ConfigurationProperty(name="idColumnName",
- parentElement="properties")
+ @ConfigurationProperty(name="idColumnName", parentElement="properties")
public void setIdColumnName(String idColumnName) {
testImmutability("tableManipulation");
this.tableManipulation.setIdColumnName(idColumnName);
}
- @ConfigurationProperty(name="idColumnType",
- parentElement="properties")
+ @ConfigurationProperty(name="idColumnType", parentElement="properties")
public void setIdColumnType(String idColumnType) {
testImmutability("tableManipulation");
this.tableManipulation.setIdColumnType(idColumnType);
}
- @ConfigurationProperty(name="dataColumnName",
- parentElement="properties")
+ @ConfigurationProperty(name="dataColumnName", parentElement="properties")
public void setDataColumnName(String dataColumnName) {
testImmutability("tableManipulation");
this.tableManipulation.setDataColumnName(dataColumnName);
}
- @ConfigurationProperty(name="dataColumnType",
- parentElement="properties")
+ @ConfigurationProperty(name="dataColumnType", parentElement="properties")
public void setDataColumnType(String dataColumnType) {
testImmutability("tableManipulation");
this.tableManipulation.setDataColumnType(dataColumnType);
}
- @ConfigurationProperty(name="timestampColumnName",
- parentElement="properties")
+ @ConfigurationProperty(name="timestampColumnName", parentElement="properties")
public void setTimestampColumnName(String timestampColumnName) {
testImmutability("tableManipulation");
this.tableManipulation.setTimestampColumnName(timestampColumnName);
}
- @ConfigurationProperty(name="timestampColumnType",
- parentElement="properties")
+ @ConfigurationProperty(name="timestampColumnType", parentElement="properties")
public void setTimestampColumnType(String timestampColumnType) {
testImmutability("tableManipulation");
this.tableManipulation.setTimestampColumnType(timestampColumnType);
@@ -117,8 +113,7 @@
* Url connection to the database.
*/
- @ConfigurationProperty(name="connectionUrl",
- parentElement="properties")
+ @ConfigurationProperty(name="connectionUrl", parentElement="properties")
public void setConnectionUrl(String connectionUrl) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setConnectionUrl(connectionUrl);
@@ -127,8 +122,7 @@
/**
* Databse user name.
*/
- @ConfigurationProperty(name="userName",
- parentElement="properties")
+ @ConfigurationProperty(name="userName", parentElement="properties")
public void setUserName(String userName) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setUserName(userName);
@@ -137,8 +131,7 @@
/**
* Database username's password.
*/
- @ConfigurationProperty(name="password",
- parentElement="properties")
+ @ConfigurationProperty(name="password", parentElement="properties")
public void setPassword(String password) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setPassword(password);
@@ -147,8 +140,7 @@
/**
* Driver class, will be loaded before initializing the {@link org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactory}
*/
- @ConfigurationProperty(name="driverClass",
- parentElement="properties")
+ @ConfigurationProperty(name="driverClass", parentElement="properties")
public void setDriverClass(String driverClass) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setDriverClass(driverClass);
@@ -159,8 +151,7 @@
*
* @see org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactory
*/
- @ConfigurationProperty(name="connectionFactoryClass",
- parentElement="properties")
+ @ConfigurationProperty(name="connectionFactoryClass", parentElement="properties")
public void setConnectionFactoryClass(String connectionFactoryClass) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setConnectionFactoryClass(connectionFactoryClass);
@@ -191,8 +182,7 @@
/**
* @see org.infinispan.loaders.jdbc.TableManipulation#getFetchSize()
*/
- @ConfigurationProperty(name="fetchSize",
- parentElement="properties")
+ @ConfigurationProperty(name="fetchSize", parentElement="properties")
public void setFetchSize(int fetchSize) {
testImmutability("tableManipulation");
this.tableManipulation.setFetchSize(fetchSize);
@@ -201,8 +191,7 @@
/**
* @see org.infinispan.loaders.jdbc.TableManipulation#getBatchSize()
*/
- @ConfigurationProperty(name="batchSize",
- parentElement="properties")
+ @ConfigurationProperty(name="batchSize", parentElement="properties")
public void setBatchSize(int batchSize) {
testImmutability("tableManipulation");
this.tableManipulation.setBatchSize(batchSize);
Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStore.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStore.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStore.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -127,4 +127,12 @@
public ConnectionFactory getConnectionFactory() {
return sharedConnectionFactory;
}
+
+ public JdbcBinaryCacheStore getBinaryCacheStore() {
+ return binaryCacheStore;
+ }
+
+ public JdbcStringBasedCacheStore getStringBasedCacheStore() {
+ return stringBasedCacheStore;
+ }
}
Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfig.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfig.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfig.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -17,10 +17,10 @@
* @author Mircea.Markus at jboss.com
*/
@ConfigurationElements(elements = {
- @ConfigurationElement(name = "loader", parent = "loaders",
- description = "org.infinispan.loaders.jdbc.mixed.JdbcMixedCacheStore",
- cardinalityInParent=Cardinality.UNBOUNDED),
- @ConfigurationElement(name = "properties", parent = "loader") })
+ @ConfigurationElement(name = "loader", parent = "loaders",
+ description = "org.infinispan.loaders.jdbc.mixed.JdbcMixedCacheStore",
+ cardinalityInParent = Cardinality.UNBOUNDED),
+ @ConfigurationElement(name = "properties", parent = "loader")})
public class JdbcMixedCacheStoreConfig extends AbstractCacheStoreConfig {
private ConnectionFactoryConfig connectionFactoryConfig = new ConnectionFactoryConfig();
@@ -75,194 +75,204 @@
if (key2StringMapper != null) config.setKey2StringMapperClass(key2StringMapper);
return config;
}
-
- @ConfigurationProperty(name="idColumnNameForStrings",
- parentElement="properties")
+
+ @ConfigurationProperty(name = "idColumnNameForStrings",
+ parentElement = "properties")
public void setIdColumnNameForStrings(String idColumnNameForStrings) {
testImmutability("stringsTableManipulation");
this.stringsTableManipulation.setIdColumnName(idColumnNameForStrings);
}
- @ConfigurationProperty(name="idColumnTypeForStrings",
- parentElement="properties")
+ @ConfigurationProperty(name = "idColumnTypeForStrings",
+ parentElement = "properties")
public void setIdColumnTypeForStrings(String idColumnTypeForStrings) {
testImmutability("stringsTableManipulation");
this.stringsTableManipulation.setIdColumnType(idColumnTypeForStrings);
}
- @ConfigurationProperty(name="tableNameForStrings",
- parentElement="properties")
- public void setTableNameForStrings(String tableNameForStrings) {
+ @ConfigurationProperty(name = "tableNamePrefixForStrings", parentElement = "properties")
+ public void setTableNamePrefixForStrings(String tableNameForStrings) {
testImmutability("stringsTableManipulation");
if (tableNameForStrings == null) throw new IllegalArgumentException("Null table name not allowed.");
- if (tableNameForStrings.equals(this.binaryTableManipulation.getTableName())) {
+ if (tableNameForStrings.equals(this.binaryTableManipulation.getTableNamePrefix())) {
throw new IllegalArgumentException("Same table name is used for both cache loaders, this is not allowed!");
}
- this.stringsTableManipulation.setTableName(tableNameForStrings);
+ this.stringsTableManipulation.setTableNamePrefix(tableNameForStrings);
}
- @ConfigurationProperty(name="dataColumnNameForStrings",
- parentElement="properties")
+ @ConfigurationProperty(name = "dataColumnNameForStrings",
+ parentElement = "properties")
public void setDataColumnNameForStrings(String dataColumnNameForStrings) {
testImmutability("stringsTableManipulation");
this.stringsTableManipulation.setDataColumnName(dataColumnNameForStrings);
}
- @ConfigurationProperty(name="dataColumnTypeForStrings",
- parentElement="properties")
+ @ConfigurationProperty(name = "dataColumnTypeForStrings",
+ parentElement = "properties")
public void setDataColumnTypeForStrings(String dataColumnTypeForStrings) {
testImmutability("stringsTableManipulation");
this.stringsTableManipulation.setDataColumnType(dataColumnTypeForStrings);
}
- @ConfigurationProperty(name="timestampColumnNameForStrings",
- parentElement="properties")
+ @ConfigurationProperty(name = "timestampColumnNameForStrings",
+ parentElement = "properties")
public void setTimestampColumnNameForStrings(String timestampColumnNameForStrings) {
testImmutability("stringsTableManipulation");
this.stringsTableManipulation.setTimestampColumnName(timestampColumnNameForStrings);
}
- @ConfigurationProperty(name="timestampColumnTypeForStrings",
- parentElement="properties")
+ @ConfigurationProperty(name = "timestampColumnTypeForStrings",
+ parentElement = "properties")
public void setTimestampColumnTypeForStrings(String timestampColumnTypeForStrings) {
testImmutability("stringsTableManipulation");
this.stringsTableManipulation.setTimestampColumnType(timestampColumnTypeForStrings);
}
- @ConfigurationProperty(name="createTableOnStartForStrings",
- parentElement="properties")
+ @ConfigurationProperty(name = "createTableOnStartForStrings",
+ parentElement = "properties")
public void setCreateTableOnStartForStrings(boolean createTableOnStartForStrings) {
testImmutability("stringsTableManipulation");
this.stringsTableManipulation.setCreateTableOnStart(createTableOnStartForStrings);
}
- @ConfigurationProperty(name="dropTableOnExitForStrings",
- parentElement="properties")
+ @ConfigurationProperty(name = "dropTableOnExitForStrings",
+ parentElement = "properties")
public void setDropTableOnExitForStrings(boolean dropTableOnExitForStrings) {
testImmutability("stringsTableManipulation");
this.stringsTableManipulation.setDropTableOnExit(dropTableOnExitForStrings);
}
- @ConfigurationProperty(name="idColumnNameForBinary",
- parentElement="properties")
+ @ConfigurationProperty(name = "idColumnNameForBinary",
+ parentElement = "properties")
public void setIdColumnNameForBinary(String idColumnNameForBinary) {
this.binaryTableManipulation.setIdColumnName(idColumnNameForBinary);
}
- @ConfigurationProperty(name="idColumnTypeForBinary",
- parentElement="properties")
+ @ConfigurationProperty(name = "idColumnTypeForBinary",
+ parentElement = "properties")
public void setIdColumnTypeForBinary(String idColumnTypeForBinary) {
testImmutability("stringsTableManipulation");
this.binaryTableManipulation.setIdColumnType(idColumnTypeForBinary);
}
- @ConfigurationProperty(name="tableNameForBinary",
- parentElement="properties")
- public void setTableNameForBinary(String tableNameForBinary) {
+ @ConfigurationProperty(name = "tableNamePrefixForBinary",
+ parentElement = "properties")
+ public void setTableNamePrefixForBinary(String tableNameForBinary) {
testImmutability("binaryTableManipulation");
if (tableNameForBinary == null) throw new IllegalArgumentException("Null table name not allowed.");
- if (tableNameForBinary.equals(this.stringsTableManipulation.getTableName())) {
+ if (tableNameForBinary.equals(this.stringsTableManipulation.getTableNamePrefix())) {
throw new IllegalArgumentException("Same table name is used for both cache loaders, this is not allowed!");
}
- this.binaryTableManipulation.setTableName(tableNameForBinary);
+ this.binaryTableManipulation.setTableNamePrefix(tableNameForBinary);
}
- @ConfigurationProperty(name="dataColumnNameForBinary",
- parentElement="properties")
+ @ConfigurationProperty(name = "dataColumnNameForBinary",
+ parentElement = "properties")
public void setDataColumnNameForBinary(String dataColumnNameForBinary) {
testImmutability("binaryTableManipulation");
this.binaryTableManipulation.setDataColumnName(dataColumnNameForBinary);
}
- @ConfigurationProperty(name="dataColumnTypeForBinary",
- parentElement="properties")
+ @ConfigurationProperty(name = "dataColumnTypeForBinary",
+ parentElement = "properties")
public void setDataColumnTypeForBinary(String dataColumnTypeForBinary) {
testImmutability("binaryTableManipulation");
this.binaryTableManipulation.setDataColumnType(dataColumnTypeForBinary);
}
- @ConfigurationProperty(name="timestampColumnNameForBinary",
- parentElement="properties")
+ @ConfigurationProperty(name = "timestampColumnNameForBinary",
+ parentElement = "properties")
public void setTimestampColumnNameForBinary(String timestampColumnNameForBinary) {
testImmutability("binaryTableManipulation");
this.binaryTableManipulation.setTimestampColumnName(timestampColumnNameForBinary);
}
- @ConfigurationProperty(name="timestampColumnTypeForBinary",
- parentElement="properties")
+ @ConfigurationProperty(name = "timestampColumnTypeForBinary",
+ parentElement = "properties")
public void setTimestampColumnTypeForBinary(String timestampColumnTypeForBinary) {
this.binaryTableManipulation.setTimestampColumnType(timestampColumnTypeForBinary);
}
- @ConfigurationProperty(name="createTableOnStartForBinary",
- parentElement="properties")
+ @ConfigurationProperty(name = "createTableOnStartForBinary",
+ parentElement = "properties")
public void setCreateTableOnStartForBinary(boolean createTableOnStartForBinary) {
testImmutability("binaryTableManipulation");
this.binaryTableManipulation.setCreateTableOnStart(createTableOnStartForBinary);
}
- @ConfigurationProperty(name="dropTableOnExitForBinary",
- parentElement="properties")
+ @ConfigurationProperty(name = "dropTableOnExitForBinary",
+ parentElement = "properties")
public void setDropTableOnExitForBinary(boolean dropTableOnExitForBinary) {
testImmutability("binaryTableManipulation");
this.binaryTableManipulation.setDropTableOnExit(dropTableOnExitForBinary);
}
- @ConfigurationProperty(name="driverClass",
- parentElement="properties")
+ @ConfigurationProperty(name = "driverClass",
+ parentElement = "properties")
public void setDriverClass(String driverClass) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setDriverClass(driverClass);
}
- @ConfigurationProperty(name="connectionUrl",
- parentElement="properties")
+ @ConfigurationProperty(name = "connectionUrl",
+ parentElement = "properties")
public void setConnectionUrl(String connectionUrl) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setConnectionUrl(connectionUrl);
}
- @ConfigurationProperty(name="userName",
- parentElement="properties")
+ @ConfigurationProperty(name = "userName",
+ parentElement = "properties")
public void setUserName(String userName) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setUserName(userName);
}
- @ConfigurationProperty(name="password",
- parentElement="properties")
+ @ConfigurationProperty(name = "password",
+ parentElement = "properties")
public void setPassword(String password) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setPassword(password);
}
+ /**
+ * Name of the connection factory class.
+ *
+ * @see org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactory
+ */
+ @ConfigurationProperty(name = "connectionFactoryClass", parentElement = "properties")
+ public void setConnectionFactoryClass(String connectionFactoryClass) {
+ testImmutability("connectionFactoryConfig");
+ this.connectionFactoryConfig.setConnectionFactoryClass(connectionFactoryClass);
+ }
+
public ConnectionFactoryConfig getConnectionFactoryConfig() {
return connectionFactoryConfig;
}
- @ConfigurationProperty(name="key2StringMapperClass",
- parentElement="properties")
+ @ConfigurationProperty(name = "key2StringMapperClass",
+ parentElement = "properties")
public void setKey2StringMapperClass(String name) {
testImmutability("key2StringMapper");
this.key2StringMapper = name;
}
- @ConfigurationProperty(name="lockConcurrencyLevelForStrings",
- parentElement="properties")
+ @ConfigurationProperty(name = "lockConcurrencyLevelForStrings",
+ parentElement = "properties")
public void setLockConcurrencyLevelForStrings(int concurrencyLevel) {
testImmutability("stringsConcurrencyLevel");
this.stringsConcurrencyLevel = concurrencyLevel;
}
- @ConfigurationProperty(name="lockConcurrencyLevelForBinary",
- parentElement="properties")
+ @ConfigurationProperty(name = "lockConcurrencyLevelForBinary",
+ parentElement = "properties")
public void setLockConcurrencyLevelForBinary(int concurrencyLevel) {
testImmutability("binaryConcurrencyLevel");
this.binaryConcurrencyLevel = concurrencyLevel;
}
- @ConfigurationProperty(name="lockAcquistionTimeout",
- parentElement="properties")
+ @ConfigurationProperty(name = "lockAcquistionTimeout",
+ parentElement = "properties")
public void setLockAcquistionTimeout(int lockAcquistionTimeout) {
testImmutability("lockAcquistionTimeout");
this.lockAcquistionTimeout = lockAcquistionTimeout;
@@ -271,8 +281,8 @@
/**
* @see org.infinispan.loaders.jdbc.TableManipulation#getFetchSize()
*/
- @ConfigurationProperty(name="fetchSize",
- parentElement="properties")
+ @ConfigurationProperty(name = "fetchSize",
+ parentElement = "properties")
public void setFetchSize(int fetchSize) {
testImmutability("tableManipulation");
this.binaryTableManipulation.setFetchSize(fetchSize);
@@ -282,11 +292,20 @@
/**
* @see org.infinispan.loaders.jdbc.TableManipulation#getBatchSize()
*/
- @ConfigurationProperty(name="batchSize",
- parentElement="properties")
+ @ConfigurationProperty(name = "batchSize",
+ parentElement = "properties")
public void setBatchSize(int batchSize) {
testImmutability("tableManipulation");
this.binaryTableManipulation.setBatchSize(batchSize);
this.stringsTableManipulation.setBatchSize(batchSize);
}
+
+ @Override
+ public JdbcMixedCacheStoreConfig clone() {
+ JdbcMixedCacheStoreConfig dolly = (JdbcMixedCacheStoreConfig) super.clone();
+ dolly.connectionFactoryConfig = this.connectionFactoryConfig.clone();
+ dolly.binaryTableManipulation = this.binaryTableManipulation.clone();
+ dolly.stringsTableManipulation = this.stringsTableManipulation.clone();
+ return dolly;
+ }
}
Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -54,10 +54,12 @@
private ConnectionFactory connectionFactory;
private TableManipulation tableManipulation;
private DataManiulationHelper dmHelper;
+ private String cacheName;
public void init(CacheLoaderConfig config, Cache cache, Marshaller m) {
super.init(config, cache, m);
this.config = (JdbcStringBasedCacheStoreConfig) config;
+ this.cacheName = cache.getName();
}
@Override
@@ -267,10 +269,15 @@
public void doConnectionFactoryInitialization(ConnectionFactory connectionFactory) throws CacheLoaderException {
this.connectionFactory = connectionFactory;
tableManipulation = config.getTableManipulation();
+ tableManipulation.setCacheName(cacheName);
tableManipulation.start(connectionFactory);
}
public ConnectionFactory getConnectionFactory() {
return connectionFactory;
}
+
+ public TableManipulation getTableManipulation() {
+ return tableManipulation;
+ }
}
Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreConfig.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreConfig.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreConfig.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -71,13 +71,21 @@
}
/**
+ * Sets the prefix for the name of the table where the data will be stored. "_<cache name>" will be appended
+ * to this prefix in order to enforce unique table names for each cache.
+ */
+ @ConfigurationProperty(name="stringsTableNamePrefix", parentElement="properties")
+ public void setStringsTableNamePrefix(String stringsTableNamePrefix) {
+ testImmutability("tableManipulation");
+ this.tableManipulation.setTableNamePrefix(stringsTableNamePrefix);
+ }
+
+ /**
* Sets the name of the table where data will be stored.
*/
- @ConfigurationProperty(name="stringsTableName",
- parentElement="properties")
- public void setStringsTableName(String stringsTableName) {
+ public void setCacheName(String cacheName) {
testImmutability("tableManipulation");
- this.tableManipulation.setTableName(stringsTableName);
+ this.tableManipulation.setCacheName(cacheName);
}
/**
@@ -87,8 +95,7 @@
* </pre>
* Mandatory.
*/
- @ConfigurationProperty(name="idColumnName",
- parentElement="properties")
+ @ConfigurationProperty(name="idColumnName", parentElement="properties")
public void setIdColumnName(String idColumnName) {
testImmutability("tableManipulation");
this.tableManipulation.setIdColumnName(idColumnName);
@@ -97,8 +104,7 @@
/**
* Sets the name of the column where the StoredEntry will be binary stored. Mandatory.
*/
- @ConfigurationProperty(name="dataColumnName",
- parentElement="properties")
+ @ConfigurationProperty(name="dataColumnName", parentElement="properties")
public void setDataColumnName(String dataColumnName) {
testImmutability("tableManipulation");
this.tableManipulation.setDataColumnName(dataColumnName);
@@ -107,15 +113,23 @@
/**
* Sets the name of the column where the timestamp (Long in java) will be stored. Mandatory.
*/
- @ConfigurationProperty(name="timestampColumnName",
- parentElement="properties")
+ @ConfigurationProperty(name="timestampColumnName", parentElement="properties")
public void setTimestampColumnName(String timestampColumnName) {
testImmutability("tableManipulation");
this.tableManipulation.setTimestampColumnName(timestampColumnName);
}
- @ConfigurationProperty(name="connectionFactoryClass",
- parentElement="properties")
+ /**
+ * Sets the prefix for the name of the table where the data will be stored. "_<cache name>" will be appended
+ * to this prefix in order to enforce unique table names for each cache.
+ */
+ @ConfigurationProperty(name="timestampColumnType", parentElement="properties")
+ public void setTimestampColumnType(String timestampColumnType) {
+ testImmutability("tableManipulation");
+ this.tableManipulation.setTimestampColumnType(timestampColumnType);
+ }
+
+ @ConfigurationProperty(name="connectionFactoryClass", parentElement="properties")
public void setConnectionFactoryClass(String connectionFactoryClass) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setConnectionFactoryClass(connectionFactoryClass);
@@ -163,8 +177,7 @@
* The name of the driver used for connecting to the database. Mandatory, will be loaded before initiating the first
* connection.
*/
- @ConfigurationProperty(name="driverClass",
- parentElement="properties")
+ @ConfigurationProperty(name="driverClass", parentElement="properties")
public void setDriverClass(String driverClassName) {
testImmutability("connectionFactoryConfig");
this.connectionFactoryConfig.setDriverClass(driverClassName);
@@ -173,8 +186,7 @@
/**
* sql equivalent for java's String. Mandatory.
*/
- @ConfigurationProperty(name="idColumnType",
- parentElement="properties")
+ @ConfigurationProperty(name="idColumnType", parentElement="properties")
public void setIdColumnType(String idColumnType) {
testImmutability("tableManipulation");
this.tableManipulation.setIdColumnType(idColumnType);
@@ -183,8 +195,7 @@
/**
* Sets the type of the column where data will be binary stored. BLOB-like type, DBMS dependent. Mandatory.
*/
- @ConfigurationProperty(name="dataColumnType",
- parentElement="properties")
+ @ConfigurationProperty(name="dataColumnType", parentElement="properties")
public void setDataColumnType(String dataColumnType) {
testImmutability("tableManipulation");
this.tableManipulation.setDataColumnType(dataColumnType);
@@ -252,4 +263,12 @@
public int getBatchSize() {
return this.tableManipulation.getBatchSize();
}
+
+ @Override
+ public JdbcStringBasedCacheStoreConfig clone() {
+ JdbcStringBasedCacheStoreConfig result = (JdbcStringBasedCacheStoreConfig) super.clone();
+ result.connectionFactoryConfig = connectionFactoryConfig.clone();
+ result.tableManipulation = tableManipulation.clone();
+ return result;
+ }
}
Modified: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/JdbcBinaryCacheStoreTest.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/JdbcBinaryCacheStoreTest.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/JdbcBinaryCacheStoreTest.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -9,6 +9,7 @@
import org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactoryConfig;
import org.infinispan.marshall.TestObjectStreamMarshaller;
import org.infinispan.test.fwk.UnitTestDatabaseManager;
+import org.infinispan.CacheDelegate;
import org.testng.annotations.Test;
/**
@@ -24,7 +25,7 @@
TableManipulation tm = UnitTestDatabaseManager.buildDefaultTableManipulation();
JdbcBinaryCacheStoreConfig config = new JdbcBinaryCacheStoreConfig(connectionFactoryConfig, tm);
JdbcBinaryCacheStore jdbcBucketCacheStore = new JdbcBinaryCacheStore();
- jdbcBucketCacheStore.init(config, null, getMarshaller());
+ jdbcBucketCacheStore.init(config, new CacheDelegate("aName"), getMarshaller());
jdbcBucketCacheStore.start();
assert jdbcBucketCacheStore.getConnectionFactory() != null;
return jdbcBucketCacheStore;
@@ -34,7 +35,7 @@
JdbcBinaryCacheStore jdbcBucketCacheStore = new JdbcBinaryCacheStore();
JdbcBinaryCacheStoreConfig config = new JdbcBinaryCacheStoreConfig(false);
config.setCreateTableOnStart(false);
- jdbcBucketCacheStore.init(config, null, new TestObjectStreamMarshaller());
+ jdbcBucketCacheStore.init(config, new CacheDelegate("aName"), new TestObjectStreamMarshaller());
jdbcBucketCacheStore.start();
assert jdbcBucketCacheStore.getConnectionFactory() == null;
@@ -44,6 +45,7 @@
config.setTableManipulation(tableManipulation);
tableManipulation.start(connectionFactory);
+ tableManipulation.setCacheName("aName");
replay(tableManipulation);
jdbcBucketCacheStore.doConnectionFactoryInitialization(connectionFactory);
verify(tableManipulation);
Modified: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/TableManipulationTest.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/TableManipulationTest.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/TableManipulationTest.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -31,6 +31,7 @@
cfg = UnitTestDatabaseManager.getUniqueConnectionFactoryConfig();
connection = DriverManager.getConnection(cfg.getConnectionUrl(), cfg.getUserName(), cfg.getPassword());
tableManipulation = UnitTestDatabaseManager.buildDefaultTableManipulation();
+ tableManipulation.setCacheName("aName");
}
@AfterTest
@@ -132,7 +133,7 @@
assert tableManipulation.tableExists(connection);
PreparedStatement ps = null;
try {
- ps = connection.prepareStatement("INSERT INTO horizon_jdbc(ID_COLUMN) values(?)");
+ ps = connection.prepareStatement("INSERT INTO " + tableManipulation.getTableName() + "(ID_COLUMN) values(?)");
ps.setString(1, System.currentTimeMillis() + "");
assert 1 == ps.executeUpdate();
} finally {
Added: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/TableNameUniquenessTest.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/TableNameUniquenessTest.java (rev 0)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/TableNameUniquenessTest.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -0,0 +1,158 @@
+package org.infinispan.loaders.jdbc;
+
+import org.infinispan.Cache;
+import org.infinispan.loaders.CacheLoaderConfig;
+import org.infinispan.loaders.CacheLoaderException;
+import org.infinispan.loaders.CacheLoaderManager;
+import org.infinispan.loaders.CacheStore;
+import org.infinispan.loaders.jdbc.binary.JdbcBinaryCacheStore;
+import org.infinispan.loaders.jdbc.mixed.JdbcMixedCacheStore;
+import org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore;
+import org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStoreConfig;
+import org.infinispan.manager.CacheManager;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.marshall.Marshaller;
+import org.infinispan.marshall.VersionAwareMarshaller;
+import org.infinispan.test.TestingUtil;
+import org.testng.annotations.Test;
+
+import java.io.Serializable;
+import java.sql.Connection;
+
+/**
+ * Test to make sure that no two caches will use the same table for storing data.
+ *
+ * @author Mircea.Markus at jboss.com
+ */
+ at Test(groups = "functional", testName = "loaders.jdbc.TableNameUniquenessTest")
+public class TableNameUniquenessTest {
+
+ public void testForJdbcStringBasedCacheStore() throws Exception {
+ CacheManager cm = new DefaultCacheManager("string-based.xml");
+ Cache first = cm.getCache("first");
+ Cache second = cm.getCache("second");
+
+ CacheLoaderConfig firstCacheLoaderConfig = first.getConfiguration().getCacheLoaderManagerConfig().getFirstCacheLoaderConfig();
+ assert firstCacheLoaderConfig != null;
+ CacheLoaderConfig secondCacheLoaderConfig = second.getConfiguration().getCacheLoaderManagerConfig().getFirstCacheLoaderConfig();
+ assert secondCacheLoaderConfig != null;
+ assert firstCacheLoaderConfig instanceof JdbcStringBasedCacheStoreConfig;
+ assert secondCacheLoaderConfig instanceof JdbcStringBasedCacheStoreConfig;
+
+ //TODO - this is a hack as VAM.start does not get called, for some reason. This should be removed.
+ VersionAwareMarshaller firstVam = (VersionAwareMarshaller) TestingUtil.extractComponent(first, Marshaller.class);
+ firstVam.start();
+ VersionAwareMarshaller secondVam = (VersionAwareMarshaller) TestingUtil.extractComponent(first, Marshaller.class);
+ secondVam.start();
+
+ JdbcStringBasedCacheStore firstCs = (JdbcStringBasedCacheStore) TestingUtil.extractComponent(first, CacheLoaderManager.class).getCacheLoader();
+ JdbcStringBasedCacheStore secondCs = (JdbcStringBasedCacheStore) TestingUtil.extractComponent(second, CacheLoaderManager.class).getCacheLoader();
+
+ asserTableExistance(firstCs.getConnectionFactory().getConnection(), "ISPN_STRING_TABLE_second", "ISPN_STRING_TABLE_first", "ISPN_STRING_TABLE");
+
+ assertNoOverlapingState(first, second, firstCs, secondCs);
+ }
+
+ public void testForJdbcBinaryCacheStore() throws Exception {
+ CacheManager cm = new DefaultCacheManager("binary.xml");
+ Cache first = cm.getCache("first");
+ Cache second = cm.getCache("second");
+
+ //TODO - this is a hack as VAM.start does not get called, for some reason. This should be removed.
+ VersionAwareMarshaller firstVam = (VersionAwareMarshaller) TestingUtil.extractComponent(first, Marshaller.class);
+ firstVam.start();
+ VersionAwareMarshaller secondVam = (VersionAwareMarshaller) TestingUtil.extractComponent(first, Marshaller.class);
+ secondVam.start();
+
+ JdbcBinaryCacheStore firstCs = (JdbcBinaryCacheStore) TestingUtil.extractComponent(first, CacheLoaderManager.class).getCacheLoader();
+ JdbcBinaryCacheStore secondCs = (JdbcBinaryCacheStore) TestingUtil.extractComponent(second, CacheLoaderManager.class).getCacheLoader();
+
+ asserTableExistance(firstCs.getConnectionFactory().getConnection(), "ISPN_BUCKET_TABLE_second", "ISPN_BUCKET_TABLE_first", "IISPN_BUCKET_TABLE");
+
+ assertNoOverlapingState(first, second, firstCs, secondCs);
+ }
+
+ public void testForMixedCacheStore() throws Exception {
+ CacheManager cm = new DefaultCacheManager("mixed.xml");
+ Cache first = cm.getCache("first");
+ Cache second = cm.getCache("second");
+
+ //TODO - this is a hack as VAM.start does not get called, for some reason. This should be removed.
+ VersionAwareMarshaller firstVam = (VersionAwareMarshaller) TestingUtil.extractComponent(first, Marshaller.class);
+ firstVam.start();
+ VersionAwareMarshaller secondVam = (VersionAwareMarshaller) TestingUtil.extractComponent(first, Marshaller.class);
+ secondVam.start();
+
+ JdbcMixedCacheStore firstCs = (JdbcMixedCacheStore) TestingUtil.extractComponent(first, CacheLoaderManager.class).getCacheLoader();
+ JdbcMixedCacheStore secondCs = (JdbcMixedCacheStore) TestingUtil.extractComponent(second, CacheLoaderManager.class).getCacheLoader();
+
+ asserTableExistance(firstCs.getConnectionFactory().getConnection(), "ISPN_MIXED_STR_TABLE_second", "ISPN_MIXED_STR_TABLE_first", "ISPN_MIXED_STR_TABLE");
+ asserTableExistance(firstCs.getConnectionFactory().getConnection(), "ISPN_MIXED_BINARY_TABLE_second", "ISPN_MIXED_BINARY_TABLE_first", "ISPN_MIXED_BINARY_TABLE");
+
+ assertNoOverlapingState(first, second, firstCs, secondCs);
+
+
+ Person person1 = new Person(29, "Mircea");
+ Person person2 = new Person(29, "Manik");
+
+ first.put("k",person1);
+ assert firstCs.containsKey("k");
+ assert !secondCs.containsKey("k");
+ assert first.get("k").equals(person1);
+ assert second.get("k") == null;
+
+ second.put("k2",person2);
+ assert second.get("k2").equals(person2);
+ assert first.get("k2") == null;
+ }
+
+
+ static class Person implements Serializable {
+ int age;
+ String name;
+
+ Person(int age, String name) {
+ this.age = age;
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Person)) return false;
+
+ Person person = (Person) o;
+
+ if (age != person.age) return false;
+ if (name != null ? !name.equals(person.name) : person.name != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = age;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+ }
+
+ private void asserTableExistance(Connection connection, String secondTable, String firstTable, String tablePrefix) throws Exception {
+ assert !TableManipulationTest.existsTable(connection, tablePrefix) : "this table should not exist!";
+ assert TableManipulationTest.existsTable(connection, firstTable);
+ assert TableManipulationTest.existsTable(connection, secondTable);
+ connection.close();
+ }
+
+ private void assertNoOverlapingState(Cache first, Cache second, CacheStore firstCs, CacheStore secondCs) throws CacheLoaderException {
+ first.put("k","v");
+ assert firstCs.containsKey("k");
+ assert !secondCs.containsKey("k");
+ assert first.get("k").equals("v");
+ assert second.get("k") == null;
+
+ second.put("k2","v2");
+ assert second.get("k2").equals("v2");
+ assert first.get("k2") == null;
+ }
+}
Property changes on: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/TableNameUniquenessTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfigTest.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfigTest.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfigTest.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -44,17 +44,17 @@
}
public void testSameTableName() {
- config.setTableNameForBinary("table");
+ config.setTableNamePrefixForBinary("table");
try {
- config.setTableNameForStrings("table");
+ config.setTableNamePrefixForStrings("table");
assert false : "expection expected as same table name is not allowed for both cache stores";
} catch (Exception e) {
//expected
}
//and the other way around
- config.setTableNameForStrings("table2");
+ config.setTableNamePrefixForStrings("table2");
try {
- config.setTableNameForBinary("table2");
+ config.setTableNamePrefixForBinary("table2");
assert false : "expection expected as same table name is not allowed for both cache stores";
} catch (Exception e) {
//expected
Modified: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -1,5 +1,6 @@
package org.infinispan.loaders.jdbc.mixed;
+import org.infinispan.CacheDelegate;
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.container.entries.InternalEntryFactory;
import org.infinispan.io.UnclosableObjectInputStream;
@@ -44,16 +45,16 @@
@BeforeTest
public void createCacheStore() throws CacheLoaderException {
stringsTm = UnitTestDatabaseManager.buildDefaultTableManipulation();
- stringsTm.setTableName("STRINGS_TABLE");
+ stringsTm.setTableNamePrefix("STRINGS_TABLE");
binaryTm = UnitTestDatabaseManager.buildDefaultTableManipulation();
- binaryTm.setTableName("BINARY_TABLE");
+ binaryTm.setTableNamePrefix("BINARY_TABLE");
cfc = UnitTestDatabaseManager.getUniqueConnectionFactoryConfig();
JdbcMixedCacheStoreConfig cacheStoreConfig = new JdbcMixedCacheStoreConfig(cfc, binaryTm, stringsTm);
cacheStoreConfig.setPurgeSynchronously(true);
cacheStoreConfig.setKey2StringMapperClass(DefaultKey2StringMapper.class.getName());
cacheStore = new JdbcMixedCacheStore();
- cacheStore.init(cacheStoreConfig, null, getMarshaller());
+ cacheStore.init(cacheStoreConfig, new CacheDelegate("aName"), getMarshaller());
cacheStore.start();
}
@@ -182,9 +183,6 @@
assertRowCounts(1, 1);
}
- public void testTableConflict() {
- }
-
private void assertRowCounts(int binary, int strings) {
assertBinaryRowCount(binary);
assertStringsRowCount(strings);
Modified: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest2.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest2.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest2.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -12,9 +12,9 @@
protected CacheStore createCacheStore() throws Exception {
JdbcMixedCacheStoreConfig jdbcCacheStoreConfig = new JdbcMixedCacheStoreConfig();
TableManipulation stringsTm = UnitTestDatabaseManager.buildDefaultTableManipulation();
- stringsTm.setTableName("STRINGS_TABLE");
+ stringsTm.setTableNamePrefix("STRINGS_TABLE");
TableManipulation binaryTm = UnitTestDatabaseManager.buildDefaultTableManipulation();
- binaryTm.setTableName("BINARY_TABLE");
+ binaryTm.setTableNamePrefix("BINARY_TABLE");
ConnectionFactoryConfig cfc = UnitTestDatabaseManager.getUniqueConnectionFactoryConfig();
jdbcCacheStoreConfig.setConnectionFactoryConfig(cfc);
Modified: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreTest.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreTest.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreTest.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -7,6 +7,7 @@
import org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactory;
import org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactoryConfig;
import org.infinispan.test.fwk.UnitTestDatabaseManager;
+import org.infinispan.CacheDelegate;
import org.testng.annotations.Test;
/**
@@ -22,7 +23,7 @@
TableManipulation tm = UnitTestDatabaseManager.buildDefaultTableManipulation();
JdbcStringBasedCacheStoreConfig config = new JdbcStringBasedCacheStoreConfig(connectionFactoryConfig, tm);
JdbcStringBasedCacheStore jdbcBucketCacheStore = new JdbcStringBasedCacheStore();
- jdbcBucketCacheStore.init(config, null, getMarshaller());
+ jdbcBucketCacheStore.init(config, new CacheDelegate("aName"), getMarshaller());
jdbcBucketCacheStore.start();
return jdbcBucketCacheStore;
}
@@ -31,7 +32,7 @@
JdbcStringBasedCacheStore stringBasedCacheStore = new JdbcStringBasedCacheStore();
JdbcStringBasedCacheStoreConfig config = new JdbcStringBasedCacheStoreConfig(false);
config.setCreateTableOnStart(false);
- stringBasedCacheStore.init(config, null, getMarshaller());
+ stringBasedCacheStore.init(config, new CacheDelegate("otherName"), getMarshaller());
stringBasedCacheStore.start();
assert stringBasedCacheStore.getConnectionFactory() == null;
@@ -41,6 +42,7 @@
config.setTableManipulation(tableManipulation);
tableManipulation.start(connectionFactory);
+ tableManipulation.setCacheName("otherName");
replay(tableManipulation);
stringBasedCacheStore.doConnectionFactoryInitialization(connectionFactory);
verify(tableManipulation);
Modified: trunk/cachestore/jdbc/src/test/java/org/infinispan/test/fwk/UnitTestDatabaseManager.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/test/fwk/UnitTestDatabaseManager.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/test/fwk/UnitTestDatabaseManager.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -120,7 +120,7 @@
public static TableManipulation buildDefaultTableManipulation() {
- return new TableManipulation("ID_COLUMN", "VARCHAR(255)", "HORIZON_JDBC", "DATA_COLUMN",
+ return new TableManipulation("ID_COLUMN", "VARCHAR(255)", "ISPN_JDBC", "DATA_COLUMN",
"BINARY", "TIMESTAMP_COLUMN", "BIGINT");
}
Added: trunk/cachestore/jdbc/src/test/resources/binary.xml
===================================================================
--- trunk/cachestore/jdbc/src/test/resources/binary.xml (rev 0)
+++ trunk/cachestore/jdbc/src/test/resources/binary.xml 2009-07-29 09:02:14 UTC (rev 623)
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:infinispan:config:4.0">
+
+ <global>
+
+ <!-- Note that if these are left blank, defaults are used. See the user guide for what these defaults are -->
+ <asyncListenerExecutor factory="org.infinispan.executors.DefaultExecutorFactory">
+ <property name="maxThreads" value="5"/>
+ <property name="threadNamePrefix" value="AsyncListenerThread"/>
+ </asyncListenerExecutor>
+
+ <asyncTransportExecutor factory="org.infinispan.executors.DefaultExecutorFactory">
+ <property name="maxThreads" value="25"/>
+ <property name="threadNamePrefix" value="AsyncSerializationThread"/>
+ </asyncTransportExecutor>
+
+ <evictionScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
+ <property name="threadNamePrefix" value="EvictionThread"/>
+ </evictionScheduledExecutor>
+
+ <replicationQueueScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
+ <property name="threadNamePrefix" value="ReplicationQueueThread"/>
+ </replicationQueueScheduledExecutor>
+
+ <globalJmxStatistics enabled="false" jmxDomain="infinispan"/>
+
+ <serialization marshallerClass="org.infinispan.marshall.VersionAwareMarshaller" version="1.0"/>
+
+ <shutdown hookBehavior="DEFAULT"/>
+ </global>
+
+ <default>
+ <locking
+ isolationLevel="REPEATABLE_READ"
+ lockAcquisitionTimeout="20000"
+ writeSkewCheck="false"
+ concurrencyLevel="500" useLockStriping="false"/>
+ <loaders>
+ <loader class="org.infinispan.loaders.jdbc.binary.JdbcBinaryCacheStore" fetchPersistentState="false"
+ ignoreModifications="false" purgeOnStartup="false">
+ <properties>
+ <property name="bucketTableNamePrefix" value="ISPN_BUCKET_TABLE"/>
+ <property name="idColumnName" value="ID_COLUMN"/>
+ <property name="dataColumnName" value="DATA_COLUMN"/>
+ <property name="timestampColumnName" value="TIMESTAMP_COLUMN"/>
+ <property name="timestampColumnType" value="BIGINT"/>
+ <property name="connectionFactoryClass" value="org.infinispan.loaders.jdbc.connectionfactory.SimpleConnectionFactory"/>
+ <property name="connectionUrl" value="jdbc:hsqldb:mem:infinispan_binary_based"/>
+ <property name="userName" value="sa"/>
+ <property name="driverClass" value="org.hsqldb.jdbcDriver"/>
+ <property name="idColumnType" value="VARCHAR(255)"/>
+ <property name="dataColumnType" value="BINARY"/>
+ <property name="dropTableOnExit" value="false"/>
+ <property name="createTableOnStart" value="true"/>
+ </properties>
+ </loader>
+ </loaders>
+
+ </default>
+
+
+ <namedCache name="first"/>
+
+ <namedCache name="second"/>
+
+ </infinispan>
Property changes on: trunk/cachestore/jdbc/src/test/resources/binary.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: trunk/cachestore/jdbc/src/test/resources/mixed.xml
===================================================================
--- trunk/cachestore/jdbc/src/test/resources/mixed.xml (rev 0)
+++ trunk/cachestore/jdbc/src/test/resources/mixed.xml 2009-07-29 09:02:14 UTC (rev 623)
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:infinispan:config:4.0">
+
+ <global>
+
+ <!-- Note that if these are left blank, defaults are used. See the user guide for what these defaults are -->
+ <asyncListenerExecutor factory="org.infinispan.executors.DefaultExecutorFactory">
+ <property name="maxThreads" value="5"/>
+ <property name="threadNamePrefix" value="AsyncListenerThread"/>
+ </asyncListenerExecutor>
+
+ <asyncTransportExecutor factory="org.infinispan.executors.DefaultExecutorFactory">
+ <property name="maxThreads" value="25"/>
+ <property name="threadNamePrefix" value="AsyncSerializationThread"/>
+ </asyncTransportExecutor>
+
+ <evictionScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
+ <property name="threadNamePrefix" value="EvictionThread"/>
+ </evictionScheduledExecutor>
+
+ <replicationQueueScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
+ <property name="threadNamePrefix" value="ReplicationQueueThread"/>
+ </replicationQueueScheduledExecutor>
+
+ <globalJmxStatistics enabled="false" jmxDomain="infinispan"/>
+
+ <serialization marshallerClass="org.infinispan.marshall.VersionAwareMarshaller" version="1.0"/>
+
+ <shutdown hookBehavior="DEFAULT"/>
+ </global>
+
+ <default>
+ <locking
+ isolationLevel="REPEATABLE_READ"
+ lockAcquisitionTimeout="20000"
+ writeSkewCheck="false"
+ concurrencyLevel="500" useLockStriping="false"/>
+ <loaders>
+ <loader class="org.infinispan.loaders.jdbc.mixed.JdbcMixedCacheStore" fetchPersistentState="false"
+ ignoreModifications="false" purgeOnStartup="false">
+ <properties>
+ <property name="tableNamePrefixForStrings" value="ISPN_MIXED_STR_TABLE"/>
+ <property name="tableNamePrefixForBinary" value="ISPN_MIXED_BINARY_TABLE"/>
+ <property name="idColumnNameForStrings" value="ID_COLUMN"/>
+ <property name="idColumnNameForBinary" value="ID_COLUMN"/>
+ <property name="dataColumnNameForStrings" value="DATA_COLUMN"/>
+ <property name="dataColumnNameForBinary" value="DATA_COLUMN"/>
+ <property name="timestampColumnNameForStrings" value="TIMESTAMP_COLUMN"/>
+ <property name="timestampColumnNameForBinary" value="TIMESTAMP_COLUMN"/>
+ <property name="timestampColumnTypeForStrings" value="BIGINT"/>
+ <property name="timestampColumnTypeForBinary" value="BIGINT"/>
+ <property name="connectionFactoryClass"
+ value="org.infinispan.loaders.jdbc.connectionfactory.SimpleConnectionFactory"/>
+ <property name="connectionUrl" value="jdbc:hsqldb:mem:infinispan_mixed_cs"/>
+ <property name="userName" value="sa"/>
+ <property name="driverClass" value="org.hsqldb.jdbcDriver"/>
+ <property name="idColumnTypeForStrings" value="VARCHAR(255)"/>
+ <property name="idColumnTypeForBinary" value="VARCHAR(255)"/>
+ <property name="dataColumnTypeForStrings" value="BINARY"/>
+ <property name="dataColumnTypeForBinary" value="BINARY"/>
+ <property name="dropTableOnExitForStrings" value="false"/>
+ <property name="dropTableOnExitForBinary" value="false"/>
+ <property name="createTableOnStartForStrings" value="true"/>
+ <property name="createTableOnStartForBinary" value="true"/>
+ <property name="createTableOnStartForStrings" value="true"/>
+ <property name="createTableOnStartForBinary" value="true"/>
+ </properties>
+ </loader>
+ </loaders>
+
+ </default>
+
+
+ <namedCache name="first"/>
+
+ <namedCache name="second"/>
+
+</infinispan>
Property changes on: trunk/cachestore/jdbc/src/test/resources/mixed.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: trunk/cachestore/jdbc/src/test/resources/string-based.xml
===================================================================
--- trunk/cachestore/jdbc/src/test/resources/string-based.xml (rev 0)
+++ trunk/cachestore/jdbc/src/test/resources/string-based.xml 2009-07-29 09:02:14 UTC (rev 623)
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:infinispan:config:4.0">
+
+ <global>
+
+ <!-- Note that if these are left blank, defaults are used. See the user guide for what these defaults are -->
+ <asyncListenerExecutor factory="org.infinispan.executors.DefaultExecutorFactory">
+ <property name="maxThreads" value="5"/>
+ <property name="threadNamePrefix" value="AsyncListenerThread"/>
+ </asyncListenerExecutor>
+
+ <asyncTransportExecutor factory="org.infinispan.executors.DefaultExecutorFactory">
+ <property name="maxThreads" value="25"/>
+ <property name="threadNamePrefix" value="AsyncSerializationThread"/>
+ </asyncTransportExecutor>
+
+ <evictionScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
+ <property name="threadNamePrefix" value="EvictionThread"/>
+ </evictionScheduledExecutor>
+
+ <replicationQueueScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
+ <property name="threadNamePrefix" value="ReplicationQueueThread"/>
+ </replicationQueueScheduledExecutor>
+
+ <globalJmxStatistics enabled="false" jmxDomain="infinispan"/>
+
+ <serialization marshallerClass="org.infinispan.marshall.VersionAwareMarshaller" version="1.0"/>
+
+ <shutdown hookBehavior="DEFAULT"/>
+ </global>
+
+ <default>
+ <locking
+ isolationLevel="REPEATABLE_READ"
+ lockAcquisitionTimeout="20000"
+ writeSkewCheck="false"
+ concurrencyLevel="500" useLockStriping="false"/>
+ <loaders>
+ <loader class="org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore" fetchPersistentState="false"
+ ignoreModifications="false" purgeOnStartup="false">
+ <properties>
+ <property name="stringsTableNamePrefix" value="ISPN_STRING_TABLE"/>
+ <property name="idColumnName" value="ID_COLUMN"/>
+ <property name="dataColumnName" value="DATA_COLUMN"/>
+ <property name="timestampColumnName" value="TIMESTAMP_COLUMN"/>
+ <property name="timestampColumnType" value="BIGINT"/>
+ <property name="connectionFactoryClass" value="org.infinispan.loaders.jdbc.connectionfactory.SimpleConnectionFactory"/>
+ <property name="connectionUrl" value="org.infinispan.loaders.jdbc.connectionfactory.SimpleConnectionFactory"/>
+ <property name="connectionUrl" value="jdbc:hsqldb:mem:infinispan_string_based"/>
+ <property name="userName" value="sa"/>
+ <property name="driverClass" value="org.hsqldb.jdbcDriver"/>
+ <property name="idColumnType" value="VARCHAR(255)"/>
+ <property name="dataColumnType" value="BINARY"/>
+ <property name="dropTableOnExit" value="false"/>
+ <property name="createTableOnStart" value="true"/>
+ </properties>
+ </loader>
+ </loaders>
+
+ </default>
+
+
+ <namedCache name="first"/>
+
+ <namedCache name="second"/>
+
+ </infinispan>
Property changes on: trunk/cachestore/jdbc/src/test/resources/string-based.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsDistSync.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsDistSync.java 2009-07-28 14:24:30 UTC (rev 622)
+++ trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsDistSync.java 2009-07-29 09:02:14 UTC (rev 623)
@@ -29,13 +29,17 @@
private final ReclosableLatch flushWaitGate = new ReclosableLatch(false);
private final ReclosableLatch joinInProgress = new ReclosableLatch(false);
private static final Log log = LogFactory.getLog(JGroupsDistSync.class);
+ public static final boolean trace = log.isTraceEnabled();
+
public void blockUntilNoJoinsInProgress() {
- while (true) {
+ while (Thread.currentThread().isInterrupted()) {
try {
joinInProgress.await();
return;
} catch (InterruptedException ie) {
+ if (trace)
+ log.trace("Interrupted while waiting for the joinInProgress gate");
Thread.currentThread().interrupt();
}
}
@@ -107,10 +111,14 @@
}
public void signalJoinInProgress() {
+ if (trace)
+ log.trace("Closing joinInProgress gate");
joinInProgress.close();
}
public void signalJoinCompleted() {
+ if (trace)
+ log.trace("Releasing " + joinInProgress + " gate");
joinInProgress.open();
}
}
More information about the infinispan-commits
mailing list