From: Enrique Saurez Date: Tue, 22 Jan 2019 18:20:22 +0000 (-0500) Subject: Fix node configuration/executable, and minor bugs X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F35%2F76235%2F3;p=music%2Fmdbc.git Fix node configuration/executable, and minor bugs Change-Id: Ia442afe3146a532b01f8e7ef0f26c2dcbfdf4334 Issue-ID: MUSIC-281 Signed-off-by: Enrique Saurez --- diff --git a/README.md b/README.md index 0384930..cc1d6b6 100755 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ o replicationFactor: indicates the needs of replication for this partition (the mdbc-server/src/main/java/org/onap/music/mdbc/tools/CreateNodeConfiguration.java To run it, use the following parameters: - +`` -t mdbc-server/src/main/java/org/onap/music/mdbc/configurations/tableConfiguration.json -b base -o /Users/quique/Desktop/ This program is going to generate all the required configuration json for each ETDB node in the system and additionally initialize all the corresponding rows and tables for the system to correctly work. The meaning of the parameters is: diff --git a/mdbc-benchmark/pom.xml b/mdbc-benchmark/pom.xml new file mode 100644 index 0000000..722c59d --- /dev/null +++ b/mdbc-benchmark/pom.xml @@ -0,0 +1,128 @@ + + + + + mdbc + org.onap.music.mdbc + 0.0.1-SNAPSHOT + + 4.0.0 + + mdbc-benchmark + 0.0.1-SNAPSHOT + mdbc-benchmark + MDBC Benchmark + jar + + + + org.json + json + 20160810 + + + mysql + mysql-connector-java + 5.1.32 + + + + org.apache.commons + commons-lang3 + 3.7 + + + junit + junit + 4.12 + test + + + com.vmlens + concurrent-junit + 1.0.0 + test + + + com.att.eelf + eelf-core + 1.0.0 + + + org.apache.calcite.avatica + avatica-server + 1.12.0 + + + com.google.code.gson + gson + 2.8.5 + + + org.mariadb.jdbc + mariadb-java-client + 1.1.7 + + + org.apache.commons + commons-math3 + 3.0 + + + + + + + maven-assembly-plugin + 3.1.0 + + + jar-with-dependencies + + + + + node-configuration + package + + single + + + + + org.onap.music.mdbc.Benchmark + + + + jar-with-dependencies + + mdbc-benchmark + false + + + + + + + + \ No newline at end of file diff --git a/mdbc-benchmark/src/main/java/org/onap/music/mdbc/Benchmark.java b/mdbc-benchmark/src/main/java/org/onap/music/mdbc/Benchmark.java new file mode 100644 index 0000000..7baeaa2 --- /dev/null +++ b/mdbc-benchmark/src/main/java/org/onap/music/mdbc/Benchmark.java @@ -0,0 +1,366 @@ +/* + * ============LICENSE_START==================================================== + * org.onap.music.mdbc + * ============================================================================= + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END====================================================== + */ + +package org.onap.music.mdbc; + +import java.sql.*; +import java.util.*; +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import org.apache.commons.math3.stat.descriptive.rank.Percentile; + +public class Benchmark +{ + + @Parameter(names = { "-m", "--ismariadb" }, + description = "Is MARIADB evaluation") + private boolean isMariaDb = false; + + + @Parameter(names = { "-h", "-help", "--help" }, help = true, + description = "Print the help message") + private boolean help = false; + + public static class MyState { + private Connection createConnection(){ + try { + Class.forName(this.driver); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + System.exit(1); + } + Connection connection=null; + try { + if(!isMariaDb) { + connection = DriverManager.getConnection(connectionUrl); + } + else{ + Properties connectionProps = new Properties(); + connectionProps.put("user", user); + connectionProps.put("password", password); + connection = DriverManager.getConnection(connectionUrl,connectionProps); + } + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + try { + connection.setAutoCommit(false); + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + return connection; + } + + private void createTable(Connection connection){ + final String sql = "CREATE TABLE IF NOT EXISTS PERSONS (\n" + + " PersonID int,\n" + + " Counter int,\n" + + " LastName varchar(255),\n" + + " FirstName varchar(255),\n" + + " Address varchar(255),\n" + + " City varchar(255)\n" + + ");"; + + Statement stmt = null; + try { + stmt = connection.createStatement(); + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + + Boolean execute=null; + try { + execute = stmt.execute(sql); + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + + try { + connection.commit(); + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + + try { + stmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + } + + private boolean cleanTable(){ + String cleanCmd = "DELETE FROM PERSONS;"; + Statement stmt = null; + try { + stmt = testConnection.createStatement(); + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + + Boolean execute=null; + try { + execute = stmt.execute(cleanCmd); + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + try { + testConnection.commit(); + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + try { + stmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + System.exit(1); + } + return execute; + } + + private void addRowsToTable(int totalNumberOfRows){ + for(int i=0; i> results){ + System.out.println("ROWS,P1,P5,P10,P25,P50,P75,P90,P95,P99,AVG,DEVIATION"); + for(Map.Entry> result : results.entrySet()) { + Percentile resultsPercentiles = new Percentile(); + double[] tmpList= new double[result.getValue().size()]; + int counter = 0; + for(Long val : result.getValue()) { + tmpList[counter++]= Double.valueOf(val); + } + resultsPercentiles.setData(tmpList); + final double average = result.getValue() + .stream() + .mapToDouble((x) -> x.doubleValue()) + .summaryStatistics() + .getAverage(); + + final double rawSum = result.getValue() + .stream() + .mapToDouble((x) -> Math.pow(x.doubleValue() - average, + 2.0)) + .sum(); + + final double deviation = Math.sqrt(rawSum / (result.getValue().size() - 1)); + System.out.printf("%d,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n", + result.getKey(), + resultsPercentiles.evaluate(1.0), + resultsPercentiles.evaluate(5.0), + resultsPercentiles.evaluate(10.0), + resultsPercentiles.evaluate(25.0), + resultsPercentiles.evaluate(50.0), + resultsPercentiles.evaluate(75.0), + resultsPercentiles.evaluate(90.0), + resultsPercentiles.evaluate(95.0), + resultsPercentiles.evaluate(99.0), + average, + deviation + ); + } + } + + public static void main( String[] args ) + { + final Benchmark testApp = new Benchmark(); + @SuppressWarnings("deprecation") + JCommander jc = new JCommander(testApp, args); + if (testApp.help) { + jc.usage(); + System.exit(1); + return; + } + MyState state = new MyState(); + if(testApp.isMariaDb){ + state.isMariaDb = true; + state.driver = "org.mariadb.jdbc.Driver"; + state.connectionUrl = "jdbc:mariadb://192.168.1.30:3306/test"; + + } + else{ + state.isMariaDb = false; + state.driver = "org.apache.calcite.avatica.remote.Driver"; + state.connectionUrl = "jdbc:avatica:remote:url=http://localhost:30000;serialization=protobuf"; + + } + //iterations + Map> results = new HashMap<>(); + final int totalIterations = 20; + final int[] rows = { 1,10,100, 500, 1000}; + for(int row: rows) { + System.out.println("Running for rows: "+Integer.toString(row)); + results.put(row,new ArrayList()); + for (int i = 0; i < totalIterations; i++) { + System.out.println("Running iteration: "+Integer.toString(i)); + state.doSetup(); + state.doWarmup(row); + long startTime = System.nanoTime(); + testMethod(state); + long endTime = System.nanoTime(); + results.get(row).add(endTime - startTime); + state.doTearDown(); + } + } + printResults(results); + } +} diff --git a/mdbc-server/pom.xml b/mdbc-server/pom.xml index 8edb5ab..4ebbc6a 100755 --- a/mdbc-server/pom.xml +++ b/mdbc-server/pom.xml @@ -208,6 +208,44 @@ single + + node-configuration + package + + single + + + + + org.onap.music.mdbc.tools.CreateNodeConfigurations + + + + jar-with-dependencies + + create-node-configuration + false + + + + mdbc-server + package + + single + + + + + org.onap.music.mdbc.MdbcServer + + + + jar-with-dependencies + + mdbc-server + false + + diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/MdbcConnection.java b/mdbc-server/src/main/java/org/onap/music/mdbc/MdbcConnection.java index 6c1163a..69a678b 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/MdbcConnection.java +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/MdbcConnection.java @@ -492,11 +492,20 @@ public class MdbcConnection implements Connection { Map> tableToInstruction = QueryProcessor.extractTableFromQuery(sql); //Check ownership of keys List queryTables = MDBCUtils.getTables(tableToInstruction); + if(this.partition!=null ){ + List snapshot = this.partition.getSnapshot(); + if(snapshot!=null){ + queryTables.addAll(snapshot); + } + } // filter out ranges that fall under Eventually consistent // category as these tables do not need ownership List scQueryTables = filterEveTables( queryTables); - this.partition = own(scQueryTables); - dbi.preStatementHook(sql); + DatabasePartition tempPartition = own(scQueryTables); + if(tempPartition!=null && tempPartition != partition) { + this.partition.updateDatabasePartition(tempPartition); + } + dbi.preStatementHook(sql); } @@ -552,19 +561,27 @@ public class MdbcConnection implements Connection { } private DatabasePartition own(List ranges) throws MDBCServiceException { + if(ranges==null||ranges.isEmpty()){ + return null; + } DatabasePartition newPartition = null; OwnershipAndCheckpoint ownAndCheck = mi.getOwnAndCheck(); UUID ownOpId = MDBCUtils.generateTimebasedUniqueKey(); try { final OwnershipReturn ownershipReturn = mi.own(ranges, partition, ownOpId); + if(ownershipReturn==null){ + return null; + } Dag dag = ownershipReturn.getDag(); - DagNode node = dag.getNode(ownershipReturn.getRangeId()); - MusicRangeInformationRow row = node.getRow(); - Map lock = new HashMap<>(); - lock.put(row, new LockResult(row.getPartitionIndex(), ownershipReturn.getOwnerId(), true, ranges)); - ownAndCheck.checkpoint(this.mi, this.dbi, dag, ranges, lock, ownershipReturn.getOwnershipId()); - newPartition = new DatabasePartition(ownershipReturn.getRanges(), ownershipReturn.getRangeId(), - ownershipReturn.getOwnerId()); + if(dag!=null) { + DagNode node = dag.getNode(ownershipReturn.getRangeId()); + MusicRangeInformationRow row = node.getRow(); + Map lock = new HashMap<>(); + lock.put(row, new LockResult(row.getPartitionIndex(), ownershipReturn.getOwnerId(), true, ranges)); + ownAndCheck.checkpoint(this.mi, this.dbi, dag, ranges, lock, ownershipReturn.getOwnershipId()); + newPartition = new DatabasePartition(ownershipReturn.getRanges(), ownershipReturn.getRangeId(), + ownershipReturn.getOwnerId()); + } } finally{ ownAndCheck.stopOwnershipTimeoutClock(ownOpId); diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/Range.java b/mdbc-server/src/main/java/org/onap/music/mdbc/Range.java index efc89cd..bc1dad7 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/Range.java +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/Range.java @@ -39,7 +39,7 @@ public class Range implements Serializable, Cloneable{ this.table = table.toUpperCase(); } - public String toString(){return table;} + public String toString(){return table.toUpperCase();} /** * Compares to Range types diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/StateManager.java b/mdbc-server/src/main/java/org/onap/music/mdbc/StateManager.java index 4c5a3ed..1f722f1 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/StateManager.java +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/StateManager.java @@ -164,8 +164,9 @@ public class StateManager { transactionInfo.deleteTxProgress(connectionId); try { Connection conn = mdbcConnections.get(connectionId); - if(conn!=null) + if(conn!=null) { conn.close(); + } } catch (SQLException e) { logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); @@ -173,7 +174,8 @@ public class StateManager { mdbcConnections.remove(connectionId); } if(connectionRanges.containsKey(connectionId)){ - //TODO release lock? + //We relinquish all locks obtained by a given + relinquish(connectionRanges.get(connectionId)); connectionRanges.remove(connectionId); } } @@ -256,4 +258,13 @@ public class StateManager { //\TODO Prefetch data to system using the data ranges as guide throw new UnsupportedOperationException("Function initialize system needs to be implemented id MdbcStateManager"); } + + private void relinquish(DatabasePartition partition){ + try { + musicInterface.relinquish(partition.getLockId(),partition.getMRIIndex().toString()); + } catch (MDBCServiceException e) { + logger.error("Relinquish failed, would need to forcefully obtain lock later"); + } + + } } diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/NodeConfiguration.java b/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/NodeConfiguration.java index 96dc65f..5349219 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/NodeConfiguration.java +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/NodeConfiguration.java @@ -41,10 +41,10 @@ public class NodeConfiguration { public String nodeName; public String sqlDatabaseName; - public NodeConfiguration(String tables, UUID mriIndex, String sqlDatabaseName, String node){ + public NodeConfiguration(String tables, String eventualTables, UUID mriIndex, String sqlDatabaseName, String node){ // public DatabasePartition(List knownRanges, UUID mriIndex, String mriTable, String lockId, String musicTxDigestTable) { partition = new DatabasePartition(toRanges(tables), mriIndex, null) ; - eventual = new Eventual(toRanges(tables)); + eventual = new Eventual(toRanges(eventualTables)); this.nodeName = node; this.sqlDatabaseName = sqlDatabaseName; } diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/TablesConfiguration.java b/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/TablesConfiguration.java index 5beb6b7..8497911 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/TablesConfiguration.java +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/TablesConfiguration.java @@ -19,6 +19,8 @@ */ package org.onap.music.mdbc.configurations; +import com.datastax.driver.core.ResultSet; +import java.util.stream.Collectors; import org.onap.music.exceptions.MDBCServiceException; import org.onap.music.logging.EELFLoggerDelegate; import org.onap.music.mdbc.MDBCUtils; @@ -63,6 +65,7 @@ public class TablesConfiguration { * @apiNote This function assumes that when used, there is not associated redo history in the tables to the tables that are going to be managed by this configuration file */ public List initializeAndCreateNodeConfigurations() throws MDBCServiceException { + logger.info("initializing the required spaces"); initInternalNamespace(); List nodeConfigs = new ArrayList<>(); @@ -72,7 +75,9 @@ public class TablesConfiguration { } for(PartitionInformation partitionInfo : partitions){ String mriTableName = partitionInfo.mriTableName; + checkIfMriIsEmpty(mriTableName); //0) Create the corresponding Music Range Information table + MusicMixin.createMusicRangeInformationTable(musicNamespace,mriTableName); String partitionId; if(partitionInfo.partitionId==null || partitionInfo.partitionId.isEmpty()){ @@ -81,34 +86,58 @@ public class TablesConfiguration { throw new MDBCServiceException("Replication factor and partition id are both empty, and this is an invalid configuration"); } //1) Create a row in the partition info table - //partitionId = DatabaseOperations.createPartitionInfoRow(musicNamespace,pitName,partitionInfo.replicationFactor,partitionInfo.tables,null); - + partitionId = MDBCUtils.generateTimebasedUniqueKey().toString(); } else{ partitionId = partitionInfo.partitionId; } //2) Create a row in the transaction information table - UUID mriTableIndex = MDBCUtils.generateTimebasedUniqueKey(); - //3) Add owner and tit information to partition info table - RedoRow newRedoRow = new RedoRow(mriTableName,mriTableIndex); - //DatabaseOperations.updateRedoRow(musicNamespace,pitName,partitionId,newRedoRow,partitionInfo.owner,null); - //4) Update ttp with the new partition - //for(String table: partitionInfo.tables) { - //DatabaseOperations.updateTableToPartition(musicNamespace, ttpName, table, partitionId, null); - //} - //5) Add it to the redo history table - //DatabaseOperations.createRedoHistoryBeginRow(musicNamespace,rhName,newRedoRow,partitionId,null); - //6) Create config for this node + + logger.info("Creating empty row with id "+partitionId); + MusicMixin.createEmptyMriRow(musicNamespace,partitionInfo.mriTableName,UUID.fromString(partitionId), + partitionInfo.owner,null,partitionInfo.getTables(),true); + + //3) Create config for this node StringBuilder newStr = new StringBuilder(); for(Range r: partitionInfo.tables){ - newStr.append(r.toString()).append(","); + newStr.append(r.toString().toUpperCase()).append(","); } - nodeConfigs.add(new NodeConfiguration(newStr.toString(),mriTableIndex, + + logger.info("Appending row to configuration "+partitionId); + nodeConfigs.add(new NodeConfiguration(newStr.toString(),"",UUID.fromString(partitionId), sqlDatabaseName, partitionInfo.owner)); } return nodeConfigs; } + private void checkIfMriIsEmpty(String mriTableName) throws MDBCServiceException { + //First check if table exists + StringBuilder checkTableExistsString = new StringBuilder("SELECT table_name FROM system_schema.tables WHERE keyspace_name='") + .append(musicNamespace) + .append("';"); + PreparedQueryObject checkTableExists = new PreparedQueryObject(); + checkTableExists.appendQueryString(checkTableExistsString.toString()); + final ResultSet resultSet = MusicCore.quorumGet(checkTableExists); + if(resultSet.isExhausted()){ + //Table doesn't exist + return; + } + //If exists, check if empty + StringBuilder checkRowsInTableString = new StringBuilder("SELECT * FROM ") + .append(musicNamespace) + .append(".") + .append(mriTableName) + .append("';"); + PreparedQueryObject checkRowsInTable = new PreparedQueryObject(); + checkRowsInTable.appendQueryString(checkRowsInTableString.toString()); + final ResultSet resultSet2 = MusicCore.quorumGet(checkTableExists); + if(!resultSet2.isExhausted()) { + throw new MDBCServiceException("When initializing the configuration of the system, the MRI should not exits " + + "be empty"); + } + } + + private void initInternalNamespace() throws MDBCServiceException { StringBuilder createKeysTableCql = new StringBuilder("CREATE TABLE IF NOT EXISTS ") .append(internalNamespace) diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/tableConfiguration.json b/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/tableConfiguration.json index 383593a..2e4e0ee 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/tableConfiguration.json +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/configurations/tableConfiguration.json @@ -3,7 +3,7 @@ { "tables": [ { - "table": "table11" + "table": "PERSONS" } ], "owner": "", diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/mixins/MusicMixin.java b/mdbc-server/src/main/java/org/onap/music/mdbc/mixins/MusicMixin.java index 6eacb4f..e8028c1 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/mixins/MusicMixin.java +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/mixins/MusicMixin.java @@ -123,7 +123,7 @@ public class MusicMixin implements MusicInterface { private String musicRangeInformationTableName = "musicrangeinformation"; private String musicRangeDependencyTableName = "musicrangedependency"; - private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicMixin.class); + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicMixin.class); @@ -335,7 +335,7 @@ public class MusicMixin implements MusicInterface { try { createMusicTxDigest();//\TODO If we start partitioning the data base, we would need to use the redotable number createMusicEventualTxDigest(); - createMusicRangeInformationTable(); + createMusicRangeInformationTable(this.music_ns,this.musicRangeInformationTableName); createMusicRangeDependencyTable(); } catch(MDBCServiceException e){ @@ -1311,21 +1311,25 @@ public class MusicMixin implements MusicInterface { } } - /** * Writes the transaction information to metric's txDigest and musicRangeInformation table * This officially commits the transaction globally */ @Override - public void commitLog(DatabasePartition partition, List eventualRanges, HashMap transactionDigest, String txId ,TxCommitProgress progressKeeper) throws MDBCServiceException{ - + public void commitLog(DatabasePartition partition,List eventualRanges, HashMap transactionDigest, + String txId ,TxCommitProgress progressKeeper) throws MDBCServiceException{ + if(partition==null){ + logger.warn("Trying tcommit log with null partition"); + return; + } + List snapshot = partition.getSnapshot(); + if(snapshot==null || snapshot.isEmpty()){ + logger.warn("Trying to commit log with empty ranges"); + return; + } // first deal with commit for eventually consistent tables filterAndAddEventualTxDigest(eventualRanges, transactionDigest, txId, progressKeeper); - - // if strong consistency tables are not present in the transaction then return - if(partition == null || partition.getMRIIndex() == null) - return; - + UUID mriIndex = partition.getMRIIndex(); String fullyQualifiedMriKey = music_ns+"."+ this.musicRangeInformationTableName+"."+mriIndex; //0. See if reference to lock was already created @@ -1351,19 +1355,21 @@ public class MusicMixin implements MusicInterface { } String serializedTransactionDigest; - try { - serializedTransactionDigest = MDBCUtils.toString(transactionDigest); - } catch (IOException e) { - throw new MDBCServiceException("Failed to serialized transaction digest with error "+e.toString(), e); - } - MusicTxDigestId digestId = new MusicTxDigestId(commitId,-1); - addTxDigest(digestId, serializedTransactionDigest); - //2. Save RRT index to RQ - if(progressKeeper!= null) { - progressKeeper.setRecordId(txId,digestId); + if(!transactionDigest.isEmpty()) { + try { + serializedTransactionDigest = MDBCUtils.toString(transactionDigest); + } catch (IOException e) { + throw new MDBCServiceException("Failed to serialized transaction digest with error " + e.toString(), e); + } + MusicTxDigestId digestId = new MusicTxDigestId(commitId, -1); + addTxDigest(digestId, serializedTransactionDigest); + //2. Save RRT index to RQ + if (progressKeeper != null) { + progressKeeper.setRecordId(txId, digestId); + } + //3. Append RRT index into the corresponding TIT row array + appendToRedoLog(partition, digestId); } - //3. Append RRT index into the corresponding TIT row array - appendToRedoLog(partition,digestId); } private void filterAndAddEventualTxDigest(List eventualRanges, @@ -1572,8 +1578,7 @@ public class MusicMixin implements MusicInterface { * * Redo: list of uiids associated to the Redo Records Table * */ - private void createMusicRangeInformationTable() throws MDBCServiceException { - String tableName = this.musicRangeInformationTableName; + public static void createMusicRangeInformationTable(String namespace, String tableName) throws MDBCServiceException { String priKey = "rangeid"; StringBuilder fields = new StringBuilder(); fields.append("rangeid uuid, "); @@ -1584,9 +1589,9 @@ public class MusicMixin implements MusicInterface { //TODO: Frozen is only needed for old versions of cassandra, please update correspondingly fields.append("txredolog list>> "); String cql = String.format("CREATE TABLE IF NOT EXISTS %s.%s (%s, PRIMARY KEY (%s));", - this.music_ns, tableName, fields, priKey); + namespace, tableName, fields, priKey); try { - executeMusicWriteQuery(this.music_ns,tableName,cql); + executeMusicWriteQuery(namespace,tableName,cql); } catch (MDBCServiceException e) { logger.error("Initialization error: Failure to create transaction information table"); throw(e); @@ -1603,8 +1608,9 @@ public class MusicMixin implements MusicInterface { if(lockId == null || lockId.isEmpty()){ throw new MDBCServiceException("Error initializing music range information, error creating a lock for a new row") ; } - createEmptyMriRow(newPartition.getMRIIndex(),info.getMetricProcessId(),lockId, - newPartition.getSnapshot(),info.getIsLatest()); + logger.info("Creating MRI " + newPartition.getMRIIndex() + " for ranges " + newPartition.getSnapshot()); + createEmptyMriRow(this.music_ns,this.musicRangeInformationTableName,newPartition.getMRIIndex(),info.getMetricProcessId(), + lockId, newPartition.getSnapshot(),info.getIsLatest()); info.setOwnerId(lockId); return newPartition; } @@ -1673,8 +1679,8 @@ public class MusicMixin implements MusicInterface { private UUID createEmptyMriRow(String processId, String lockId, List ranges) throws MDBCServiceException { UUID id = MDBCUtils.generateTimebasedUniqueKey(); - return createEmptyMriRow(id,processId,lockId,ranges,true); - + logger.info("Creating MRI "+ id + " for ranges " + ranges); + return createEmptyMriRow(this.music_ns,this.musicRangeInformationTableName,id,processId,lockId,ranges,true); } /** @@ -1682,13 +1688,13 @@ public class MusicMixin implements MusicInterface { * @param processId id of the process that is going to own initially this. * @return uuid associated to the new row */ - private UUID createEmptyMriRow(UUID id, String processId, String lockId, List ranges, boolean isLatest) + public static UUID createEmptyMriRow(String musicNamespace, String mriTableName, UUID id, String processId, + String lockId, List ranges, boolean isLatest) throws MDBCServiceException{ - logger.info("Creating MRI " + id + " for ranges " + ranges); StringBuilder insert = new StringBuilder("INSERT INTO ") - .append(this.music_ns) + .append(musicNamespace) .append('.') - .append(this.musicRangeInformationTableName) + .append(mriTableName) .append(" (rangeid,keys,ownerid,islatest,metricprocessid,txredolog) VALUES ") .append("(") .append(id) @@ -1711,9 +1717,8 @@ public class MusicMixin implements MusicInterface { PreparedQueryObject query = new PreparedQueryObject(); query.appendQueryString(insert.toString()); try { - executeMusicLockedPut(this.music_ns,this.musicRangeInformationTableName,id.toString(),query,lockId,null); + executeMusicLockedPut(musicNamespace,mriTableName,id.toString(),query,lockId,null); } catch (MDBCServiceException e) { - logger.error("Initialization error: Failure to add new row to transaction information"); throw new MDBCServiceException("Initialization error:Failure to add new row to transaction information", e); } return id; @@ -1722,8 +1727,10 @@ public class MusicMixin implements MusicInterface { @Override public void appendToRedoLog(DatabasePartition partition, MusicTxDigestId newRecord) throws MDBCServiceException { logger.info("Appending to redo log for partition " + partition.getMRIIndex() + " txId=" + newRecord.txId); - PreparedQueryObject appendQuery = createAppendMtxdIndexToMriQuery(musicRangeInformationTableName, partition.getMRIIndex(), musicTxDigestTableName, newRecord.txId); - ReturnType returnType = MusicCore.criticalPut(music_ns, musicRangeInformationTableName, partition.getMRIIndex().toString(), appendQuery, partition.getLockId(), null); + PreparedQueryObject appendQuery = createAppendMtxdIndexToMriQuery(musicRangeInformationTableName, partition.getMRIIndex(), + musicTxDigestTableName, newRecord.txId); + ReturnType returnType = MusicCore.criticalPut(music_ns, musicRangeInformationTableName, partition.getMRIIndex().toString(), + appendQuery, partition.getLockId(), null); if(returnType.getResult().compareTo(ResultType.SUCCESS) != 0 ){ logger.error(EELFLoggerDelegate.errorLogger, "Error when executing append operation with return type: "+returnType.getMessage()); throw new MDBCServiceException("Error when executing append operation with return type: "+returnType.getMessage()); @@ -1906,11 +1913,9 @@ public class MusicMixin implements MusicInterface { String cql = String.format("SELECT * FROM %s.%s ;", music_ns, this.musicEventualTxDigestTableName); // Ex 1 & 2 might return millions of records!! things to consider outOfMemory issue, performance issue etc.. How to overcome?? // Ex 3: will return less records compare to Ex:1 and Ex:2. - PreparedQueryObject pQueryObject = new PreparedQueryObject(); - pQueryObject.appendQueryString(cql); // I need to get a ResultSet of all the records and give each row to the below HashMap. - ResultSet rs = executeMusicRead(pQueryObject.toString()); + ResultSet rs = executeMusicRead(cql); while (!rs.isExhausted()) { Row row = rs.one(); String digest = row.getString("transactiondigest"); @@ -2034,7 +2039,7 @@ public class MusicMixin implements MusicInterface { private List lockRow(LockRequest request, DatabasePartition partition,Map rowLock) throws MDBCServiceException { - if(partition.getMRIIndex()==request.id && partition.isLocked()){ + if(partition.getMRIIndex().equals(request.id) && partition.isLocked()){ return new ArrayList<>(); } //\TODO: this function needs to be improved, to track possible changes in the owner of a set of ranges @@ -2045,8 +2050,8 @@ public class MusicMixin implements MusicInterface { } private void unlockKeyInMusic(String table, String key, String lockref) { - String fullyQualifiedKey= music_ns+"."+ table+"."+lockref; - MusicCore.destroyLockRef(fullyQualifiedKey,lockref); + String fullyQualifiedKey= music_ns+"."+ table+"."+lockref; + MusicCore.destroyLockRef(fullyQualifiedKey,lockref); } private void releaseLocks(Map newLocks) throws MDBCServiceException{ @@ -2201,10 +2206,13 @@ public class MusicMixin implements MusicInterface { if(ranges == null || ranges.isEmpty()) return null; - + Map newLocks = new HashMap<>(); //Init timeout clock ownAndCheck.startOwnershipTimeoutClock(opId); + if(partition.isLocked()&&partition.getSnapshot().containsAll(ranges)) { + return new OwnershipReturn(opId,partition.getLockId(),partition.getMRIIndex(),partition.getSnapshot(),null); + } //Find List extendedRanges = getExtendedRanges(ranges); List allMriRows = getAllMriRows(); @@ -2218,7 +2226,7 @@ public class MusicMixin implements MusicInterface { DagNode node = dag.nextToOwn(); MusicRangeInformationRow row = node.getRow(); UUID uuid = row.getPartitionIndex(); - if(partition.isLocked()&&partition.getMRIIndex()==uuid|| + if(partition.isLocked()&&partition.getMRIIndex().equals(uuid)|| newLocks.containsKey(uuid) || !row.getIsLatest()){ dag.setOwn(node); @@ -2301,7 +2309,9 @@ public class MusicMixin implements MusicInterface { } final LockResult lockResult = lock.get(newUUID); partition.updateDatabasePartition(newPartition); - createEmptyMriRow(partition.getMRIIndex(),myId,lockResult.getOwnerId(),partition.getSnapshot(),true); + logger.info("Creating MRI " +partition.getMRIIndex()+ " for ranges " + partition.getSnapshot()); + createEmptyMriRow(this.music_ns,this.musicRangeInformationTableName,partition.getMRIIndex(),myId, + lockResult.getOwnerId(),partition.getSnapshot(),true); return oldIds; } @@ -2352,6 +2362,9 @@ public class MusicMixin implements MusicInterface { @Override public void relinquish(String ownerId, String rangeId) throws MDBCServiceException{ + if(ownerId==null||ownerId.isEmpty()||rangeId==null||rangeId.isEmpty()){ + return; + } String fullyQualifiedMriKey = music_ns+"."+ musicRangeInformationTableName+"."+rangeId; try { MusicCore.voluntaryReleaseLock(fullyQualifiedMriKey,ownerId); @@ -2442,13 +2455,13 @@ public class MusicMixin implements MusicInterface { private static Row executeMusicUnlockedQuorumGet(PreparedQueryObject cqlObject) throws MDBCServiceException{ ResultSet result = MusicCore.quorumGet(cqlObject); - if(result.isExhausted()){ + if(result == null || result.isExhausted()){ throw new MDBCServiceException("There is not a row that matches the query: ["+cqlObject.getQuery()+"]"); } return result.one(); } - private void executeMusicLockedPut(String namespace, String tableName, + private static void executeMusicLockedPut(String namespace, String tableName, String primaryKeyWithoutDomain, PreparedQueryObject queryObject, String lockId, Condition conditionInfo) throws MDBCServiceException { ReturnType rt ; @@ -2490,7 +2503,9 @@ public class MusicMixin implements MusicInterface { @Override public void replayTransaction(HashMap digest) throws MDBCServiceException{ + //\TODO: implement logic to move data from digests to Music Data Tables //throw new NotImplementedException("Error, replay transaction in music mixin needs to be implemented"); + return; } @Override diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/mixins/MySQLMixin.java b/mdbc-server/src/main/java/org/onap/music/mdbc/mixins/MySQLMixin.java index 25b3de0..00abe85 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/mixins/MySQLMixin.java +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/mixins/MySQLMixin.java @@ -668,7 +668,9 @@ NEW.field refers to the new value } finally { try { - rs.close(); + if(rs!=null) { + rs.close(); + } } catch (SQLException e) { //continue } diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/tools/CreateNodeConfigurations.java b/mdbc-server/src/main/java/org/onap/music/mdbc/tools/CreateNodeConfigurations.java index d5ab051..bf14191 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/tools/CreateNodeConfigurations.java +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/tools/CreateNodeConfigurations.java @@ -19,8 +19,11 @@ */ package org.onap.music.mdbc.tools; +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.exceptions.MDBCServiceException; import org.onap.music.logging.EELFLoggerDelegate; +import org.onap.music.main.MusicUtil; import org.onap.music.mdbc.configurations.NodeConfiguration; import org.onap.music.mdbc.configurations.TablesConfiguration; import com.beust.jcommander.JCommander; @@ -52,6 +55,7 @@ public class CreateNodeConfigurations { public void readInput(){ + LOG.info("Reading inputs"); try { inputConfig = TablesConfiguration.readJsonFromFile(tableConfigurationsFile); } catch (FileNotFoundException e) { @@ -75,6 +79,8 @@ public class CreateNodeConfigurations { } public static void main(String[] args) { + LOG.info("Starting create node configuration executor"); + LOG.info("Using music file configuration:"+MusicUtil.getMusicPropertiesFilePath()); CreateNodeConfigurations configs = new CreateNodeConfigurations(); @SuppressWarnings("deprecation") JCommander jc = new JCommander(configs, args); diff --git a/mdbc-server/src/main/java/org/onap/music/mdbc/tools/CreatePartition.java b/mdbc-server/src/main/java/org/onap/music/mdbc/tools/CreatePartition.java index 0277902..7624201 100755 --- a/mdbc-server/src/main/java/org/onap/music/mdbc/tools/CreatePartition.java +++ b/mdbc-server/src/main/java/org/onap/music/mdbc/tools/CreatePartition.java @@ -32,6 +32,9 @@ public class CreatePartition { @Parameter(names = { "-t", "--tables" }, required = true, description = "This is the tables that are assigned to this ") private String tables; + @Parameter(names = { "-e", "--tables" }, required = true, + description = "This is the tables that are assigned to this ") + private String eventual; @Parameter(names = { "-f", "--file" }, required = true, description = "This is the output file that is going to have the configuration for the ranges") private String file; @@ -48,7 +51,7 @@ public class CreatePartition { } public void convert(){ - config = new NodeConfiguration(tables, UUID.fromString(mriIndex),"test",""); + config = new NodeConfiguration(tables, eventual,UUID.fromString(mriIndex),"test",""); } public void saveToFile(){ diff --git a/mdbc-server/src/main/resources/logback.xml b/mdbc-server/src/main/resources/logback.xml index df02405..af973b8 100755 --- a/mdbc-server/src/main/resources/logback.xml +++ b/mdbc-server/src/main/resources/logback.xml @@ -46,6 +46,7 @@ + diff --git a/mdbc-server/src/main/resources/music.properties b/mdbc-server/src/main/resources/music.properties index 83dcb7c..a676f70 100755 --- a/mdbc-server/src/main/resources/music.properties +++ b/mdbc-server/src/main/resources/music.properties @@ -1,8 +1,8 @@ cassandra.host =\ - localhost + 143.215.128.49 cassandra.user =\ - cassandra + metric cassandra.password =\ - cassandra + metriccluster zookeeper.host =\ localhost diff --git a/mdbc-server/src/test/java/org/onap/music/mdbc/TestUtils.java b/mdbc-server/src/test/java/org/onap/music/mdbc/TestUtils.java index 8c45c2e..291179a 100755 --- a/mdbc-server/src/test/java/org/onap/music/mdbc/TestUtils.java +++ b/mdbc-server/src/test/java/org/onap/music/mdbc/TestUtils.java @@ -201,7 +201,7 @@ public class TestUtils { break; case "all.public.ips": String[] ips = prop.getProperty(key).split(":"); - if (ips.length == 1) { + if (ips.length== 1) { // Future use } else if (ips.length > 1) { MusicUtil.setAllPublicIps( diff --git a/mdbc-server/src/test/java/org/onap/music/mdbc/mixins/MusicMixinTest.java b/mdbc-server/src/test/java/org/onap/music/mdbc/mixins/MusicMixinTest.java index 0b2bb57..5221964 100644 --- a/mdbc-server/src/test/java/org/onap/music/mdbc/mixins/MusicMixinTest.java +++ b/mdbc-server/src/test/java/org/onap/music/mdbc/mixins/MusicMixinTest.java @@ -112,7 +112,7 @@ public class MusicMixinTest { @Test(timeout=1000) public void own() { - Range range = new Range("table1"); + Range range = new Range("TABLE1"); List ranges = new ArrayList<>(); ranges.add(range); final DatabasePartition partition = TestUtils.createBasicRow(range, mixin, mdbcServerName); @@ -149,21 +149,21 @@ public class MusicMixinTest { @Test(timeout=1000) public void own2() throws InterruptedException, MDBCServiceException { List range12 = new ArrayList<>( Arrays.asList( - new Range("range1"), - new Range("range2") + new Range("RANGE1"), + new Range("RANGE2") )); List range34 = new ArrayList<>( Arrays.asList( - new Range("range3"), - new Range("range4") + new Range("RANGE3"), + new Range("RANGE4") )); List range24 = new ArrayList<>( Arrays.asList( - new Range("range2"), - new Range("range4") + new Range("RANGE2"), + new Range("RANGE4") )); List range123 = new ArrayList<>( Arrays.asList( - new Range("range1"), - new Range("range2"), - new Range("range3") + new Range("RANGE1"), + new Range("RANGE2"), + new Range("RANGE3") )); DatabasePartition db1 = addRow(range12, false); DatabasePartition db2 = addRow(range34, false); @@ -189,8 +189,8 @@ public class MusicMixinTest { DagNode missing = outgoingEdges.get(0); Set missingRanges = missing.getRangeSet(); assertEquals(2,missingRanges.size()); - assertTrue(missingRanges.contains(new Range("range1"))); - assertTrue(missingRanges.contains(new Range("range3"))); + assertTrue(missingRanges.contains(new Range("RANGE1"))); + assertTrue(missingRanges.contains(new Range("RANGE3"))); List outgoingEdges1 = missing.getOutgoingEdges(); assertEquals(1,outgoingEdges1.size()); @@ -198,9 +198,9 @@ public class MusicMixinTest { assertFalse(finalNode.hasNotIncomingEdges()); Set finalSet = finalNode.getRangeSet(); assertEquals(3,finalSet.size()); - assertTrue(finalSet.contains(new Range("range1"))); - assertTrue(finalSet.contains(new Range("range2"))); - assertTrue(finalSet.contains(new Range("range3"))); + assertTrue(finalSet.contains(new Range("RANGE1"))); + assertTrue(finalSet.contains(new Range("RANGE2"))); + assertTrue(finalSet.contains(new Range("RANGE3"))); DagNode node5 = dag.getNode(db5.getMRIIndex()); List toRemoveOutEdges = node5.getOutgoingEdges(); diff --git a/mdbc-server/src/test/java/org/onap/music/mdbc/ownership/OwnershipAndCheckpointTest.java b/mdbc-server/src/test/java/org/onap/music/mdbc/ownership/OwnershipAndCheckpointTest.java index 753c629..0c2a804 100644 --- a/mdbc-server/src/test/java/org/onap/music/mdbc/ownership/OwnershipAndCheckpointTest.java +++ b/mdbc-server/src/test/java/org/onap/music/mdbc/ownership/OwnershipAndCheckpointTest.java @@ -208,9 +208,12 @@ public class OwnershipAndCheckpointTest { OwnershipReturn own = cleanAndOwnPartition(ranges,ownOpId); Map locks = new HashMap<>(); - locks.put(own.getDag().getNode(own.getRangeId()).getRow(),new LockResult(own.getRangeId(),own.getOwnerId(),true, - ranges)); - ownAndCheck.checkpoint(musicMixin,mysqlMixin,own.getDag(),ranges,locks, ownOpId); + if(own.getDag()!=null) { + locks.put(own.getDag().getNode(own.getRangeId()).getRow(), + new LockResult(own.getRangeId(), own.getOwnerId(), true, + ranges)); + ownAndCheck.checkpoint(musicMixin, mysqlMixin, own.getDag(), ranges, locks, ownOpId); + } checkData(); } @@ -227,9 +230,13 @@ public class OwnershipAndCheckpointTest { UUID ownOpId = MDBCUtils.generateTimebasedUniqueKey(); OwnershipReturn own = cleanAndOwnPartition(ranges,ownOpId); + Map locks = new HashMap<>(); - locks.put(own.getDag().getNode(own.getRangeId()).getRow(),new LockResult(own.getRangeId(),own.getOwnerId(),true, - ranges)); + if(own.getDag()!=null) { + locks.put(own.getDag().getNode(own.getRangeId()).getRow(), + new LockResult(own.getRangeId(), own.getOwnerId(), true, + ranges)); + } ownAndCheck.warmup(musicMixin,mysqlMixin,ranges); checkData(); diff --git a/pom.xml b/pom.xml index 3398faa..cbd2771 100755 --- a/pom.xml +++ b/pom.xml @@ -98,6 +98,7 @@ mdbc-server mdbc-packages + mdbc-benchmark @@ -248,6 +249,16 @@ netty-handler 4.1.30.Final + + com.beust + jcommander + 1.72 + + + org.apache.commons + commons-math3 + 3.0 +