diff --git a/build.xml b/build.xml index 1a62fa342f..90c4bd446d 100644 --- a/build.xml +++ b/build.xml @@ -8,6 +8,8 @@ + + + + @@ -88,4 +92,30 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/org/apache/cassandra/config/DatabaseDescriptor.java b/src/org/apache/cassandra/config/DatabaseDescriptor.java index 1cb791f3ea..683009c9ae 100644 --- a/src/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/org/apache/cassandra/config/DatabaseDescriptor.java @@ -25,6 +25,8 @@ import java.io.*; import org.apache.cassandra.db.ColumnFamily; import org.apache.cassandra.db.Table; import org.apache.cassandra.db.TypeInfo; +import org.apache.cassandra.db.DBManager; +import org.apache.cassandra.db.SystemTable; import org.apache.cassandra.db.Table.TableMetadata; import org.apache.cassandra.utils.FileUtils; import org.apache.cassandra.utils.XMLUtils; @@ -114,304 +116,347 @@ public class DatabaseDescriptor // the path qualified config file (storage-conf.xml) name private static String configFileName_; - - public static Map> init(String filePath) throws Throwable + + static { - /* Read the configuration file to retrieve DB related properties. */ - String file = filePath + System.getProperty("file.separator") + "storage-conf.xml"; - return initInternal(file); - } + try + { + String file = System.getProperty("storage-config") + System.getProperty("file.separator") + "storage-conf.xml"; + String os = System.getProperty("os.name"); + XMLUtils xmlUtils = new XMLUtils(file); - public static Map> init() throws Throwable - { - /* Read the configuration file to retrieve DB related properties. */ - configFileName_ = System.getProperty("storage-config") + System.getProperty("file.separator") + "storage-conf.xml"; - return initInternal(configFileName_); + /* Cluster Name */ + clusterName_ = xmlUtils.getNodeValue("/Storage/ClusterName"); + + /* Ganglia servers contact list */ + gangliaServers_ = xmlUtils.getNodeValues("/Storage/GangliaServers/GangliaServer"); + + /* ZooKeeper's address */ + zkAddress_ = xmlUtils.getNodeValue("/Storage/ZookeeperAddress"); + + /* Hashing strategy */ + hashingStrategy_ = xmlUtils.getNodeValue("/Storage/HashingStrategy"); + /* Callout location */ + calloutLocation_ = xmlUtils.getNodeValue("/Storage/CalloutLocation"); + + /* JobTracker address */ + jobTrackerHost_ = xmlUtils.getNodeValue("/Storage/JobTrackerHost"); + + /* Job Jar file location */ + jobJarFileLocation_ = xmlUtils.getNodeValue("/Storage/JobJarFileLocation"); + + /* Zookeeper's session timeout */ + String zkSessionTimeout = xmlUtils.getNodeValue("/Storage/ZookeeperSessionTimeout"); + if ( zkSessionTimeout != null ) + zkSessionTimeout_ = Integer.parseInt(zkSessionTimeout); + + /* Data replication factor */ + String replicationFactor = xmlUtils.getNodeValue("/Storage/ReplicationFactor"); + if ( replicationFactor != null ) + replicationFactor_ = Integer.parseInt(replicationFactor); + + /* RPC Timeout */ + String rpcTimeoutInMillis = xmlUtils.getNodeValue("/Storage/RpcTimeoutInMillis"); + if ( rpcTimeoutInMillis != null ) + rpcTimeoutInMillis_ = Integer.parseInt(rpcTimeoutInMillis); + + /* Thread per pool */ + String threadsPerPool = xmlUtils.getNodeValue("/Storage/ThreadsPerPool"); + if ( threadsPerPool != null ) + threadsPerPool_ = Integer.parseInt(threadsPerPool); + + /* TCP port on which the storage system listens */ + String port = xmlUtils.getNodeValue("/Storage/StoragePort"); + if ( port != null ) + storagePort_ = Integer.parseInt(port); + + /* UDP port for control messages */ + port = xmlUtils.getNodeValue("/Storage/ControlPort"); + if ( port != null ) + controlPort_ = Integer.parseInt(port); + + /* HTTP port for HTTP messages */ + port = xmlUtils.getNodeValue("/Storage/HttpPort"); + if ( port != null ) + httpPort_ = Integer.parseInt(port); + + /* Touch Key Cache Size */ + String touchKeyCacheSize = xmlUtils.getNodeValue("/Storage/TouchKeyCacheSize"); + if ( touchKeyCacheSize != null ) + touchKeyCacheSize_ = Integer.parseInt(touchKeyCacheSize); + + /* Number of days to keep the memtable around w/o flushing */ + String lifetime = xmlUtils.getNodeValue("/Storage/MemtableLifetimeInDays"); + if ( lifetime != null ) + memtableLifetime_ = Integer.parseInt(lifetime); + + /* Size of the memtable in memory in MB before it is dumped */ + String memtableSize = xmlUtils.getNodeValue("/Storage/MemtableSizeInMB"); + if ( memtableSize != null ) + memtableSize_ = Integer.parseInt(memtableSize); + /* Number of objects in millions in the memtable before it is dumped */ + String memtableObjectCount = xmlUtils.getNodeValue("/Storage/MemtableObjectCountInMillions"); + if ( memtableObjectCount != null ) + memtableObjectCount_ = Integer.parseInt(memtableObjectCount); + + /* This parameter enables or disables consistency checks. + * If set to false the read repairs are disable for very + * high throughput on reads but at the cost of consistency.*/ + String doConsistencyCheck = xmlUtils.getNodeValue("/Storage/DoConsistencyChecksBoolean"); + if ( doConsistencyCheck != null ) + doConsistencyCheck_ = Boolean.parseBoolean(doConsistencyCheck); + + + /* read the size at which we should do column indexes */ + String columnIndexSizeInKB = xmlUtils.getNodeValue("/Storage/ColumnIndexSizeInKB"); + if(columnIndexSizeInKB == null) + { + columnIndexSizeInKB_ = 64; + } + else + { + columnIndexSizeInKB_ = Integer.parseInt(columnIndexSizeInKB); + } + + /* metadata directory */ + metadataDirectory_ = xmlUtils.getNodeValue("/Storage/MetadataDirectory"); + if ( metadataDirectory_ != null ) + FileUtils.createDirectory(metadataDirectory_); + else + { + if ( os.equals("Linux") ) + { + metadataDirectory_ = "/var/storage/system"; + } + } + + /* snapshot directory */ + snapshotDirectory_ = xmlUtils.getNodeValue("/Storage/SnapshotDirectory"); + if ( snapshotDirectory_ != null ) + FileUtils.createDirectory(snapshotDirectory_); + else + { + snapshotDirectory_ = metadataDirectory_ + System.getProperty("file.separator") + "snapshot"; + } + + /* map output directory */ + mapOutputDirectories_ = xmlUtils.getNodeValues("/Storage/MapOutputDirectories/MapOutputDirectory"); + if ( mapOutputDirectories_.length > 0 ) + { + for ( String mapOutputDirectory : mapOutputDirectories_ ) + FileUtils.createDirectory(mapOutputDirectory); + } + + /* data file directory */ + dataFileDirectories_ = xmlUtils.getNodeValues("/Storage/DataFileDirectories/DataFileDirectory"); + if ( dataFileDirectories_.length > 0 ) + { + for ( String dataFileDirectory : dataFileDirectories_ ) + FileUtils.createDirectory(dataFileDirectory); + } + else + { + if ( os.equals("Linux") ) + { + dataFileDirectories_ = new String[]{"/var/storage/data"}; + } + } + + /* bootstrap file directory */ + bootstrapFileDirectory_ = xmlUtils.getNodeValue("/Storage/BootstrapFileDirectory"); + if ( bootstrapFileDirectory_ != null ) + FileUtils.createDirectory(bootstrapFileDirectory_); + else + { + if ( os.equals("Linux") ) + { + bootstrapFileDirectory_ = "/var/storage/bootstrap"; + } + } + + /* commit log directory */ + logFileDirectory_ = xmlUtils.getNodeValue("/Storage/CommitLogDirectory"); + if ( logFileDirectory_ != null ) + FileUtils.createDirectory(logFileDirectory_); + else + { + if ( os.equals("Linux") ) + { + logFileDirectory_ = "/var/storage/commitlog"; + } + } + + /* threshold after which commit log should be rotated. */ + String value = xmlUtils.getNodeValue("/Storage/CommitLogRotationThresholdInMB"); + if ( value != null) + logRotationThreshold_ = Integer.parseInt(value) * 1024 * 1024; + + /* fast sync option */ + value = xmlUtils.getNodeValue("/Storage/CommitLogFastSync"); + if ( value != null ) + fastSync_ = Boolean.parseBoolean(value); + + tableToCFMetaDataMap_ = new HashMap>(); + + /* Rack Aware option */ + value = xmlUtils.getNodeValue("/Storage/RackAware"); + if ( value != null ) + rackAware_ = Boolean.parseBoolean(value); + + /* Read the table related stuff from config */ + NodeList tables = xmlUtils.getRequestedNodeList("/Storage/Tables/Table"); + int size = tables.getLength(); + for ( int i = 0; i < size; ++i ) + { + Node table = tables.item(i); + + /* parsing out the table name */ + String tName = XMLUtils.getAttributeValue(table, "Name"); + tables_.add(tName); + tableToCFMetaDataMap_.put(tName, new HashMap()); + + String xqlTable = "/Storage/Tables/Table[@Name='" + tName + "']/"; + NodeList columnFamilies = xmlUtils.getRequestedNodeList(xqlTable + "ColumnFamily"); + + // get name of the rowKey for this table + String n_rowKey = xmlUtils.getNodeValue(xqlTable + "RowKey"); + if (n_rowKey == null) + n_rowKey = d_rowKey_; + + //NodeList columnFamilies = xmlUtils.getRequestedNodeList(table, "ColumnFamily"); + int size2 = columnFamilies.getLength(); + + for ( int j = 0; j < size2; ++j ) + { + Node columnFamily = columnFamilies.item(j); + String cName = XMLUtils.getAttributeValue(columnFamily, "Name"); + String xqlCF = xqlTable + "ColumnFamily[@Name='" + cName + "']/"; + + /* squirrel away the application column families */ + applicationColumnFamilies_.add(cName); + + // Parse out the column type + String columnType = xmlUtils.getAttributeValue(columnFamily, "ColumnType"); + columnType = ColumnFamily.getColumnType(columnType); + + // Parse out the column family sorting property for columns + String columnIndexProperty = XMLUtils.getAttributeValue(columnFamily, "ColumnSort"); + String columnIndexType = ColumnFamily.getColumnSortProperty(columnIndexProperty); + + // Parse out user-specified logical names for the various dimensions + // of a the column family from the config. + String n_superColumnMap = xmlUtils.getNodeValue(xqlCF + "SuperColumnMap"); + if (n_superColumnMap == null) + n_superColumnMap = d_superColumnMap_; + + String n_superColumnKey = xmlUtils.getNodeValue(xqlCF + "SuperColumnKey"); + if (n_superColumnKey == null) + n_superColumnKey = d_superColumnKey_; + + String n_columnMap = xmlUtils.getNodeValue(xqlCF + "ColumnMap"); + if (n_columnMap == null) + n_columnMap = d_columnMap_; + + String n_columnKey = xmlUtils.getNodeValue(xqlCF + "ColumnKey"); + if (n_columnKey == null) + n_columnKey = d_columnKey_; + + String n_columnValue = xmlUtils.getNodeValue(xqlCF + "ColumnValue"); + if (n_columnValue == null) + n_columnValue = d_columnValue_; + + String n_columnTimestamp = xmlUtils.getNodeValue(xqlCF + "ColumnTimestamp"); + if (n_columnTimestamp == null) + n_columnTimestamp = d_columnTimestamp_; + + // now populate the column family meta data and + // insert it into the table dictionary. + CFMetaData cfMetaData = new CFMetaData(); + + cfMetaData.tableName = tName; + cfMetaData.cfName = cName; + + cfMetaData.columnType = columnType; + cfMetaData.indexProperty_ = columnIndexType; + + cfMetaData.n_rowKey = n_rowKey; + cfMetaData.n_columnMap = n_columnMap; + cfMetaData.n_columnKey = n_columnKey; + cfMetaData.n_columnValue = n_columnValue; + cfMetaData.n_columnTimestamp = n_columnTimestamp; + if ("Super".equals(columnType)) + { + cfMetaData.n_superColumnKey = n_superColumnKey; + cfMetaData.n_superColumnMap = n_superColumnMap; + } + + tableToCFMetaDataMap_.get(tName).put(cName, cfMetaData); + } + } + + /* Load the seeds for node contact points */ + String[] seeds = xmlUtils.getNodeValues("/Storage/Seeds/Seed"); + for( int i = 0; i < seeds.length; ++i ) + { + seeds_.add( seeds[i] ); + } + } + catch (Exception e) { + throw new RuntimeException(e); + } + + try + { + storeMetadata(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } } - public static Map> initInternal(String file) throws Throwable + + /* + * Create the metadata tables. This table has information about + * the table name and the column families that make up the table. + * Each column family also has an associated ID which is an int. + */ + private static void storeMetadata() throws IOException { - String os = System.getProperty("os.name"); - XMLUtils xmlUtils = new XMLUtils(file); + AtomicInteger idGenerator = new AtomicInteger(0); + Set tables = tableToCFMetaDataMap_.keySet(); - /* Cluster Name */ - clusterName_ = xmlUtils.getNodeValue("/Storage/ClusterName"); - - /* Ganglia servers contact list */ - gangliaServers_ = xmlUtils.getNodeValues("/Storage/GangliaServers/GangliaServer"); - - /* ZooKeeper's address */ - zkAddress_ = xmlUtils.getNodeValue("/Storage/ZookeeperAddress"); - - /* Hashing strategy */ - hashingStrategy_ = xmlUtils.getNodeValue("/Storage/HashingStrategy"); - /* Callout location */ - calloutLocation_ = xmlUtils.getNodeValue("/Storage/CalloutLocation"); - - /* JobTracker address */ - jobTrackerHost_ = xmlUtils.getNodeValue("/Storage/JobTrackerHost"); - - /* Job Jar file location */ - jobJarFileLocation_ = xmlUtils.getNodeValue("/Storage/JobJarFileLocation"); - - /* Zookeeper's session timeout */ - String zkSessionTimeout = xmlUtils.getNodeValue("/Storage/ZookeeperSessionTimeout"); - if ( zkSessionTimeout != null ) - zkSessionTimeout_ = Integer.parseInt(zkSessionTimeout); - - /* Data replication factor */ - String replicationFactor = xmlUtils.getNodeValue("/Storage/ReplicationFactor"); - if ( replicationFactor != null ) - replicationFactor_ = Integer.parseInt(replicationFactor); - - /* RPC Timeout */ - String rpcTimeoutInMillis = xmlUtils.getNodeValue("/Storage/RpcTimeoutInMillis"); - if ( rpcTimeoutInMillis != null ) - rpcTimeoutInMillis_ = Integer.parseInt(rpcTimeoutInMillis); - - /* Thread per pool */ - String threadsPerPool = xmlUtils.getNodeValue("/Storage/ThreadsPerPool"); - if ( threadsPerPool != null ) - threadsPerPool_ = Integer.parseInt(threadsPerPool); - - /* TCP port on which the storage system listens */ - String port = xmlUtils.getNodeValue("/Storage/StoragePort"); - if ( port != null ) - storagePort_ = Integer.parseInt(port); - - /* UDP port for control messages */ - port = xmlUtils.getNodeValue("/Storage/ControlPort"); - if ( port != null ) - controlPort_ = Integer.parseInt(port); - - /* HTTP port for HTTP messages */ - port = xmlUtils.getNodeValue("/Storage/HttpPort"); - if ( port != null ) - httpPort_ = Integer.parseInt(port); - - /* Touch Key Cache Size */ - String touchKeyCacheSize = xmlUtils.getNodeValue("/Storage/TouchKeyCacheSize"); - if ( touchKeyCacheSize != null ) - touchKeyCacheSize_ = Integer.parseInt(touchKeyCacheSize); - - /* Number of days to keep the memtable around w/o flushing */ - String lifetime = xmlUtils.getNodeValue("/Storage/MemtableLifetimeInDays"); - if ( lifetime != null ) - memtableLifetime_ = Integer.parseInt(lifetime); - - /* Size of the memtable in memory in MB before it is dumped */ - String memtableSize = xmlUtils.getNodeValue("/Storage/MemtableSizeInMB"); - if ( memtableSize != null ) - memtableSize_ = Integer.parseInt(memtableSize); - /* Number of objects in millions in the memtable before it is dumped */ - String memtableObjectCount = xmlUtils.getNodeValue("/Storage/MemtableObjectCountInMillions"); - if ( memtableObjectCount != null ) - memtableObjectCount_ = Integer.parseInt(memtableObjectCount); - - /* This parameter enables or disables consistency checks. - * If set to false the read repairs are disable for very - * high throughput on reads but at the cost of consistency.*/ - String doConsistencyCheck = xmlUtils.getNodeValue("/Storage/DoConsistencyChecksBoolean"); - if ( doConsistencyCheck != null ) - doConsistencyCheck_ = Boolean.parseBoolean(doConsistencyCheck); - - - /* read the size at which we should do column indexes */ - String columnIndexSizeInKB = xmlUtils.getNodeValue("/Storage/ColumnIndexSizeInKB"); - if(columnIndexSizeInKB == null) + for ( String table : tables ) { - columnIndexSizeInKB_ = 64; - } - else - { - columnIndexSizeInKB_ = Integer.parseInt(columnIndexSizeInKB); - } - - /* metadata directory */ - metadataDirectory_ = xmlUtils.getNodeValue("/Storage/MetadataDirectory"); - if ( metadataDirectory_ != null ) - FileUtils.createDirectory(metadataDirectory_); - else - { - if ( os.equals("Linux") ) + Table.TableMetadata tmetadata = Table.TableMetadata.instance(); + if (tmetadata.isEmpty()) { - metadataDirectory_ = "/var/storage/system"; - } - } + tmetadata = Table.TableMetadata.instance(); + /* Column families associated with this table */ + Map columnFamilies = tableToCFMetaDataMap_.get(table); - /* snapshot directory */ - snapshotDirectory_ = xmlUtils.getNodeValue("/Storage/SnapshotDirectory"); - if ( snapshotDirectory_ != null ) - FileUtils.createDirectory(snapshotDirectory_); - else - { - snapshotDirectory_ = metadataDirectory_ + System.getProperty("file.separator") + "snapshot"; - } - - /* map output directory */ - mapOutputDirectories_ = xmlUtils.getNodeValues("/Storage/MapOutputDirectories/MapOutputDirectory"); - if ( mapOutputDirectories_.length > 0 ) - { - for ( String mapOutputDirectory : mapOutputDirectories_ ) - FileUtils.createDirectory(mapOutputDirectory); - } - - /* data file directory */ - dataFileDirectories_ = xmlUtils.getNodeValues("/Storage/DataFileDirectories/DataFileDirectory"); - if ( dataFileDirectories_.length > 0 ) - { - for ( String dataFileDirectory : dataFileDirectories_ ) - FileUtils.createDirectory(dataFileDirectory); - } - else - { - if ( os.equals("Linux") ) - { - dataFileDirectories_ = new String[]{"/var/storage/data"}; - } - } - - /* bootstrap file directory */ - bootstrapFileDirectory_ = xmlUtils.getNodeValue("/Storage/BootstrapFileDirectory"); - if ( bootstrapFileDirectory_ != null ) - FileUtils.createDirectory(bootstrapFileDirectory_); - else - { - if ( os.equals("Linux") ) - { - bootstrapFileDirectory_ = "/var/storage/bootstrap"; - } - } - - /* commit log directory */ - logFileDirectory_ = xmlUtils.getNodeValue("/Storage/CommitLogDirectory"); - if ( logFileDirectory_ != null ) - FileUtils.createDirectory(logFileDirectory_); - else - { - if ( os.equals("Linux") ) - { - logFileDirectory_ = "/var/storage/commitlog"; - } - } - - /* threshold after which commit log should be rotated. */ - String value = xmlUtils.getNodeValue("/Storage/CommitLogRotationThresholdInMB"); - if ( value != null) - logRotationThreshold_ = Integer.parseInt(value) * 1024 * 1024; - - /* fast sync option */ - value = xmlUtils.getNodeValue("/Storage/CommitLogFastSync"); - if ( value != null ) - fastSync_ = Boolean.parseBoolean(value); - - tableToCFMetaDataMap_ = new HashMap>(); - - /* Rack Aware option */ - value = xmlUtils.getNodeValue("/Storage/RackAware"); - if ( value != null ) - rackAware_ = Boolean.parseBoolean(value); - - /* Read the table related stuff from config */ - NodeList tables = xmlUtils.getRequestedNodeList("/Storage/Tables/Table"); - int size = tables.getLength(); - for ( int i = 0; i < size; ++i ) - { - Node table = tables.item(i); - - /* parsing out the table name */ - String tName = XMLUtils.getAttributeValue(table, "Name"); - tables_.add(tName); - tableToCFMetaDataMap_.put(tName, new HashMap()); - - String xqlTable = "/Storage/Tables/Table[@Name='" + tName + "']/"; - NodeList columnFamilies = xmlUtils.getRequestedNodeList(xqlTable + "ColumnFamily"); - - // get name of the rowKey for this table - String n_rowKey = xmlUtils.getNodeValue(xqlTable + "RowKey"); - if (n_rowKey == null) - n_rowKey = d_rowKey_; - - //NodeList columnFamilies = xmlUtils.getRequestedNodeList(table, "ColumnFamily"); - int size2 = columnFamilies.getLength(); - - for ( int j = 0; j < size2; ++j ) - { - Node columnFamily = columnFamilies.item(j); - String cName = XMLUtils.getAttributeValue(columnFamily, "Name"); - String xqlCF = xqlTable + "ColumnFamily[@Name='" + cName + "']/"; - - /* squirrel away the application column families */ - applicationColumnFamilies_.add(cName); - - // Parse out the column type - String columnType = xmlUtils.getAttributeValue(columnFamily, "ColumnType"); - columnType = ColumnFamily.getColumnType(columnType); - - // Parse out the column family sorting property for columns - String columnIndexProperty = XMLUtils.getAttributeValue(columnFamily, "ColumnSort"); - String columnIndexType = ColumnFamily.getColumnSortProperty(columnIndexProperty); - - // Parse out user-specified logical names for the various dimensions - // of a the column family from the config. - String n_superColumnMap = xmlUtils.getNodeValue(xqlCF + "SuperColumnMap"); - if (n_superColumnMap == null) - n_superColumnMap = d_superColumnMap_; - - String n_superColumnKey = xmlUtils.getNodeValue(xqlCF + "SuperColumnKey"); - if (n_superColumnKey == null) - n_superColumnKey = d_superColumnKey_; - - String n_columnMap = xmlUtils.getNodeValue(xqlCF + "ColumnMap"); - if (n_columnMap == null) - n_columnMap = d_columnMap_; - - String n_columnKey = xmlUtils.getNodeValue(xqlCF + "ColumnKey"); - if (n_columnKey == null) - n_columnKey = d_columnKey_; - - String n_columnValue = xmlUtils.getNodeValue(xqlCF + "ColumnValue"); - if (n_columnValue == null) - n_columnValue = d_columnValue_; - - String n_columnTimestamp = xmlUtils.getNodeValue(xqlCF + "ColumnTimestamp"); - if (n_columnTimestamp == null) - n_columnTimestamp = d_columnTimestamp_; - - // now populate the column family meta data and - // insert it into the table dictionary. - CFMetaData cfMetaData = new CFMetaData(); - - cfMetaData.tableName = tName; - cfMetaData.cfName = cName; - - cfMetaData.columnType = columnType; - cfMetaData.indexProperty_ = columnIndexType; - - cfMetaData.n_rowKey = n_rowKey; - cfMetaData.n_columnMap = n_columnMap; - cfMetaData.n_columnKey = n_columnKey; - cfMetaData.n_columnValue = n_columnValue; - cfMetaData.n_columnTimestamp = n_columnTimestamp; - if ("Super".equals(columnType)) + for (String columnFamily : columnFamilies.keySet()) { - cfMetaData.n_superColumnKey = n_superColumnKey; - cfMetaData.n_superColumnMap = n_superColumnMap; + tmetadata.add(columnFamily, idGenerator.getAndIncrement(), DatabaseDescriptor.getColumnType(columnFamily)); } - tableToCFMetaDataMap_.get(tName).put(cName, cfMetaData); + /* + * Here we add all the system related column families. + */ + /* Add the TableMetadata column family to this map. */ + tmetadata.add(Table.TableMetadata.cfName_, idGenerator.getAndIncrement()); + /* Add the LocationInfo column family to this map. */ + tmetadata.add(SystemTable.cfName_, idGenerator.getAndIncrement()); + /* Add the recycle column family to this map. */ + tmetadata.add(Table.recycleBin_, idGenerator.getAndIncrement()); + /* Add the Hints column family to this map. */ + tmetadata.add(Table.hints_, idGenerator.getAndIncrement(), ColumnFamily.getColumnType("Super")); + tmetadata.apply(); + idGenerator.set(0); } } - - /* Load the seeds for node contact points */ - String[] seeds = xmlUtils.getNodeValues("/Storage/Seeds/Seed"); - for( int i = 0; i < seeds.length; ++i ) - { - seeds_.add( seeds[i] ); - } - return tableToCFMetaDataMap_; } - + public static String getHashingStrategy() { return hashingStrategy_; @@ -735,9 +780,9 @@ public class DatabaseDescriptor return TypeInfo.LONG; } } - - public static void main(String[] args) throws Throwable + + public static Map> getTableToColumnFamilyMap() { - DatabaseDescriptor.initInternal("C:\\Engagements\\Cassandra-Golden\\storage-conf.xml"); + return tableToCFMetaDataMap_; } } diff --git a/src/org/apache/cassandra/db/BinaryMemtable.java b/src/org/apache/cassandra/db/BinaryMemtable.java index 254601f2a1..64dc2b4944 100644 --- a/src/org/apache/cassandra/db/BinaryMemtable.java +++ b/src/org/apache/cassandra/db/BinaryMemtable.java @@ -29,8 +29,9 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.io.SSTable; import org.apache.cassandra.utils.BloomFilter; +import org.apache.cassandra.io.SSTable; + import org.apache.log4j.Logger; import org.cliffc.high_scale_lib.NonBlockingHashMap; diff --git a/src/org/apache/cassandra/db/CommitLog.java b/src/org/apache/cassandra/db/CommitLog.java index ff4911cdd9..4aa151b8f3 100644 --- a/src/org/apache/cassandra/db/CommitLog.java +++ b/src/org/apache/cassandra/db/CommitLog.java @@ -626,9 +626,6 @@ class CommitLog public static void main(String[] args) throws Throwable { LogUtil.init(); - - // the return value is not used in this case - DatabaseDescriptor.init(); File logDir = new File(DatabaseDescriptor.getLogFileLocation()); File[] files = logDir.listFiles(); diff --git a/src/org/apache/cassandra/db/DBManager.java b/src/org/apache/cassandra/db/DBManager.java index 7ef718d7ec..7a9c6426e5 100644 --- a/src/org/apache/cassandra/db/DBManager.java +++ b/src/org/apache/cassandra/db/DBManager.java @@ -91,10 +91,7 @@ public class DBManager public DBManager() throws Throwable { - /* Read the configuration file */ - Map> tableToColumnFamilyMap = DatabaseDescriptor.init(); - storeMetadata(tableToColumnFamilyMap); - Set tables = tableToColumnFamilyMap.keySet(); + Set tables = DatabaseDescriptor.getTableToColumnFamilyMap().keySet(); for (String table : tables) { @@ -106,47 +103,6 @@ public class DBManager recoveryMgr.doRecovery(); } - /* - * Create the metadata tables. This table has information about - * the table name and the column families that make up the table. - * Each column family also has an associated ID which is an int. - */ - private static void storeMetadata(Map> tableToColumnFamilyMap) throws Throwable - { - AtomicInteger idGenerator = new AtomicInteger(0); - Set tables = tableToColumnFamilyMap.keySet(); - - for ( String table : tables ) - { - Table.TableMetadata tmetadata = Table.TableMetadata.instance(); - if ( tmetadata.isEmpty() ) - { - tmetadata = Table.TableMetadata.instance(); - /* Column families associated with this table */ - Map columnFamilies = tableToColumnFamilyMap.get(table); - - for (String columnFamily : columnFamilies.keySet()) - { - tmetadata.add(columnFamily, idGenerator.getAndIncrement(), DatabaseDescriptor.getColumnType(columnFamily)); - } - - /* - * Here we add all the system related column families. - */ - /* Add the TableMetadata column family to this map. */ - tmetadata.add(Table.TableMetadata.cfName_, idGenerator.getAndIncrement()); - /* Add the LocationInfo column family to this map. */ - tmetadata.add(SystemTable.cfName_, idGenerator.getAndIncrement()); - /* Add the recycle column family to this map. */ - tmetadata.add(Table.recycleBin_, idGenerator.getAndIncrement()); - /* Add the Hints column family to this map. */ - tmetadata.add(Table.hints_, idGenerator.getAndIncrement(), ColumnFamily.getColumnType("Super")); - tmetadata.apply(); - idGenerator.set(0); - } - } - } - /* * This method reads the system table and retrieves the metadata * associated with this storage instance. Currently we store the diff --git a/src/org/apache/cassandra/db/RecoveryManager.java b/src/org/apache/cassandra/db/RecoveryManager.java index 7a901c14de..f4e2d75bd9 100644 --- a/src/org/apache/cassandra/db/RecoveryManager.java +++ b/src/org/apache/cassandra/db/RecoveryManager.java @@ -93,7 +93,6 @@ public class RecoveryManager public static void main(String[] args) throws Throwable { - DatabaseDescriptor.init(); long start = System.currentTimeMillis(); RecoveryManager rm = RecoveryManager.instance(); rm.doRecovery(); diff --git a/src/org/apache/cassandra/db/SystemTable.java b/src/org/apache/cassandra/db/SystemTable.java index 50968c49cc..23999a0ff1 100644 --- a/src/org/apache/cassandra/db/SystemTable.java +++ b/src/org/apache/cassandra/db/SystemTable.java @@ -45,7 +45,7 @@ public class SystemTable /* Name of the SystemTable */ public static final String name_ = "System"; /* Name of the only column family in the Table */ - static final String cfName_ = "LocationInfo"; + public static final String cfName_ = "LocationInfo"; /* Name of columns in this table */ static final String generation_ = "Generation"; static final String token_ = "Token"; diff --git a/src/org/apache/cassandra/db/Table.java b/src/org/apache/cassandra/db/Table.java index be5b0e2977..85386d4cbe 100644 --- a/src/org/apache/cassandra/db/Table.java +++ b/src/org/apache/cassandra/db/Table.java @@ -153,7 +153,7 @@ public class Table cfTypeMap_.put(cf, type); } - boolean isEmpty() + public boolean isEmpty() { return cfIdMap_.isEmpty(); } @@ -193,7 +193,7 @@ public class Table return cfIdMap_.containsKey(cfName); } - void apply() throws IOException + public void apply() throws IOException { String table = DatabaseDescriptor.getTables().get(0); DataOutputBuffer bufOut = new DataOutputBuffer(); @@ -895,13 +895,4 @@ public class Table long timeTaken = System.currentTimeMillis() - start; dbAnalyticsSource_.updateWriteStatistics(timeTaken); } - - public static void main(String[] args) throws Throwable - { - StorageService service = StorageService.instance(); - service.start(); - Table table = Table.open("Mailbox"); - Row row = table.get("35300190:1"); - System.out.println( row.key() ); - } } diff --git a/src/org/apache/cassandra/service/StorageService.java b/src/org/apache/cassandra/service/StorageService.java index 84f444c381..a0dd149f7f 100644 --- a/src/org/apache/cassandra/service/StorageService.java +++ b/src/org/apache/cassandra/service/StorageService.java @@ -171,7 +171,7 @@ public final class StorageService implements IEndPointStateChangeSubscriber, Sto public static PartitionerType getPartitionerType() { - return (DatabaseDescriptor.getHashingStrategy().equalsIgnoreCase(DatabaseDescriptor.ophf_)) ? PartitionerType.OPHF : PartitionerType.RANDOM; + return (DatabaseDescriptor.ophf_.equalsIgnoreCase(DatabaseDescriptor.getHashingStrategy())) ? PartitionerType.OPHF : PartitionerType.RANDOM; } /** @@ -444,10 +444,10 @@ public final class StorageService implements IEndPointStateChangeSubscriber, Sto components_.add(component); } - private void initPartitioner() + static { String hashingStrategy = DatabaseDescriptor.getHashingStrategy(); - if ( hashingStrategy.equalsIgnoreCase(DatabaseDescriptor.ophf_) ) + if (DatabaseDescriptor.ophf_.equalsIgnoreCase(hashingStrategy)) { partitioner_ = new OrderPreservingHashPartitioner(); } @@ -458,9 +458,7 @@ public final class StorageService implements IEndPointStateChangeSubscriber, Sto } public void start() throws Throwable - { - /* Set up the partitioner */ - initPartitioner(); + { /* Start the DB */ storageMetadata_ = DBManager.instance().start(); /* Set up TCP endpoint */ diff --git a/src/org/apache/cassandra/test/DBTest.java b/src/org/apache/cassandra/test/DBTest.java index 212513ac02..068088e86d 100644 --- a/src/org/apache/cassandra/test/DBTest.java +++ b/src/org/apache/cassandra/test/DBTest.java @@ -182,7 +182,6 @@ public class DBTest //doWrites(); //doRead("543"); - DatabaseDescriptor.init(); DBTest.doTest(); } } diff --git a/test/org/apache/cassandra/ServerTest.java b/test/org/apache/cassandra/ServerTest.java new file mode 100644 index 0000000000..59db562838 --- /dev/null +++ b/test/org/apache/cassandra/ServerTest.java @@ -0,0 +1,22 @@ +package org.apache.cassandra; + +import org.testng.annotations.Test; +import org.testng.annotations.BeforeMethod; + +import java.io.File; + +@Test(groups={"serial"}) +public class ServerTest { + // TODO clean up static structures too (e.g. memtables) + @BeforeMethod + public void cleanup() { + // for convenience, this assumes that you haven't changed the test config away from storing everything + // under /var/cassandra. + for (String dirname : new String[] {"bootstrap", "commitlog", "data", "staging", "system"}) { + File dir = new File("/var/cassandra", dirname); + for (File f : dir.listFiles()) { + f.delete(); + } + } + } +} diff --git a/test/org/apache/cassandra/db/ColumnComparatorFactoryTest.java b/test/org/apache/cassandra/db/ColumnComparatorFactoryTest.java new file mode 100644 index 0000000000..766526597c --- /dev/null +++ b/test/org/apache/cassandra/db/ColumnComparatorFactoryTest.java @@ -0,0 +1,25 @@ +package org.apache.cassandra.db; + +import org.testng.annotations.Test; + +import java.util.Comparator; + +public class ColumnComparatorFactoryTest { + public Comparator nameComparator; + + @Test + public void testLT() { + IColumn col1 = new Column("Column-8"); + IColumn col2 = new Column("Column-9"); + nameComparator = ColumnComparatorFactory.getComparator(ColumnComparatorFactory.ComparatorType.NAME); + assert nameComparator.compare(col1, col2) < 0; + } + + @Test + public void testGT() { + IColumn col1 = new Column("Column-9"); + IColumn col2 = new Column("Column-10"); + // tricky -- remember we're comparing _lexically_ + assert nameComparator.compare(col1, col2) > 0; + } +} diff --git a/test/org/apache/cassandra/db/ColumnFamilyStoreTest.java b/test/org/apache/cassandra/db/ColumnFamilyStoreTest.java new file mode 100644 index 0000000000..8abadbbcf8 --- /dev/null +++ b/test/org/apache/cassandra/db/ColumnFamilyStoreTest.java @@ -0,0 +1,114 @@ +package org.apache.cassandra.db; + +import org.apache.cassandra.ServerTest; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Random; + +public class ColumnFamilyStoreTest extends ServerTest { + @Test + public void testMain() throws IOException, ColumnFamilyNotDefinedException { + Table table = Table.open("Table1"); + Random random = new Random(); + byte[] bytes1 = new byte[1024]; + byte[] bytes2 = new byte[1024]; + random.nextBytes(bytes1); + random.nextBytes(bytes2); + + for (int i = 800; i < 1000; ++i) + { + String key = Integer.toString(i); + RowMutation rm; + for ( int j = 0; j < 8; ++j ) + { + byte[] bytes = j % 2 == 0 ? bytes1 : bytes2; + rm = new RowMutation("Table1", key); + rm.add("Standard1:" + "Column-" + j, bytes, j); + rm.apply(); + + for ( int k = 0; k < 8; ++k ) + { + bytes = (j + k) % 2 == 0 ? bytes1 : bytes2; + rm = new RowMutation("Table1", key); + rm.add("Super1:" + "SuperColumn-" + j + ":Column-" + k, bytes, k); + rm.apply(); + } + } + } + + for ( int i = 800; i < 1000; ++i ) + { + String key = Integer.toString(i); + // TODO actually test results + ColumnFamily cf = table.get(key, "Super1:SuperColumn-1"); + assert cf != null; + Collection superColumns = cf.getAllColumns(); + for ( IColumn superColumn : superColumns ) + { + Collection subColumns = superColumn.getSubColumns(); + for ( IColumn subColumn : subColumns ) + { + //System.out.println(subColumn); + } + } + } + } + + @Test + public void testRemove() throws IOException, ColumnFamilyNotDefinedException { + Table table = Table.open("Table1"); + ColumnFamilyStore store = table.getColumnFamilyStore("Standard1"); + RowMutation rm; + + // add data + rm = new RowMutation("Table1", "key1"); + rm.add("Standard1:Column1", "asdf".getBytes(), 0); + rm.apply(); + store.forceFlush(); + + // remove + rm = new RowMutation("Table1", "key1"); + ColumnFamily cf = new ColumnFamily("Standard1"); + cf.delete(1); + rm.add(cf.name(), cf); + rm.apply(); + + ColumnFamily retrieved = store.getColumnFamily("key1", "Standard1", new IdentityFilter()); + assert retrieved.getColumnCount() == 0; + } + + @Test + public void testRemoveSuperColumn() throws IOException, ColumnFamilyNotDefinedException { + Table table = Table.open("Table1"); + ColumnFamilyStore store = table.getColumnFamilyStore("Super1"); + RowMutation rm; + + // add data + rm = new RowMutation("Table1", "key1"); + rm.add("Super1:SC1:Column1", "asdf".getBytes(), 0); + rm.apply(); + store.forceFlush(); + + // remove + rm = new RowMutation("Table1", "key1"); + ColumnFamily cf = new ColumnFamily("Super1"); + SuperColumn sc = new SuperColumn("SC1"); + sc.markForDeleteAt(1); + cf.addColumn(sc); + rm.add(cf.name(), cf); + rm.apply(); + + List families = store.getColumnFamilies("key1", "Super1", new IdentityFilter()); + assert families.get(0).getAllColumns().first().getMarkedForDeleteAt() == 1; // delete marker, just added + assert !families.get(1).getAllColumns().first().isMarkedForDelete(); // flushed old version + ColumnFamily resolved = ColumnFamilyStore.resolve(families); + assert resolved.getAllColumns().first().getMarkedForDeleteAt() == 1; + Collection subColumns = resolved.getAllColumns().first().getSubColumns(); + assert subColumns.size() == 1; + assert subColumns.iterator().next().timestamp() == 0; + assert ColumnFamilyStore.removeDeleted(resolved).getColumnCount() == 0; + } +} diff --git a/test/org/apache/cassandra/db/ColumnFamilyTest.java b/test/org/apache/cassandra/db/ColumnFamilyTest.java new file mode 100644 index 0000000000..3256e6465b --- /dev/null +++ b/test/org/apache/cassandra/db/ColumnFamilyTest.java @@ -0,0 +1,67 @@ +package org.apache.cassandra.db; + +import org.apache.cassandra.io.DataInputBuffer; +import org.apache.cassandra.io.DataOutputBuffer; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Random; +import java.util.TreeMap; + +public class ColumnFamilyTest +{ + // TODO test SuperColumns + + @Test + public void testSingleColumn() throws IOException { + Random random = new Random(); + byte[] bytes = new byte[1024]; + random.nextBytes(bytes); + ColumnFamily cf; + + cf = new ColumnFamily("Standard1", "Standard"); + cf.addColumn("C", bytes, 1); + DataOutputBuffer bufOut = new DataOutputBuffer(); + ColumnFamily.serializer().serialize(cf, bufOut); + + DataInputBuffer bufIn = new DataInputBuffer(); + bufIn.reset(bufOut.getData(), bufOut.getLength()); + cf = ColumnFamily.serializer().deserialize(bufIn); + assert cf != null; + assert cf.name().equals("Standard1"); + assert cf.getAllColumns().size() == 1; + } + + @Test + public void testManyColumns() throws IOException { + ColumnFamily cf; + + TreeMap map = new TreeMap(); + for ( int i = 100; i < 1000; ++i ) + { + map.put(Integer.toString(i), ("Avinash Lakshman is a good man: " + i).getBytes()); + } + + // write + cf = new ColumnFamily("Standard1", "Standard"); + DataOutputBuffer bufOut = new DataOutputBuffer(); + for (String cName: map.navigableKeySet()) + { + cf.addColumn(cName, map.get(cName), 314); + } + ColumnFamily.serializer().serialize(cf, bufOut); + + // verify + DataInputBuffer bufIn = new DataInputBuffer(); + bufIn.reset(bufOut.getData(), bufOut.getLength()); + cf = ColumnFamily.serializer().deserialize(bufIn); + for (String cName: map.navigableKeySet()) + { + assert Arrays.equals(cf.getColumn(cName).value(), map.get(cName)); + + } + assert new HashSet(cf.getColumns().keySet()).equals(map.keySet()); + } +} diff --git a/test/org/apache/cassandra/db/CommitLogTest.java b/test/org/apache/cassandra/db/CommitLogTest.java new file mode 100644 index 0000000000..38da560cbf --- /dev/null +++ b/test/org/apache/cassandra/db/CommitLogTest.java @@ -0,0 +1,45 @@ +package org.apache.cassandra.db; + +import org.testng.annotations.Test; + +import java.util.Set; +import java.util.Map; +import java.util.Arrays; +import java.io.File; +import java.io.IOException; + +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.io.DataInputBuffer; +import org.apache.cassandra.ServerTest; + +public class CommitLogTest extends ServerTest { + @Test + public void testMain() throws IOException { + // TODO this is useless, since it assumes we have a working set of commit logs to parse + /* + File logDir = new File(DatabaseDescriptor.getLogFileLocation()); + File[] files = logDir.listFiles(); + Arrays.sort( files, new FileUtils.FileComparator() ); + + byte[] bytes = new byte[CommitLogHeader.size(Integer.parseInt(args[0]))]; + for ( File file : files ) + { + CommitLog clog = new CommitLog( file ); + clog.readCommitLogHeader(file.getAbsolutePath(), bytes); + DataInputBuffer bufIn = new DataInputBuffer(); + bufIn.reset(bytes, 0, bytes.length); + CommitLogHeader clHeader = CommitLogHeader.serializer().deserialize(bufIn); + + StringBuilder sb = new StringBuilder(""); + for ( byte b : bytes ) + { + sb.append(b); + sb.append(" "); + } + + System.out.println("FILE:" + file); + System.out.println(clHeader.toString()); + } + */ + } +} diff --git a/test/org/apache/cassandra/db/DBManagerTest.java b/test/org/apache/cassandra/db/DBManagerTest.java new file mode 100644 index 0000000000..dc3b96a184 --- /dev/null +++ b/test/org/apache/cassandra/db/DBManagerTest.java @@ -0,0 +1,12 @@ +package org.apache.cassandra.db; + +import org.testng.annotations.Test; +import org.apache.cassandra.ServerTest; + +public class DBManagerTest extends ServerTest { + @Test + public void testMain() throws Throwable { + // TODO clean up old detritus + DBManager.instance().start(); + } +} diff --git a/test/org/apache/cassandra/db/RecoveryManagerTest.java b/test/org/apache/cassandra/db/RecoveryManagerTest.java new file mode 100644 index 0000000000..b442bc0ed3 --- /dev/null +++ b/test/org/apache/cassandra/db/RecoveryManagerTest.java @@ -0,0 +1,16 @@ +package org.apache.cassandra.db; + +import org.testng.annotations.Test; + +import java.io.IOException; + +import org.apache.cassandra.ServerTest; + +public class RecoveryManagerTest extends ServerTest { + @Test + public void testDoRecovery() throws IOException { + // TODO nothing to recover + RecoveryManager rm = RecoveryManager.instance(); + rm.doRecovery(); + } +} diff --git a/test/org/apache/cassandra/db/SystemTableTest.java b/test/org/apache/cassandra/db/SystemTableTest.java new file mode 100644 index 0000000000..5adaabbcb0 --- /dev/null +++ b/test/org/apache/cassandra/db/SystemTableTest.java @@ -0,0 +1,14 @@ +package org.apache.cassandra.db; + +import org.apache.cassandra.ServerTest; +import org.apache.cassandra.service.StorageService; +import org.testng.annotations.Test; + +import java.io.IOException; + +public class SystemTableTest extends ServerTest { + @Test + public void testMain() throws IOException { + SystemTable.openSystemTable(SystemTable.cfName_).updateToken( StorageService.hash("503545744:0") ); + } +} diff --git a/test/org/apache/cassandra/db/TableTest.java b/test/org/apache/cassandra/db/TableTest.java new file mode 100644 index 0000000000..41f58f1383 --- /dev/null +++ b/test/org/apache/cassandra/db/TableTest.java @@ -0,0 +1,15 @@ +package org.apache.cassandra.db; + +import org.testng.annotations.Test; + +import java.io.IOException; + +import org.apache.cassandra.service.StorageService; + +public class TableTest { + @Test + public void testOpen() throws Throwable { + Table table = Table.open("Mailbox"); + Row row = table.get("35300190:1"); + } +} diff --git a/test/org/apache/cassandra/dht/RangeTest.java b/test/org/apache/cassandra/dht/RangeTest.java new file mode 100644 index 0000000000..38c47b0499 --- /dev/null +++ b/test/org/apache/cassandra/dht/RangeTest.java @@ -0,0 +1,20 @@ +package org.apache.cassandra.dht; + +import org.testng.annotations.Test; + +import java.math.BigInteger; + +public class RangeTest { + @Test + public void testRange() { + Range left = new Range(new BigInteger("0"), new BigInteger("100")); + assert left.contains(new BigInteger("10")); + assert !left.contains(new BigInteger("-1")); + assert !left.contains(new BigInteger("101")); + + Range right = new Range(new BigInteger("100"), new BigInteger("0")); + assert right.contains(new BigInteger("200")); + assert right.contains(new BigInteger("-10")); + assert !right.contains(new BigInteger("1")); + } +} diff --git a/test/org/apache/cassandra/io/DataInputBufferTest.java b/test/org/apache/cassandra/io/DataInputBufferTest.java new file mode 100644 index 0000000000..b6bb7a681c --- /dev/null +++ b/test/org/apache/cassandra/io/DataInputBufferTest.java @@ -0,0 +1,39 @@ +package org.apache.cassandra.io; + +import org.testng.annotations.Test; + +import java.util.Random; +import java.io.IOException; + +public class DataInputBufferTest { + @Test + public void testRandom() throws IOException { + Random random = new Random(); + byte[] bytes = new byte[1024*1024]; + random.nextBytes(bytes); + + DataInputBuffer.FastByteArrayInputStream bis = new DataInputBuffer.FastByteArrayInputStream(bytes); + int read = 0; + int n = 0; + while ( true ) + { + read = bis.read(); + if ( read == -1 ) + break; + assert read == ((int)bytes[n++]&0xFF); + } + assert n == bytes.length; + } + + @Test + public void testSmall() throws IOException { + DataOutputBuffer bufOut = new DataOutputBuffer(); + bufOut.writeUTF("Avinash"); + bufOut.writeInt(41*1024*1024); + DataInputBuffer bufIn = new DataInputBuffer(); + bufIn.reset(bufOut.getData(), bufOut.getLength()); + assert bufIn.readUTF().equals("Avinash"); + assert bufIn.readInt() == 41 * 1024 * 1024; + } + +} diff --git a/test/org/apache/cassandra/io/SSTableTest.java b/test/org/apache/cassandra/io/SSTableTest.java new file mode 100644 index 0000000000..7ee7600db2 --- /dev/null +++ b/test/org/apache/cassandra/io/SSTableTest.java @@ -0,0 +1,75 @@ +package org.apache.cassandra.io; + +import org.apache.cassandra.ServerTest; +import org.apache.cassandra.db.FileStruct; +import org.apache.cassandra.utils.BloomFilter; +import org.apache.commons.collections.CollectionUtils; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +public class SSTableTest extends ServerTest { + // @Test + public void testSingleWrite() throws IOException { + File f = File.createTempFile("sstable", ""); + SSTable ssTable; + + // write test data + ssTable = new SSTable(f.getParent(), f.getName()); + BloomFilter bf = new BloomFilter(1000, 8); + Random random = new Random(); + byte[] bytes = new byte[1024]; + random.nextBytes(bytes); + + String key = Integer.toString(1); + ssTable.append(key, bytes); + bf.fill(key); + ssTable.close(bf); + + // TODO append/next are not symmetrical ops anymore + + // verify + ssTable = new SSTable(f.getPath() + "-Data.db"); + DataInputBuffer bufIn = ssTable.next(key, "Test:C"); + byte[] bytes2 = new byte[1024]; + bufIn.readFully(bytes2); + assert Arrays.equals(bytes2, bytes); + } + + // @Test + public void testManyWrites() throws IOException { + File f = File.createTempFile("sstable", ""); + SSTable ssTable; + + TreeMap map = new TreeMap(); + for ( int i = 100; i < 1000; ++i ) + { + map.put(Integer.toString(i), ("Avinash Lakshman is a good man: " + i).getBytes()); + } + + // write + ssTable = new SSTable(f.getParent(), f.getName()); + BloomFilter bf = new BloomFilter(1000, 8); + for (String key: map.navigableKeySet()) + { + ssTable.append(key, map.get(key)); + } + ssTable.close(bf); + + // TODO append/next are not symmetrical ops anymore + + // verify + List keys = new ArrayList(map.keySet()); + Collections.shuffle(keys); + ssTable = new SSTable(f.getPath() + "-Data.db"); + for (String key: keys) + { + DataInputBuffer bufIn = ssTable.next(key, "Test:C"); + byte[] bytes2 = new byte[map.get(key).length]; + bufIn.readFully(bytes2); + assert Arrays.equals(bytes2, map.get(key)); + } + } +} diff --git a/test/org/apache/cassandra/service/CassandraServerTest.java b/test/org/apache/cassandra/service/CassandraServerTest.java new file mode 100644 index 0000000000..07c7dfe5ac --- /dev/null +++ b/test/org/apache/cassandra/service/CassandraServerTest.java @@ -0,0 +1,46 @@ +package org.apache.cassandra.service; + +import org.apache.cassandra.ServerTest; +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.IteratorUtils; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.*; + +public class CassandraServerTest extends ServerTest { + /* + @Test + public void test_get_column() throws Throwable { + CassandraServer server = new CassandraServer(); + server.start(); + + try { + column_t c1 = new column_t("c1", "0", 0L); + column_t c2 = new column_t("c2", "0", 0L); + List columns = new ArrayList(); + columns.add(c1); + columns.add(c2); + Map> cfmap = new HashMap>(); + cfmap.put("Standard1", columns); + cfmap.put("Standard2", columns); + + batch_mutation_t m = new batch_mutation_t("Table1", "key1", cfmap); + server.batch_insert(m, 1); + + column_t column; + column = server.get_column("Table1", "key1", "Standard1:c2"); + assert column.value.equals("0"); + + column = server.get_column("Table1", "key1", "Standard2:c2"); + assert column.value.equals("0"); + + ArrayList column_ts = server.get_slice_strong("Table1", "key1", "Standard1", -1, -1); + assert column_ts.size() == 2; + } finally { + server.shutdown(); + } + } + */ +} diff --git a/test/org/apache/cassandra/utils/KeyGenerator.java b/test/org/apache/cassandra/utils/KeyGenerator.java new file mode 100644 index 0000000000..99ddef0db1 --- /dev/null +++ b/test/org/apache/cassandra/utils/KeyGenerator.java @@ -0,0 +1,148 @@ +package org.apache.cassandra.utils; + +import java.io.*; +import java.util.Random; + +public class KeyGenerator { + private static String randomKey(Random r) { + StringBuffer buffer = new StringBuffer(); + for (int j = 0; j < 16; j++) { + buffer.append((char)r.nextInt()); + } + return buffer.toString(); + } + + static class RandomStringGenerator implements ResetableIterator { + int i, n, seed; + Random random; + + RandomStringGenerator(int seed, int n) { + i = 0; + this.seed = seed; + this.n = n; + reset(); + } + + public int size() { + return n; + } + + public void reset() { + random = new Random(seed); + } + + public boolean hasNext() { + return i < n; + } + + public String next() { + i++; + return randomKey(random); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + static class IntGenerator implements ResetableIterator { + private int i, start, n; + + IntGenerator(int n) { + this(0, n); + } + + IntGenerator(int start, int n) { + this.start = start; + this.n = n; + reset(); + } + + public int size() { + return n - start; + } + + public void reset() { + i = start; + } + + public boolean hasNext() { + return i < n; + } + + public String next() { + return Integer.toString(i++); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + static class WordGenerator implements ResetableIterator { + static int WORDS; + + static { + try { + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("/usr/share/dict/words"))); + while (br.ready()) { + br.readLine(); + WORDS++; + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + BufferedReader reader; + private int modulo; + private int skip; + String next; + + WordGenerator(int skip, int modulo) { + this.skip = skip; + this.modulo = modulo; + reset(); + } + + public int size() { + return (1 + WORDS - skip) / modulo; + } + + public void reset() { + try { + reader = new BufferedReader(new InputStreamReader(new FileInputStream("/usr/share/dict/words"))); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + for (int i = 0; i < skip; i++) { + try { + reader.readLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + next(); + } + + public boolean hasNext() { + return next != null; + } + + public String next() { + try { + String s = next; + for (int i = 0; i < modulo; i++) { + next = reader.readLine(); + } + return s; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/test/org/apache/cassandra/utils/ResetableIterator.java b/test/org/apache/cassandra/utils/ResetableIterator.java new file mode 100644 index 0000000000..a2f1caf52f --- /dev/null +++ b/test/org/apache/cassandra/utils/ResetableIterator.java @@ -0,0 +1,9 @@ +package org.apache.cassandra.utils; + +import java.util.Iterator; + +public interface ResetableIterator extends Iterator { + public void reset(); + + int size(); +} diff --git a/test/testng.xml b/test/testng.xml new file mode 100644 index 0000000000..d91aeb4eee --- /dev/null +++ b/test/testng.xml @@ -0,0 +1 @@ +