├── scripts ├── callScaleIn.sh ├── gitexclusefiles.sh ├── callScaleOut.sh ├── grantMaster.sql ├── slave-template.sql ├── set_env.sh ├── cleanDB.sh ├── initSlave.sh ├── initMaster.sh ├── enableMonitors.sh ├── testConnection.sh ├── scaleOut.sh ├── prepareMasterSlaves.sh └── my.cnf ├── tpcw ├── dstats.tar.gz ├── WebContent.tar.gz ├── mysql-connector-java-5.1.32.jar ├── mysql.sql └── tpcw.patch ├── target └── classes │ ├── com │ └── bittiger │ │ ├── logic │ │ ├── Server.class │ │ ├── Stats.class │ │ ├── Executor.class │ │ ├── Monitor.class │ │ ├── ActionType.class │ │ ├── Application.class │ │ ├── Controller.class │ │ ├── Destroyer.class │ │ ├── EventQueue.class │ │ ├── LoadBalancer.class │ │ └── rules │ │ │ ├── ScaleInRule.class │ │ │ ├── ScaleOutRule.class │ │ │ └── AvailabilityNotEnoughRule.class │ │ ├── querypool │ │ ├── bq1.class │ │ ├── bq10.class │ │ ├── bq11.class │ │ ├── bq12.class │ │ ├── bq13.class │ │ ├── bq2.class │ │ ├── bq3.class │ │ ├── bq4.class │ │ ├── bq5.class │ │ ├── bq6.class │ │ ├── bq7.class │ │ ├── bq8.class │ │ ├── bq9.class │ │ ├── wq1.class │ │ ├── wq2.class │ │ ├── wq3.class │ │ ├── wq4.class │ │ ├── wq5.class │ │ ├── StatsQuery.class │ │ ├── StringPool.class │ │ ├── ParmGenerator.class │ │ ├── PopulateTable.class │ │ ├── QueryMetaData.class │ │ ├── TableMetaData.class │ │ └── CleanStatsQuery.class │ │ └── client │ │ ├── Utilities.class │ │ ├── UserSession.class │ │ ├── ClientEmulator.class │ │ ├── TPCWProperties.class │ │ └── OpenSystemTicketProducer.class │ ├── META-INF │ ├── MANIFEST.MF │ └── maven │ │ └── com.bittiger │ │ └── elasticDB │ │ ├── pom.properties │ │ └── pom.xml │ ├── log4j.properties │ └── tpcw.properties ├── src └── main │ ├── java │ └── com │ │ └── bittiger │ │ ├── logic │ │ ├── ActionType.java │ │ ├── Server.java │ │ ├── Application.java │ │ ├── Stats.java │ │ ├── Destroyer.java │ │ ├── rules │ │ │ ├── ScaleOutRule.java │ │ │ ├── AvailabilityNotEnoughRule.java │ │ │ └── ScaleInRule.java │ │ ├── EventQueue.java │ │ ├── Controller.java │ │ ├── Executor.java │ │ ├── LoadBalancer.java │ │ └── Monitor.java │ │ ├── querypool │ │ ├── QueryMetaData.java │ │ ├── CleanStatsQuery.java │ │ ├── bq10.java │ │ ├── bq3.java │ │ ├── bq13.java │ │ ├── bq9.java │ │ ├── bq1.java │ │ ├── bq5.java │ │ ├── bq11.java │ │ ├── bq4.java │ │ ├── bq12.java │ │ ├── bq2.java │ │ ├── bq6.java │ │ ├── bq7.java │ │ ├── StatsQuery.java │ │ ├── wq1.java │ │ ├── wq5.java │ │ ├── bq8.java │ │ ├── wq4.java │ │ ├── wq3.java │ │ ├── wq2.java │ │ ├── ParmGenerator.java │ │ ├── StringPool.java │ │ ├── TableMetaData.java │ │ └── PopulateTable.java │ │ └── client │ │ ├── OpenSystemTicketProducer.java │ │ ├── Utilities.java │ │ ├── TPCWProperties.java │ │ ├── UserSession.java │ │ └── ClientEmulator.java │ └── resources │ ├── log4j.properties │ └── tpcw.properties ├── README.md └── pom.xml /scripts/callScaleIn.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | ssh root@$1 "/etc/init.d/mysql stop" -------------------------------------------------------------------------------- /scripts/gitexclusefiles.sh: -------------------------------------------------------------------------------- 1 | git config --global core.excludesfile .Eclipse.gitignore 2 | -------------------------------------------------------------------------------- /scripts/callScaleOut.sh: -------------------------------------------------------------------------------- 1 | ssh root@$1 "/home/ubuntu/elasticDB/scripts/scaleOut.sh $1 $2 $3" 2 | -------------------------------------------------------------------------------- /tpcw/dstats.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/tpcw/dstats.tar.gz -------------------------------------------------------------------------------- /tpcw/WebContent.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/tpcw/WebContent.tar.gz -------------------------------------------------------------------------------- /scripts/grantMaster.sql: -------------------------------------------------------------------------------- 1 | GRANT REPLICATION SLAVE ON *.* TO 'root'@'%'; 2 | show master status; 3 | 4 | -------------------------------------------------------------------------------- /tpcw/mysql-connector-java-5.1.32.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/tpcw/mysql-connector-java-5.1.32.jar -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/Server.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/Server.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/Stats.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/Stats.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/Executor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/Executor.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/Monitor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/Monitor.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq1.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq10.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq10.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq11.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq11.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq12.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq12.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq13.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq13.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq2.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq3.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq3.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq4.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq4.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq5.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq5.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq6.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq6.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq7.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq7.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq8.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq8.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/bq9.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/bq9.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/wq1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/wq1.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/wq2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/wq2.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/wq3.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/wq3.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/wq4.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/wq4.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/wq5.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/wq5.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/client/Utilities.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/client/Utilities.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/ActionType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/ActionType.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/Application.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/Application.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/Controller.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/Controller.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/Destroyer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/Destroyer.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/EventQueue.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/EventQueue.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/client/UserSession.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/client/UserSession.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/LoadBalancer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/LoadBalancer.class -------------------------------------------------------------------------------- /target/classes/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Built-By: FunkyARUI 3 | Build-Jdk: 1.8.0_101 4 | Created-By: Maven Integration for Eclipse 5 | 6 | -------------------------------------------------------------------------------- /target/classes/com/bittiger/client/ClientEmulator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/client/ClientEmulator.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/client/TPCWProperties.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/client/TPCWProperties.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/StatsQuery.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/StatsQuery.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/StringPool.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/StringPool.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/rules/ScaleInRule.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/rules/ScaleInRule.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/rules/ScaleOutRule.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/rules/ScaleOutRule.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/ParmGenerator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/ParmGenerator.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/PopulateTable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/PopulateTable.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/QueryMetaData.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/QueryMetaData.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/TableMetaData.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/TableMetaData.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/querypool/CleanStatsQuery.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/querypool/CleanStatsQuery.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/client/OpenSystemTicketProducer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/client/OpenSystemTicketProducer.class -------------------------------------------------------------------------------- /target/classes/com/bittiger/logic/rules/AvailabilityNotEnoughRule.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FunkyARUI/Elastic-DB/HEAD/target/classes/com/bittiger/logic/rules/AvailabilityNotEnoughRule.class -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/ActionType.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | public enum ActionType { 4 | AvailNotEnoughAddServer, BadPerformanceAddServer, GoodPerformanceRemoveServer, NoOp 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/QueryMetaData.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.text.ParseException; 4 | 5 | public interface QueryMetaData { 6 | public String getQueryStr() throws ParseException; 7 | } 8 | -------------------------------------------------------------------------------- /scripts/slave-template.sql: -------------------------------------------------------------------------------- 1 | STOP SLAVE; 2 | CHANGE MASTER TO 3 | MASTER_HOST='vader-1-vm3', 4 | MASTER_USER='root', 5 | MASTER_PASSWORD='TigerBit!2016', 6 | MASTER_LOG_FILE='mysql-bin.000002', 7 | MASTER_LOG_POS=445; 8 | START SLAVE; 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/CleanStatsQuery.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | public class CleanStatsQuery { 4 | 5 | public String query = "delete from datapoints"; 6 | 7 | public String getQueryStr() { 8 | return query; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /target/classes/META-INF/maven/com.bittiger/elasticDB/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Wed Jun 28 09:42:57 CDT 2017 3 | version=1.0-SNAPSHOT 4 | groupId=com.bittiger 5 | m2e.projectName=elasticDB 6 | m2e.projectLocation=/Users/FunkyARUI/Desktop/Bittiger/Ecommerce/elasticDB 7 | artifactId=elasticDB 8 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/Server.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | public class Server { 4 | String ip; 5 | 6 | public Server(String ip) { 7 | super(); 8 | this.ip = ip; 9 | } 10 | 11 | public String getIp() { 12 | return ip; 13 | } 14 | 15 | public void setIp(String ip) { 16 | this.ip = ip; 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /scripts/set_env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o allexport 4 | 5 | MYSQL_USERNAME='root' 6 | MYSQL_PASSWORD='TigerBit!2016' 7 | 8 | # HOSTS 9 | MASTER=ec2-52-15-240-190.us-east-2.compute.amazonaws.com 10 | SLAVE=(ec2-13-59-33-146.us-east-2.compute.amazonaws.com ec2-52-14-202-232.us-east-2.compute.amazonaws.com) 11 | CANDIDATE=(ec2-13-58-247-217.us-east-2.compute.amazonaws.com) 12 | 13 | set +o allexport 14 | 15 | -------------------------------------------------------------------------------- /scripts/cleanDB.sh: -------------------------------------------------------------------------------- 1 | SCRIPT_HOME=/home/ubuntu/elasticDB/scripts 2 | 3 | echo "SCRIPT_HOME is set to $SCRIPT_HOME" 4 | 5 | source $SCRIPT_HOME/set_env.sh 6 | 7 | mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD" < $SCRIPT_HOME/../tpcw/mysql.sql 8 | 9 | echo "clean mysql done" 10 | 11 | cd /home/ubuntu/java-tpcw 12 | 13 | ant gendb 14 | 15 | mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD" -e "purge binary logs before now();" 16 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/Application.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Created by IntelliJ IDEA. 7 | * User: pxiong 8 | * Date: Jun 28, 2010 9 | * Time: 12:07:35 PM 10 | * To change this template use File | Settings | File Templates. 11 | */ 12 | public class Application { 13 | public String path; 14 | public String writeQueue; 15 | public ArrayList readQueue; 16 | } 17 | -------------------------------------------------------------------------------- /tpcw/mysql.sql: -------------------------------------------------------------------------------- 1 | GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY 'TigerBit!2016'; 2 | FLUSH PRIVILEGES; 3 | 4 | drop database if exists tpcw; 5 | purge binary logs before now(); 6 | create database tpcw; 7 | 8 | drop database if exists canvasjs_db; 9 | create database canvasjs_db; 10 | use canvasjs_db; 11 | create table datapoints (x double, u double, r double, w double, m double, s double); 12 | insert into datapoints values 13 | (0,1,1,3,4,10),(1,2,4,27,2,10),(2,3,9,81,1.4,20),(3,4,16,243,1.2,20),(4,5,25,600,1.1,10); 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/Stats.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | public class Stats { 4 | public String type; 5 | public int sessionId; 6 | public long start; 7 | public long end; 8 | public long duration; 9 | 10 | public Stats(int sessionId, String type, long start, long end) { 11 | super(); 12 | this.type = type; 13 | this.sessionId = sessionId; 14 | this.start = start; 15 | this.end = end; 16 | this.duration = end - start; 17 | } 18 | 19 | public String toString() { 20 | return sessionId + "," + type + "," + duration; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /scripts/initSlave.sh: -------------------------------------------------------------------------------- 1 | SCRIPT_HOME=/home/ubuntu/elasticDB/scripts 2 | 3 | echo "SCRIPT_HOME is set to $SCRIPT_HOME" 4 | 5 | MYSQL_HOME=$SCRIPT_HOME/../mysql 6 | 7 | echo "MYSQL_HOME is set to $MYSQL_HOME" 8 | 9 | source $SCRIPT_HOME/set_env.sh 10 | 11 | rm -rf /var/lib/mysql 12 | scp -r root@$1:/var/lib/mysql /var/lib 13 | chown -R mysql.mysql /var/lib/mysql 14 | chmod -R 777 /var/lib/mysql 15 | sed -e "s/server-id=1/server-id=`expr $2`/ig" $SCRIPT_HOME/my.cnf > /etc/mysql/my.cnf 16 | chown -R mysql.mysql /etc/mysql/my.cnf 17 | chmod -R 644 /etc/mysql/my.cnf 18 | /etc/init.d/mysql start 19 | -------------------------------------------------------------------------------- /scripts/initMaster.sh: -------------------------------------------------------------------------------- 1 | SCRIPT_HOME=/home/ubuntu/elasticDB/scripts 2 | 3 | echo "SCRIPT_HOME is set to $SCRIPT_HOME" 4 | 5 | MYSQL_HOME=$SCRIPT_HOME/../mysql 6 | 7 | echo "MYSQL_HOME is set to $MYSQL_HOME" 8 | 9 | source $SCRIPT_HOME/set_env.sh 10 | 11 | #rm -rf /var/lib/mysql 12 | #tar xzvf $MYSQL_HOME/mysql-db.tar.gz -C /var/lib 13 | #chown -R mysql.mysql /var/lib/mysql 14 | #chmod -R 777 /var/lib/mysql 15 | sed -e "s/server-id=1/server-id=`expr $1`/ig" $SCRIPT_HOME/my.cnf > /etc/mysql/my.cnf 16 | chown -R mysql.mysql /etc/mysql/my.cnf 17 | chmod -R 644 /etc/mysql/my.cnf 18 | /etc/init.d/mysql start 19 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Root logger option 2 | #log4j.rootLogger=DEBUG, file, stdout 3 | #log4j.rootLogger=DEBUG, stdout 4 | log4j.rootLogger=INFO, stdout 5 | 6 | # Direct log messages to a log file 7 | #log4j.appender.file=org.apache.log4j.RollingFileAppender 8 | #log4j.appender.file.File=/tmp/tpcw.log 9 | #log4j.appender.file.MaxFileSize=10MB 10 | #log4j.appender.file.MaxBackupIndex=10 11 | #log4j.appender.file.layout=org.apache.log4j.PatternLayout 12 | #log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 13 | 14 | # Direct log messages to stdout 15 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 16 | log4j.appender.stdout.Target=System.out 17 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 18 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -------------------------------------------------------------------------------- /target/classes/log4j.properties: -------------------------------------------------------------------------------- 1 | # Root logger option 2 | #log4j.rootLogger=DEBUG, file, stdout 3 | #log4j.rootLogger=DEBUG, stdout 4 | log4j.rootLogger=INFO, stdout 5 | 6 | # Direct log messages to a log file 7 | #log4j.appender.file=org.apache.log4j.RollingFileAppender 8 | #log4j.appender.file.File=/tmp/tpcw.log 9 | #log4j.appender.file.MaxFileSize=10MB 10 | #log4j.appender.file.MaxBackupIndex=10 11 | #log4j.appender.file.layout=org.apache.log4j.PatternLayout 12 | #log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 13 | 14 | # Direct log messages to stdout 15 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 16 | log4j.appender.stdout.Target=System.out 17 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 18 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq10.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | public class bq10 implements QueryMetaData{ 6 | public String query = "select count(*) from customer where " + 7 | "c_uname not like '?' "; 8 | ParmGenerator pg = new ParmGenerator(); 9 | 10 | public String getQueryStr() { 11 | String qString = ""; 12 | int count = 0; 13 | StringTokenizer st = new StringTokenizer(query, "?", false); 14 | while (st.hasMoreTokens()) { 15 | qString += st.nextToken(); 16 | count++; 17 | switch (count) { 18 | case 1: 19 | qString += pg.getCustomerUserName(); 20 | break; 21 | case 2: 22 | break; 23 | default: 24 | System.out.println("More token than expected"); 25 | System.exit(100); 26 | } 27 | } 28 | return qString; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq3.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | //sql.getBook 6 | public class bq3 implements QueryMetaData { 7 | public String query = "select * from item, author where " 8 | + "i_a_id = a_id and " + "i_id = ?"; 9 | ParmGenerator pg = new ParmGenerator(); 10 | 11 | public String getQueryStr() { 12 | String qString = ""; 13 | int count = 0; 14 | StringTokenizer st = new StringTokenizer(query, "?", false); 15 | while (st.hasMoreTokens()) { 16 | qString += st.nextToken(); 17 | count++; 18 | switch (count) { 19 | case 1: 20 | qString += pg.getItemID(); 21 | break; 22 | case 2: 23 | break; 24 | default: 25 | System.out.println("More token than expected"); 26 | System.exit(100); 27 | } 28 | } 29 | return qString; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq13.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | // sql.getCDiscount 6 | public class bq13 implements QueryMetaData { 7 | public String query = "select max(c_discount) from customer where " 8 | + "(c_uname not like '?')"; 9 | ParmGenerator pg = new ParmGenerator(); 10 | 11 | public String getQueryStr() { 12 | String qString = ""; 13 | int count = 0; 14 | StringTokenizer st = new StringTokenizer(query, "?", false); 15 | while (st.hasMoreTokens()) { 16 | qString += st.nextToken(); 17 | count++; 18 | switch (count) { 19 | case 1: 20 | qString += pg.getCustomerUserName(); 21 | break; 22 | case 2: 23 | break; 24 | default: 25 | System.out.println("More token than expected"); 26 | System.exit(100); 27 | } 28 | } 29 | return qString; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq9.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | public class bq9 implements QueryMetaData { 6 | public String query = "select ol_i_id, i_title, i_publisher, i_cost, ol_qty, ol_discount, ol_comments " 7 | + "from order_line, item orders " 8 | + "where ol_i_id=i_id and ol_o_id=?"; 9 | ParmGenerator pg = new ParmGenerator(); 10 | 11 | public String getQueryStr() { 12 | String qString = ""; 13 | int count = 0; 14 | StringTokenizer st = new StringTokenizer(query, "?", false); 15 | while (st.hasMoreTokens()) { 16 | qString += st.nextToken(); 17 | count++; 18 | switch (count) { 19 | case 1: 20 | qString += pg.getOrderID(); 21 | break; 22 | case 2: 23 | break; 24 | default: 25 | System.out.println("More token than expected"); 26 | System.exit(100); 27 | } 28 | } 29 | return qString; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq1.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | //sql.getCustomer 6 | public class bq1 implements QueryMetaData { 7 | public String query = "SELECT * FROM customer, address, country WHERE customer.c_addr_id = address.addr_id AND address.addr_co_id = country.co_id AND " 8 | + "(customer.c_uname = '?')"; 9 | ParmGenerator pg = new ParmGenerator(); 10 | 11 | public String getQueryStr() { 12 | String qString = ""; 13 | int count = 0; 14 | StringTokenizer st = new StringTokenizer(query, "?", false); 15 | while (st.hasMoreTokens()) { 16 | qString += st.nextToken(); 17 | count++; 18 | switch (count) { 19 | case 1: 20 | qString += pg.getCustomerUserName(); 21 | break; 22 | case 2: 23 | break; 24 | default: 25 | System.out.println("More token than expected"); 26 | System.exit(100); 27 | } 28 | } 29 | return qString; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq5.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | public class bq5 implements QueryMetaData { 6 | public String query = "select i_id, i_title,a_lname, a_fname from item, author where " 7 | + "(i_subject like '%?%' or i_title like '%?%') and i_a_id = a_id"; 8 | ParmGenerator pg = new ParmGenerator(); 9 | 10 | public String getQueryStr() { 11 | String qString = ""; 12 | int count = 0; 13 | StringTokenizer st = new StringTokenizer(query, "?", false); 14 | while (st.hasMoreTokens()) { 15 | qString += st.nextToken(); 16 | count++; 17 | switch (count) { 18 | case 1: 19 | qString += pg.getItemSubject(); 20 | break; 21 | case 2: 22 | qString += pg.getItemTitle(); 23 | break; 24 | case 3: 25 | break; 26 | default: 27 | System.out.println("More token than expected"); 28 | System.exit(100); 29 | } 30 | } 31 | return qString; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq11.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | //sql.getMostRecentOrder.id 5 | public class bq11 implements QueryMetaData { 6 | public String query = "SELECT o_id " + "FROM customer, orders " 7 | + "WHERE customer.c_id = orders.o_c_id " + "AND c_uname not like '?' " 8 | + "ORDER BY o_date, orders.o_id DESC limit 1"; 9 | ParmGenerator pg = new ParmGenerator(); 10 | 11 | public String getQueryStr() { 12 | String qString = ""; 13 | int count = 0; 14 | StringTokenizer st = new StringTokenizer(query, "?", false); 15 | while (st.hasMoreTokens()) { 16 | qString += st.nextToken(); 17 | count++; 18 | switch (count) { 19 | case 1: 20 | qString += pg.getCustomerUserName(); 21 | break; 22 | case 2: 23 | break; 24 | default: 25 | System.out.println("More token than expected"); 26 | System.exit(100); 27 | } 28 | } 29 | return qString; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq4.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | public class bq4 implements QueryMetaData { 6 | public String query = "select i_id, i_title, a_lname, a_fname from item, author where " 7 | + "i_a_id = a_id and " 8 | + "(a_lname like '%?%' or a_fname like '%?%')"; 9 | ParmGenerator pg = new ParmGenerator(); 10 | 11 | public String getQueryStr() { 12 | String qString = ""; 13 | int count = 0; 14 | StringTokenizer st = new StringTokenizer(query, "?", false); 15 | while (st.hasMoreTokens()) { 16 | qString += st.nextToken(); 17 | count++; 18 | switch (count) { 19 | case 1: 20 | qString += pg.getAuthorLastName(); 21 | break; 22 | case 2: 23 | qString += pg.getAuthorFirstName(); 24 | break; 25 | case 3: 26 | break; 27 | default: 28 | System.out.println("More token than expected"); 29 | System.exit(100); 30 | } 31 | } 32 | return qString; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq12.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | public class bq12 implements QueryMetaData { 6 | public String query = "select c_uname,c_passwd, c_fname, c_lname, c_phone, c_email, c_birthdate, c_data, " 7 | + "addr_street1, addr_street2, addr_city, addr_state, addr_zip, co_name from customer, address, country " 8 | + "where c_addr_id=addr_id and addr_co_id = co_id and c_id = ?"; 9 | ParmGenerator pg = new ParmGenerator(); 10 | 11 | public String getQueryStr() { 12 | String qString = ""; 13 | int count = 0; 14 | StringTokenizer st = new StringTokenizer(query, "?", false); 15 | while (st.hasMoreTokens()) { 16 | qString += st.nextToken(); 17 | count++; 18 | switch (count) { 19 | case 1: 20 | qString += pg.getCustomerID(); 21 | break; 22 | case 2: 23 | break; 24 | default: 25 | System.out.println("More token than expected"); 26 | System.exit(100); 27 | } 28 | } 29 | return qString; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/Destroyer.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import com.bittiger.client.ClientEmulator; 11 | import com.bittiger.client.Utilities; 12 | 13 | public class Destroyer extends Thread { 14 | 15 | private ClientEmulator c; 16 | 17 | public Destroyer(ClientEmulator c) { 18 | this.c = c; 19 | } 20 | 21 | private static transient final Logger LOG = LoggerFactory 22 | .getLogger(Destroyer.class); 23 | 24 | @Override 25 | public void run() { 26 | // Executor executors the events in the queue one by one. 27 | LOG.info("Destroyer starts......"); 28 | try { 29 | Thread.sleep(c.getTpcw().interval 30 | * c.getTpcw().destroyerSleepInterval); 31 | LOG.info("Destroyer destroys " + c.getTpcw().destroyTarget); 32 | Utilities.scaleIn(c.getTpcw().destroyTarget); 33 | } catch (Exception e) { 34 | LOG.error(e.getMessage()); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq2.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | //sql.getNewProducts 6 | public class bq2 implements QueryMetaData { 7 | public String query = "SELECT i_id, i_title, a_fname, a_lname " + 8 | "FROM item, author " + 9 | "WHERE item.i_a_id = author.a_id " + 10 | "AND (item.i_subject like '%?%') " + 11 | "ORDER BY item.i_pub_date DESC,item.i_title " + 12 | "limit 50"; 13 | ParmGenerator pg = new ParmGenerator(); 14 | 15 | public String getQueryStr() { 16 | String qString = ""; 17 | int count = 0; 18 | StringTokenizer st = new StringTokenizer(query, "?", false); 19 | while (st.hasMoreTokens()) { 20 | qString += st.nextToken(); 21 | count++; 22 | switch (count) { 23 | case 1: 24 | qString += pg.getItemSubject(); 25 | break; 26 | case 2: 27 | break; 28 | default: 29 | System.out.println("More token than expected"); 30 | System.exit(100); 31 | } 32 | } 33 | return qString; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/rules/ScaleOutRule.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic.rules; 2 | 3 | import org.easyrules.annotation.Action; 4 | import org.easyrules.annotation.Condition; 5 | import org.easyrules.annotation.Rule; 6 | 7 | import com.bittiger.client.ClientEmulator; 8 | import com.bittiger.client.Utilities; 9 | import com.bittiger.logic.ActionType; 10 | import com.bittiger.logic.Controller; 11 | 12 | @Rule(name = "ScaleOutRule", description = "Check if we need to add server for better performance") 13 | public class ScaleOutRule { 14 | 15 | private ClientEmulator c; 16 | private String perf; 17 | 18 | @Condition 19 | public boolean checkPerformance() { 20 | String[] tokens = perf.split(","); 21 | String[] details = tokens[0].split(":"); 22 | return !details[3].equals("NA") 23 | && (Double.parseDouble(details[3]) > 400); 24 | } 25 | 26 | @Action 27 | public void addServer() throws Exception { 28 | c.getEventQueue().put(ActionType.BadPerformanceAddServer); 29 | } 30 | 31 | public void setInput(ClientEmulator c, String perf) { 32 | this.c = c; 33 | this.perf = perf; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq6.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | public class bq6 implements QueryMetaData { 6 | public String query = "SELECT i_id, i_title, a_fname, a_lname " 7 | + "FROM item, author, order_line " 8 | + "WHERE item.i_id = order_line.ol_i_id " 9 | + "AND item.i_a_id = author.a_id " 10 | + "AND (item.i_subject like '%?%')" 11 | + "GROUP BY i_id, i_title, a_fname, a_lname " 12 | + "ORDER BY SUM(ol_qty) DESC " + "limit 50"; 13 | ParmGenerator pg = new ParmGenerator(); 14 | 15 | public String getQueryStr() { 16 | String qString = ""; 17 | int count = 0; 18 | StringTokenizer st = new StringTokenizer(query, "?", false); 19 | while (st.hasMoreTokens()) { 20 | qString += st.nextToken(); 21 | count++; 22 | switch (count) { 23 | case 1: 24 | qString += pg.getItemSubject(); 25 | break; 26 | case 2: 27 | break; 28 | default: 29 | System.out.println("More token than expected"); 30 | System.exit(100); 31 | } 32 | } 33 | return qString; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/rules/AvailabilityNotEnoughRule.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic.rules; 2 | 3 | import org.easyrules.annotation.Action; 4 | import org.easyrules.annotation.Condition; 5 | import org.easyrules.annotation.Rule; 6 | 7 | import com.bittiger.client.ClientEmulator; 8 | import com.bittiger.client.Utilities; 9 | import com.bittiger.logic.ActionType; 10 | import com.bittiger.logic.Controller; 11 | 12 | @Rule(name = "AvailabilityRule", description = "Guarrantee the minimum number of slaves") 13 | public class AvailabilityNotEnoughRule { 14 | 15 | private ClientEmulator c; 16 | private int readQueueSize; 17 | 18 | @Condition 19 | public boolean checkNumSlave() { 20 | // The rule should be applied only if 21 | // the number of slaves is less than minimum. 22 | return readQueueSize < Utilities.minimumSlave; 23 | } 24 | 25 | @Action 26 | public void addServer() throws Exception { 27 | c.getEventQueue().put(ActionType.AvailNotEnoughAddServer); 28 | } 29 | 30 | public void setInput(ClientEmulator c, int readQueueSize) { 31 | this.c = c; 32 | this.readQueueSize = readQueueSize; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/rules/ScaleInRule.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic.rules; 2 | 3 | import org.easyrules.annotation.Action; 4 | import org.easyrules.annotation.Condition; 5 | import org.easyrules.annotation.Rule; 6 | 7 | import com.bittiger.client.ClientEmulator; 8 | import com.bittiger.client.Utilities; 9 | import com.bittiger.logic.ActionType; 10 | import com.bittiger.logic.Controller; 11 | 12 | @Rule(name = "ScaleInRule", description = "Check if we need to remove server for better resource usage") 13 | public class ScaleInRule { 14 | 15 | private ClientEmulator c; 16 | private String perf; 17 | 18 | @Condition 19 | public boolean checkPerformance() { 20 | String[] tokens = perf.split(","); 21 | String[] details = tokens[0].split(":"); 22 | return !details[3].equals("NA") 23 | && (Double.parseDouble(details[3]) < 200 && Double 24 | .parseDouble(details[3]) > 0); 25 | } 26 | 27 | @Action 28 | public void removeServer() throws Exception { 29 | c.getEventQueue().put(ActionType.GoodPerformanceRemoveServer); 30 | } 31 | 32 | public void setInput(ClientEmulator c, String perf) { 33 | this.c = c; 34 | this.perf = perf; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/EventQueue.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | public class EventQueue { 7 | Queue queue = new LinkedList(); 8 | 9 | public synchronized ActionType peek() { 10 | while (queue.isEmpty()) { 11 | try { 12 | wait(); 13 | } catch (InterruptedException e) { 14 | } 15 | } 16 | return queue.peek(); 17 | } 18 | 19 | public synchronized void get() { 20 | queue.poll(); 21 | } 22 | 23 | public synchronized void put(ActionType actionType) { 24 | switch (actionType) { 25 | case AvailNotEnoughAddServer: 26 | if (!queue.contains(ActionType.AvailNotEnoughAddServer) 27 | && !queue.contains(ActionType.BadPerformanceAddServer)) { 28 | queue.offer(actionType); 29 | } 30 | break; 31 | case BadPerformanceAddServer: 32 | case GoodPerformanceRemoveServer: 33 | // we ignore the performance request if there is anything going on 34 | // in the queue 35 | if (queue.isEmpty()) { 36 | queue.offer(actionType); 37 | } 38 | break; 39 | case NoOp: 40 | queue.offer(actionType); 41 | break; 42 | default: 43 | break; 44 | } 45 | notifyAll(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq7.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | public class bq7 implements QueryMetaData { 6 | public String query = "select c_fname, c_lname, c_phone, c_email, " 7 | + "o_id, o_date, o_sub_total, o_tax, o_total, o_ship_type, o_ship_date, o_bill_addr_id, o_ship_addr_id, o_c_id, o_status, " 8 | + "addr_street1, addr_street2, addr_city, addr_state, addr_zip, co_name from customer, address, country, orders " 9 | + "where o_id=? and c_id=? and o_bill_addr_id=addr_id and addr_co_id = co_id"; 10 | ParmGenerator pg = new ParmGenerator(); 11 | 12 | public String getQueryStr() { 13 | String qString = ""; 14 | int count = 0; 15 | StringTokenizer st = new StringTokenizer(query, "?", false); 16 | while (st.hasMoreTokens()) { 17 | qString += st.nextToken(); 18 | count++; 19 | switch (count) { 20 | case 1: 21 | qString += pg.getOrderID(); 22 | break; 23 | case 2: 24 | qString += pg.getCustomerID(); 25 | break; 26 | case 3: 27 | break; 28 | default: 29 | System.out.println("More token than expected"); 30 | System.exit(100); 31 | } 32 | } 33 | return qString; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /scripts/enableMonitors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | HOME=/home/ubuntu/elasticDB 4 | 5 | echo "HOME is set to $HOME" 6 | 7 | SCRIPT_HOME=/home/ubuntu/elasticDB/scripts 8 | 9 | echo "SCRIPT_HOME is set to $SCRIPT_HOME" 10 | 11 | TPCW_HOME=/home/ubuntu/elasticDB/tpcw 12 | 13 | echo "TPCW_HOME is set to $TPCW_HOME" 14 | 15 | LOCAL_SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 16 | 17 | echo "LOCAL_SCRIPT_HOME is set to $LOCAL_SCRIPT_HOME" 18 | 19 | source $LOCAL_SCRIPT_HOME/set_env.sh 20 | 21 | # enable CanvasJS on master 22 | echo "*** enable CanvasJS on master *********************************" 23 | ssh root@$MASTER "rm -rf /var/lib/tomcat7/webapps/WebContent" 24 | ssh root@$MASTER "tar xzvf $TPCW_HOME/WebContent.tar.gz -C /var/lib/tomcat7/webapps" 25 | 26 | # unzip dstats on all servers 27 | echo "*** unzip dstats on all servers *********************************" 28 | for i in $MASTER ${SLAVE[@]} ${CANDIDATE[@]} 29 | do 30 | echo "enable dstats on $i" 31 | ssh root@$i "tar xzvf $TPCW_HOME/dstats.tar.gz -C $TPCW_HOME" 32 | #ssh root@$i "$TPCW_HOME/./dstat-0.7.3/dstat" 33 | osascript -e 'tell application "Terminal" to do script "echo '$i' && ssh root@'$i' \"'$TPCW_HOME'/./dstat-0.7.3/dstat --color 5 \""' 34 | done 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elasticDB node setup 2 | 1. set master and slaves in set_env.sh 3 | 2. make sure you have installed mysql on all the nodes in the queues. 4 | 3. make sure those nodes in the queues have root access to each other without passwd 5 | 6 | # elasticDB eclipse 7 | 1. import code to your eclipse 8 | 2. run mvn eclipse:eclipse and mvn dependency:resolve 9 | 10 | # elasticDB property 11 | 1. modify the scripts/set_env.sh to set the MASTER, SLAVE and CANDIDATE 12 | 2. modify the tpcw.properties to set the read queue, write queue and candiate queues 13 | 3. modify the tpcw.properties to set the server that we would like to destroy (to test availability) 14 | 15 | # elasticDB experiment setup 16 | 1. ./testConnection to test the access of each other 17 | 2. ./prepareMasterSlaves to get ready for master, slave and candidates. 18 | 19 | # elasticDB run 20 | 1. From eclipse, just run without any parameter 21 | 2. From eclipse, in order to test scalability run with -c 22 | 3. From eclipse, in order to test availability and scalability run with -c -d 23 | 4. You can also run from CommandLine accordingly 24 | 25 | # elasticDB monitor 26 | 1. run ./enableMonitors.sh, this will run dstats and open windows for MASTER, SLAVE and CANDIDATE 27 | 2. open your browser to point to monitorIp:8080/WebContent/elasticdb.jsp 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/StatsQuery.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | public class StatsQuery { 6 | public StatsQuery(double x, double u, double r, double w, double m, double s) { 7 | super(); 8 | this.x = x; 9 | this.u = u; 10 | this.r = r; 11 | this.w = w; 12 | this.m = m; 13 | this.s = s; 14 | } 15 | 16 | double x; 17 | double u; 18 | double r; 19 | double w; 20 | double m; 21 | double s; 22 | 23 | public String query = "insert into datapoints values" + "(?,?,?,?,?,?)"; 24 | 25 | public String getQueryStr() { 26 | String qString = ""; 27 | int count = 0; 28 | StringTokenizer st = new StringTokenizer(query, "?", false); 29 | while (st.hasMoreTokens()) { 30 | qString += st.nextToken(); 31 | count++; 32 | switch (count) { 33 | case 1: 34 | qString += x; 35 | break; 36 | case 2: 37 | qString += u; 38 | break; 39 | case 3: 40 | qString += r; 41 | break; 42 | case 4: 43 | qString += w; 44 | break; 45 | case 5: 46 | qString += m; 47 | break; 48 | case 6: 49 | qString += s; 50 | break; 51 | case 7: 52 | break; 53 | default: 54 | System.out.println("More token than expected"); 55 | System.exit(100); 56 | } 57 | } 58 | return qString; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/Controller.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | import java.util.Date; 4 | import java.util.TimerTask; 5 | 6 | import org.easyrules.api.RulesEngine; 7 | import org.easyrules.core.RulesEngineBuilder; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import com.bittiger.client.ClientEmulator; 12 | import com.bittiger.logic.rules.ScaleInRule; 13 | import com.bittiger.logic.rules.ScaleOutRule; 14 | 15 | public class Controller extends TimerTask { 16 | private ClientEmulator c; 17 | private static transient final Logger LOG = LoggerFactory 18 | .getLogger(Controller.class); 19 | 20 | public Controller(ClientEmulator ce) { 21 | this.c = ce; 22 | } 23 | 24 | public void run() { 25 | Date date = new Date(); 26 | LOG.info("Controller is running at " + date.toString()); 27 | String perf = c.getMonitor().readPerformance(); 28 | /** 29 | * Create a rules engine and register the business rule 30 | */ 31 | RulesEngine rulesEngine = RulesEngineBuilder.aNewRulesEngine().build(); 32 | ScaleOutRule scaleOutRule = new ScaleOutRule(); 33 | scaleOutRule.setInput(c, perf); 34 | ScaleInRule scaleInRule = new ScaleInRule(); 35 | scaleInRule.setInput(c, perf); 36 | rulesEngine.registerRule(scaleOutRule); 37 | rulesEngine.registerRule(scaleInRule); 38 | rulesEngine.fireRules(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/wq1.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | public class wq1 implements QueryMetaData { 6 | public String query = "insert into address values" 7 | + "(?,'?','?','?','?','?',?)"; 8 | ParmGenerator pg = new ParmGenerator(); 9 | 10 | public String getQueryStr() { 11 | PopulateTable pt = new PopulateTable(); 12 | String qString = ""; 13 | int count = 0; 14 | StringTokenizer st = new StringTokenizer(query, "?", false); 15 | while (st.hasMoreTokens()) { 16 | qString += st.nextToken(); 17 | count++; 18 | switch (count) { 19 | case 1: 20 | qString += pt.randomBetweenInclusive(576000, 2147483647); 21 | break; 22 | case 2: 23 | qString += pt.randomAstring(15, 40); 24 | break; 25 | case 3: 26 | qString += pt.randomAstring(15, 40); 27 | break; 28 | case 4: 29 | qString += pt.randomAstring(4, 30); 30 | break; 31 | case 5: 32 | qString += pt.randomAstring(2, 20); 33 | break; 34 | case 6: 35 | qString += pt.randomAstring(5, 10); 36 | break; 37 | case 7: 38 | qString += pt.randomBetweenInclusive(1, 92); 39 | break; 40 | case 8: 41 | break; 42 | default: 43 | System.out.println("More token than expected"); 44 | System.exit(100); 45 | } 46 | } 47 | return qString; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/client/OpenSystemTicketProducer.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.client; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.Random; 5 | 6 | public class OpenSystemTicketProducer extends Thread { 7 | private TPCWProperties tpcw = null; 8 | public long startTime; 9 | public long warmup; 10 | public long mi; 11 | public long warmdown; 12 | private final BlockingQueue queue; 13 | private Random rand; 14 | private double[] rate; 15 | 16 | public OpenSystemTicketProducer(ClientEmulator ce, BlockingQueue bQueue) { 17 | this.tpcw = ce.getTpcw(); 18 | this.warmup = tpcw.warmup; 19 | this.mi = tpcw.mi; 20 | this.warmdown = tpcw.warmdown; 21 | this.queue = bQueue; 22 | this.rand = new Random(); 23 | this.rate = tpcw.rate; 24 | } 25 | 26 | public void run() { 27 | int num = 0; 28 | while (true) { 29 | long currTime = System.currentTimeMillis(); 30 | if (currTime - startTime < (warmup + mi + warmdown)) { 31 | double r = rand.nextDouble(); 32 | int rlIndex = (int) (Math.floor((double) (currTime - startTime) 33 | / tpcw.interval)); 34 | double sendrate = 0 - rate[rlIndex]; 35 | long wait = ((long) (sendrate * Math.log(r))); 36 | try { 37 | Thread.sleep(wait); 38 | queue.put(num++); 39 | } catch (Exception e) { 40 | e.printStackTrace(); 41 | } 42 | 43 | } else { 44 | // put additional tickets to make system end 45 | for (int j = 0; j < 1000000; j++) { 46 | try { 47 | queue.put(num++); 48 | } catch (InterruptedException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | break; 53 | } 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /scripts/testConnection.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | HOME=/home/ubuntu/elasticDB 4 | 5 | echo "HOME is set to $HOME" 6 | 7 | SCRIPT_HOME=/home/ubuntu/elasticDB/scripts 8 | 9 | echo "SCRIPT_HOME is set to $SCRIPT_HOME" 10 | 11 | CURRENT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 12 | 13 | echo "CURRENT_HOME is set to $CURRENT_HOME" 14 | 15 | source $CURRENT_HOME/set_env.sh 16 | 17 | TPCW_HOME=$CURRENT_HOME/../tpcw 18 | 19 | TPCW_HOME="$( cd "$TPCW_HOME" && pwd )" 20 | 21 | echo "TPCW_HOME is set to $TPCW_HOME" 22 | 23 | # Check scp from local to all servers 24 | echo "*** Check scp from local to all servers *********************************" 25 | for i in $MASTER ${SLAVE[@]} ${CANDIDATE[@]} 26 | do 27 | echo "check local to $i" 28 | ssh -o StrictHostKeyChecking=no -o BatchMode=yes root@$i "hostname" 29 | done 30 | 31 | echo "*** sync elastic db *********************************" 32 | for i in $MASTER ${SLAVE[@]} ${CANDIDATE[@]} 33 | do 34 | echo "sync to $i" 35 | ssh root@$i "rm -rf $HOME" 36 | ssh root@$i "mkdir -p $HOME" 37 | scp -r $CURRENT_HOME root@$i:$HOME 38 | scp -r $TPCW_HOME root@$i:$HOME 39 | done 40 | 41 | 42 | # Check scp to all servers 43 | echo "*** checking scp to all servers *********************************" 44 | 45 | for i in $MASTER ${SLAVE[@]} ${CANDIDATE[@]} 46 | do 47 | for j in $MASTER ${SLAVE[@]} ${CANDIDATE[@]} 48 | do 49 | echo "$i at $j" 50 | ssh -o StrictHostKeyChecking=no -o BatchMode=yes root@$i "ssh root@$j "hostname"" 51 | done 52 | done 53 | 54 | # Check scp to all servers 55 | echo "*** change my.cnf to open to everywhere *********************************" 56 | for i in $MASTER ${SLAVE[@]} ${CANDIDATE[@]} 57 | do 58 | echo "configure mysql at $i" 59 | ssh root@$i "sed -i "s/127.0.0.1/0.0.0.0/ig" /etc/mysql/my.cnf" 60 | ssh root@$i "/etc/init.d/mysql restart" 61 | done 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/wq5.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | import java.util.Calendar; 5 | import java.util.Random; 6 | import java.sql.PreparedStatement; 7 | import java.text.ParseException; 8 | 9 | public class wq5 implements QueryMetaData { 10 | public String query = "insert into order_line values" + "(?,?,?,?,?,'?')"; 11 | ParmGenerator pg = new ParmGenerator(); 12 | 13 | public String getQueryStr() throws ParseException { 14 | PopulateTable pt = new PopulateTable(); 15 | String qString = ""; 16 | int count = 0; 17 | StringTokenizer st = new StringTokenizer(query, "?", false); 18 | int id = pt.randomBetweenInclusive(6, 1000000); 19 | 20 | while (st.hasMoreTokens()) { 21 | qString += st.nextToken(); 22 | count++; 23 | switch (count) { 24 | case 1: 25 | qString += id; 26 | break; 27 | case 2: 28 | qString += pt.randomBetweenInclusive(1, 259200); 29 | break; 30 | case 3: 31 | qString += pt.randomBetweenInclusive(1, 10000); 32 | break; 33 | case 4: 34 | qString += pt.randomBetweenInclusive(1, 300); 35 | break; 36 | case 5: 37 | float ol_discount = pt.randomFloatTwoWithin(0, 0, 0, 3) / 10; // sent 38 | // [0.00..0.3] 39 | // instead 40 | // of 41 | // [0.00..0.03], 42 | // so 43 | // divide 44 | // by 45 | // 10 46 | qString += pt.OL_DISCOUNT(ol_discount); 47 | break; 48 | case 6: 49 | qString += pt.randomAstring(20, 100); 50 | break; 51 | case 7: 52 | break; 53 | default: 54 | System.out.println("More token than expected"); 55 | System.exit(100); 56 | } 57 | } 58 | return qString; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/bq8.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | 5 | //sql.getMostRecentOrder.order 6 | public class bq8 implements QueryMetaData { 7 | public String query = "SELECT orders.*, customer.*, " 8 | + " cc_xacts.cx_type, " 9 | + " ship.addr_street1 AS ship_addr_street1, " 10 | + " ship.addr_street2 AS ship_addr_street2, " 11 | + " ship.addr_state AS ship_addr_state, " 12 | + " ship.addr_zip AS ship_addr_zip, " 13 | + " ship_co.co_name AS ship_co_name, " 14 | + " bill.addr_street1 AS bill_addr_street1, " 15 | + " bill.addr_street2 AS bill_addr_street2, " 16 | + " bill.addr_state AS bill_addr_state, " 17 | + " bill.addr_zip AS bill_addr_zip, " 18 | + " bill_co.co_name AS bill_co_name " 19 | + "FROM customer, orders, cc_xacts," + " address AS ship, " 20 | + " country AS ship_co, " + " address AS bill, " 21 | + " country AS bill_co " + "WHERE orders.o_id = ? " 22 | + " AND cx_o_id = orders.o_id " 23 | + " AND customer.c_id = orders.o_c_id " 24 | + " AND orders.o_bill_addr_id = bill.addr_id " 25 | + " AND bill.addr_co_id = bill_co.co_id " 26 | + " AND orders.o_ship_addr_id = ship.addr_id " 27 | + " AND ship.addr_co_id = ship_co.co_id " 28 | + " AND orders.o_c_id = customer.c_id"; 29 | ParmGenerator pg = new ParmGenerator(); 30 | 31 | public String getQueryStr() { 32 | String qString = ""; 33 | int count = 0; 34 | StringTokenizer st = new StringTokenizer(query, "?", false); 35 | while (st.hasMoreTokens()) { 36 | qString += st.nextToken(); 37 | count++; 38 | switch (count) { 39 | case 1: 40 | qString += pg.getOrderID(); 41 | break; 42 | case 2: 43 | break; 44 | default: 45 | System.out.println("More token than expected"); 46 | System.exit(100); 47 | } 48 | } 49 | return qString; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/client/Utilities.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.client; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import com.bittiger.logic.Server; 11 | 12 | public class Utilities { 13 | private static transient final Logger LOG = LoggerFactory 14 | .getLogger(Utilities.class); 15 | 16 | public static final int retryTimes = 3; 17 | 18 | public static final int minimumSlave = 3; 19 | 20 | 21 | public static String getUrl(Server server) { 22 | return "jdbc:mysql://" + server.getIp() + "/tpcw"; 23 | } 24 | 25 | public static String getStatsUrl(String serverIp) { 26 | return "jdbc:mysql://" + serverIp + "/canvasjs_db"; 27 | } 28 | 29 | public static boolean scaleOut(String source, String target, String master) 30 | throws InterruptedException, IOException { 31 | ProcessBuilder pb = new ProcessBuilder("/bin/bash", 32 | "scripts/callScaleOut.sh", source, target, master); 33 | pb.redirectErrorStream(true); 34 | Process p = pb.start(); 35 | LOG.info("Kick in " + target + " from " + source); 36 | BufferedReader is = new BufferedReader(new InputStreamReader( 37 | p.getInputStream())); 38 | String line; 39 | while ((line = is.readLine()) != null) 40 | LOG.info(line); 41 | p.waitFor(); 42 | return true; 43 | } 44 | 45 | public static boolean scaleIn(String target) throws InterruptedException, 46 | IOException { 47 | ProcessBuilder pb = new ProcessBuilder("/bin/bash", 48 | "scripts/callScaleIn.sh", target); 49 | pb.redirectErrorStream(true); 50 | Process p = pb.start(); 51 | LOG.info("Kick out " + target); 52 | BufferedReader is = new BufferedReader(new InputStreamReader( 53 | p.getInputStream())); 54 | String line; 55 | while ((line = is.readLine()) != null) 56 | LOG.info(line); 57 | p.waitFor(); 58 | return true; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scripts/scaleOut.sh: -------------------------------------------------------------------------------- 1 | #this should be called from source 2 | SCRIPT_HOME=/home/ubuntu/elasticDB/scripts 3 | 4 | echo "SCRIPT_HOME is set to $SCRIPT_HOME" 5 | 6 | MYSQL_HOME=$SCRIPT_HOME/../mysql 7 | 8 | echo "MYSQL_HOME is set to $MYSQL_HOME" 9 | 10 | source $SCRIPT_HOME/set_env.sh 11 | 12 | SOURCE=$1 13 | TARGET=$2 14 | MASTER=$3 15 | 16 | echo "$1 $2 $3" 17 | 18 | echo "step 1 stop the source slave" 19 | mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD" -e "stop slave;" 20 | 21 | echo "step 2 get source slave's status" 22 | var=$(cat /var/lib/mysql/relay-log.info | xargs | awk -F" " '{print $1,$2,$3,$4}') 23 | set -- $var 24 | echo "relay bin is $1, pos is $2, master bin is $3, pos is $4" 25 | 26 | #this should be called in Ubuntu 27 | sed -e "s/vader-1-vm3/$MASTER/ig" $SCRIPT_HOME/slave-template.sql > $SCRIPT_HOME/grantSlave.sql 28 | sed -i "s/mysql-bin.000002/$3/ig" $SCRIPT_HOME/grantSlave.sql 29 | sed -i "s/=445/=$4/ig" $SCRIPT_HOME/grantSlave.sql 30 | 31 | scp $SCRIPT_HOME/grantSlave.sql root@$TARGET:$SCRIPT_HOME/grantSlave.sql 32 | 33 | rm -rf $SCRIPT_HOME/grantSlave.sql* 34 | 35 | echo "step 3 stop target $TARGET" 36 | ssh root@$TARGET "/etc/init.d/mysql stop" 37 | 38 | echo "step 4 copy files from $SOURCE to target $TARGET" 39 | servernum=$[ ( $RANDOM % 900 ) + 100 ] 40 | ssh root@$TARGET "$SCRIPT_HOME/initSlave.sh $SOURCE `expr $servernum`" 41 | 42 | #sounds like it will automatically read it. 43 | #echo "step 5 set the relay bin" 44 | #ssh root@$TARGET "mysqlbinlog --start-position=$2 /var/lib/mysql/$1 | mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD"" 45 | 46 | echo "step 6 set the master bin" 47 | ssh root@$TARGET "mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD" < $SCRIPT_HOME/grantSlave.sql" 48 | 49 | echo "step 7 start the source slave" 50 | mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD" -e "start slave;" 51 | 52 | ssh root@$TARGET "rm -rf $SCRIPT_HOME/grantSlave.sql" 53 | 54 | echo "finish" 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/wq4.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | import java.util.Calendar; 5 | import java.util.Random; 6 | import java.sql.PreparedStatement; 7 | import java.text.ParseException; 8 | 9 | public class wq4 implements QueryMetaData { 10 | public String query = "insert into cc_xacts values" 11 | + "(?,'?',?,'?','?','?','?','?',?)"; 12 | ParmGenerator pg = new ParmGenerator(); 13 | 14 | public String getQueryStr() throws ParseException { 15 | PopulateTable pt = new PopulateTable(); 16 | String qString = ""; 17 | int count = 0; 18 | StringTokenizer st = new StringTokenizer(query, "?", false); 19 | int id = pt.randomBetweenInclusive(259200, 2147483647); 20 | Calendar cal = Calendar.getInstance(); 21 | Calendar CX_EXPIRY = pt.randomDateAdjust(cal, 22 | -pt.randomBetweenInclusive(10, 730)); 23 | StringPool sp = new StringPool(); // StringPool 24 | Random rd = new Random(); 25 | while (st.hasMoreTokens()) { 26 | qString += st.nextToken(); 27 | count++; 28 | switch (count) { 29 | case 1: 30 | qString += id; 31 | break; 32 | case 2: 33 | qString += sp.cxtype[rd.nextInt(sp.cxtype.length)]; 34 | break; 35 | case 3: 36 | qString += new Long(pt.randomNstring(16, 16)).longValue(); 37 | break; 38 | case 4: 39 | qString += pt.randomAstring(14, 30); 40 | break; 41 | case 5: 42 | qString += pt.sqlDate(CX_EXPIRY); 43 | break; 44 | case 6: 45 | qString += pt.randomAstring(15, 15); 46 | break; 47 | case 7: 48 | // qString += pt.randomNstring(9,16); 49 | qString += rd.nextFloat() * 100000; 50 | break; 51 | case 8: 52 | qString += pt.sqlDate(CX_EXPIRY); // just copy 53 | break; 54 | case 9: 55 | qString += pt.randomBetweenInclusive(1, 92); 56 | break; 57 | case 10: 58 | break; 59 | default: 60 | System.out.println("More token than expected"); 61 | System.exit(100); 62 | } 63 | } 64 | return qString; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/wq3.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | import java.util.Calendar; 5 | import java.util.Random; 6 | import java.sql.PreparedStatement; 7 | import java.text.ParseException; 8 | 9 | public class wq3 implements QueryMetaData { 10 | public String query = "insert into orders values" 11 | + "(?,?,'?','?','?','?','?','?',?,?,'?')"; 12 | ParmGenerator pg = new ParmGenerator(); 13 | 14 | public String getQueryStr() throws ParseException { 15 | PopulateTable pt = new PopulateTable(); 16 | String qString = ""; 17 | int count = 0; 18 | StringTokenizer st = new StringTokenizer(query, "?", false); 19 | int id = pt.randomBetweenInclusive(126000, 2147483647); 20 | 21 | Calendar cal = Calendar.getInstance(); 22 | Calendar O_DATE = pt.randomDateAdjust(cal, 23 | -pt.randomBetweenInclusive(0, 7)); 24 | float O_SUB_TOTAL = pt.randomFloatTwoWithin(10, 0, 9999, 99); 25 | float O_TAX = pt.O_TAX(O_SUB_TOTAL); 26 | float O_TOTAL = pt.O_TOTAL(O_SUB_TOTAL, O_TAX); 27 | Calendar O_SHIP_DATE = pt.randomDateAdjust(O_DATE, 28 | pt.randomBetweenInclusive(0, 2)); 29 | StringPool sp = new StringPool(); // StringPool 30 | Random rd = new Random(); 31 | 32 | while (st.hasMoreTokens()) { 33 | qString += st.nextToken(); 34 | count++; 35 | switch (count) { 36 | case 1: 37 | qString += id; 38 | break; 39 | case 2: 40 | qString += pt.randomBetweenInclusive(1, (int) 288000); 41 | break; 42 | case 3: 43 | qString += pt.sqlDate(O_DATE); 44 | break; 45 | case 4: 46 | qString += O_SUB_TOTAL; 47 | break; 48 | case 5: 49 | qString += O_TAX; 50 | break; 51 | case 6: 52 | qString += O_TOTAL; 53 | break; 54 | case 7: 55 | qString += sp.shiptype[rd.nextInt(sp.shiptype.length)]; 56 | break; 57 | case 8: 58 | qString += pt.sqlDateTime(O_SHIP_DATE); 59 | break; 60 | case 9: 61 | qString += pt.randomBetweenInclusive(1, 576000); 62 | break; 63 | case 10: 64 | qString += pt.randomBetweenInclusive(1, 576000); 65 | break; 66 | case 11: 67 | qString += sp.status[rd.nextInt(sp.status.length)]; 68 | break; 69 | case 12: 70 | break; 71 | default: 72 | System.out.println("More token than expected"); 73 | System.exit(100); 74 | } 75 | } 76 | return qString; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /target/classes/tpcw.properties: -------------------------------------------------------------------------------- 1 | workload_vector = 10,10,10,60,60,60,10,10,10,10,10,10 2 | rate_vector = 35,35,35,35,35,35,35,35,35,35,35,35 3 | 4 | #workload_vector = 800,800,800,800,800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800,800 5 | #rate_vector = 35,35,35,35,88, 88, 88, 88, 88, 88, 88, 88, 88, 117, 88, 88, 58, 50, 58, 50, 58, 44, 44, 39, 29, 25, 25, 27, 23, 23, 25, 25, 25, 25, 21, 21, 21, 15, 23, 29, 35, 35, 39, 44, 44, 39, 50, 44, 58, 35, 29, 29, 32, 29, 25, 25, 25, 25, 29, 23, 27, 44, 39, 29,35 6 | 7 | #workload_vector = 50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50 8 | #rate_vector = 350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350 9 | #rate_vector = 35,35,35,35,66.14,64.98,65.49,66.67,67.48,65.88,66.53,65.88,64.85,64.85,64.98,65.23,68.73,68.03,64.60,64.72,63.37,63.25,67.07,66.40,64.47,63.98,62.66,60.72,54.56,55.74,58.17,57.47,55.19,55.46,54.29,54.38,57.67,54.56,52.08,55.83,49.53,52.91,47.35,44.86,44.74,42.84,42.74,41.98,45.11,44.74,41.72,42.03,41.31,41.25,40.60,42.79,42.63,41.93,45.79,44.68,42.30,42.57,41.88,38.99,35.96,36.31,38.80,39.17,38.05,32.68,32.68,35.69,42.09,44.86,46.17,46.75,48.03,48.73,49.24,49.98,53.33,51.36,53.68,57.77,55.74,51.36,57.67,55.56,53.85,53.76,58.79,57.57,53.50,49.98,47.96,46.62,45.98,45.29,45.23,48.24,47.55,44.80,45.60,46.10,35 10 | 11 | #mixrate=1 is open, 0 is closed 12 | mixRate = 0 13 | TPCmean = 1000 14 | warmup = 60000 15 | mi = 600000 16 | warmdown = 60000 17 | 18 | interval = 60000 19 | 20 | rwratio = 0.66 21 | read = 0,0.075,0.083,0.183,0.297,0.4,0.51,0.52,0.53,0.54,0.63,0.81,0.91,1 22 | write = 0,0.187,0.53,0.68,0.84,1 23 | 24 | #vm0=35.162.86.105 25 | #vm1=54.204.168.204 26 | #vm2=35.161.215.21 27 | #vm3=35.164.142.220 28 | 29 | writeQueue = ec2-52-15-240-190.us-east-2.compute.amazonaws.com 30 | readQueue = ec2-52-15-240-190.us-east-2.compute.amazonaws.com,ec2-13-59-33-146.us-east-2.compute.amazonaws.com,ec2-52-14-202-232.us-east-2.compute.amazonaws.com 31 | candidateQueue = ec2-13-58-247-217.us-east-2.compute.amazonaws.com 32 | 33 | #Destroyer will stop mysql service at $destroyTarget after $destroyerSleepInterval 34 | destroyerSleepInterval=9 35 | destroyTarget=ec2-13-59-33-146.us-east-2.compute.amazonaws.com 36 | 37 | username = root 38 | password = TigerBit!2016 -------------------------------------------------------------------------------- /src/main/resources/tpcw.properties: -------------------------------------------------------------------------------- 1 | workload_vector = 10,10,10,60,60,60,10,10,10,10,10,10 2 | rate_vector = 35,35,35,35,35,35,35,35,35,35,35,35 3 | 4 | #workload_vector = 800,800,800,800,800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800,800 5 | #rate_vector = 35,35,35,35,88, 88, 88, 88, 88, 88, 88, 88, 88, 117, 88, 88, 58, 50, 58, 50, 58, 44, 44, 39, 29, 25, 25, 27, 23, 23, 25, 25, 25, 25, 21, 21, 21, 15, 23, 29, 35, 35, 39, 44, 44, 39, 50, 44, 58, 35, 29, 29, 32, 29, 25, 25, 25, 25, 29, 23, 27, 44, 39, 29,35 6 | 7 | #workload_vector = 50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50 8 | #rate_vector = 350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350 9 | #rate_vector = 35,35,35,35,66.14,64.98,65.49,66.67,67.48,65.88,66.53,65.88,64.85,64.85,64.98,65.23,68.73,68.03,64.60,64.72,63.37,63.25,67.07,66.40,64.47,63.98,62.66,60.72,54.56,55.74,58.17,57.47,55.19,55.46,54.29,54.38,57.67,54.56,52.08,55.83,49.53,52.91,47.35,44.86,44.74,42.84,42.74,41.98,45.11,44.74,41.72,42.03,41.31,41.25,40.60,42.79,42.63,41.93,45.79,44.68,42.30,42.57,41.88,38.99,35.96,36.31,38.80,39.17,38.05,32.68,32.68,35.69,42.09,44.86,46.17,46.75,48.03,48.73,49.24,49.98,53.33,51.36,53.68,57.77,55.74,51.36,57.67,55.56,53.85,53.76,58.79,57.57,53.50,49.98,47.96,46.62,45.98,45.29,45.23,48.24,47.55,44.80,45.60,46.10,35 10 | 11 | #mixrate=1 is open, 0 is closed 12 | mixRate = 0 13 | TPCmean = 1000 14 | warmup = 60000 15 | mi = 600000 16 | warmdown = 60000 17 | 18 | interval = 60000 19 | 20 | rwratio = 0.66 21 | read = 0,0.075,0.083,0.183,0.297,0.4,0.51,0.52,0.53,0.54,0.63,0.81,0.91,1 22 | write = 0,0.187,0.53,0.68,0.84,1 23 | 24 | #vm0=35.162.86.105 25 | #vm1=54.204.168.204 26 | #vm2=35.161.215.21 27 | #vm3=35.164.142.220 28 | 29 | writeQueue = ec2-52-15-240-190.us-east-2.compute.amazonaws.com 30 | readQueue = ec2-52-15-240-190.us-east-2.compute.amazonaws.com,ec2-13-59-33-146.us-east-2.compute.amazonaws.com,ec2-52-14-202-232.us-east-2.compute.amazonaws.com 31 | candidateQueue = ec2-13-58-247-217.us-east-2.compute.amazonaws.com 32 | 33 | #Destroyer will stop mysql service at $destroyTarget after $destroyerSleepInterval 34 | destroyerSleepInterval=9 35 | destroyTarget=ec2-13-59-33-146.us-east-2.compute.amazonaws.com 36 | 37 | username = root 38 | password = TigerBit!2016 -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/Executor.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.bittiger.client.ClientEmulator; 7 | import com.bittiger.client.Utilities; 8 | 9 | public class Executor extends Thread { 10 | 11 | private ClientEmulator c; 12 | 13 | public Executor(ClientEmulator c) { 14 | this.c = c; 15 | } 16 | 17 | private static transient final Logger LOG = LoggerFactory 18 | .getLogger(Executor.class); 19 | 20 | @Override 21 | public void run() { 22 | // Executor executors the events in the queue one by one. 23 | LOG.info("Executor starts......"); 24 | while (true) { 25 | ActionType actionType = c.getEventQueue().peek(); 26 | long currTime = System.currentTimeMillis(); 27 | if (currTime > c.getStartTime() + c.getTpcw().warmup 28 | + c.getTpcw().mi) { 29 | return; 30 | } 31 | try { 32 | LOG.info(actionType + " request received"); 33 | if (actionType == ActionType.AvailNotEnoughAddServer 34 | || actionType == ActionType.BadPerformanceAddServer) { 35 | if (c.getLoadBalancer().getCandidateQueue().size() == 0) { 36 | LOG.info("CandidateQueue size is 0, skip adding server"); 37 | } else { 38 | Server target = c.getLoadBalancer().getCandidateQueue() 39 | .remove(0); 40 | Server source = c 41 | .getLoadBalancer() 42 | .getReadQueue() 43 | .get(c.getLoadBalancer().getReadQueue().size() - 1); 44 | Server master = c.getLoadBalancer().getWriteQueue(); 45 | // make sure source ! = master 46 | if (source.equals(master)) { 47 | LOG.error("source should not be equal to master"); 48 | continue; 49 | } 50 | Utilities.scaleOut(source.getIp(), target.getIp(), 51 | master.getIp()); 52 | c.getLoadBalancer().addServer(target); 53 | LOG.info("kick in " + target.getIp() + " done "); 54 | } 55 | } else if (actionType == ActionType.GoodPerformanceRemoveServer) { 56 | if (c.getLoadBalancer().getReadQueue().size() == Utilities.minimumSlave) { 57 | LOG.info("Read queue size is " + Utilities.minimumSlave 58 | + ", skip scale in"); 59 | } else { 60 | Server server = c.getLoadBalancer().removeServer(); 61 | Utilities.scaleIn(server.getIp()); 62 | LOG.info("Kick out server" + server.getIp() + " done "); 63 | } 64 | } 65 | LOG.info(actionType + " request done"); 66 | // now consume the token 67 | c.getEventQueue().get(); 68 | } catch (Exception e) { 69 | LOG.error(e.getMessage()); 70 | } 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.bittiger 5 | elasticDB 6 | jar 7 | 1.0-SNAPSHOT 8 | elasticDB 9 | http://maven.apache.org 10 | 11 | 12 | junit 13 | junit 14 | 3.8.1 15 | test 16 | 17 | 18 | mysql 19 | mysql-connector-java 20 | 5.1.6 21 | 22 | 23 | org.slf4j 24 | slf4j-api 25 | 1.7.7 26 | 27 | 28 | org.slf4j 29 | slf4j-log4j12 30 | 1.7.7 31 | 32 | 33 | org.easyrules 34 | easyrules-jmx 35 | 2.3.0 36 | 37 | 38 | args4j 39 | args4j 40 | 2.33 41 | 42 | 43 | 44 | 45 | 46 | maven-assembly-plugin 47 | 48 | 49 | 50 | com.bittiger.client.ClientEmulator 51 | 52 | 53 | 54 | jar-with-dependencies 55 | 56 | 57 | 58 | 59 | make-assembly 60 | package 61 | 62 | single 63 | 64 | 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-compiler-plugin 70 | 2.3.2 71 | 72 | 1.6 73 | 1.6 74 | 75 | log4j.properties 76 | true 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/LoadBalancer.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.easyrules.api.RulesEngine; 7 | import org.easyrules.core.RulesEngineBuilder; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import com.bittiger.client.ClientEmulator; 12 | import com.bittiger.logic.rules.AvailabilityNotEnoughRule; 13 | 14 | public class LoadBalancer { 15 | private List readQueue = new ArrayList(); 16 | private Server writeQueue = null; 17 | private List candidateQueue = new ArrayList(); 18 | private int nextReadServer = 0; 19 | private ClientEmulator c; 20 | private static transient final Logger LOG = LoggerFactory 21 | .getLogger(LoadBalancer.class); 22 | 23 | public LoadBalancer(ClientEmulator ce) { 24 | this.c = ce; 25 | writeQueue = new Server(ce.getTpcw().writeQueue[0]); 26 | for (int i = 0; i < ce.getTpcw().readQueue.length; i++) { 27 | readQueue.add(new Server(ce.getTpcw().readQueue[i])); 28 | } 29 | for (int i = 0; i < ce.getTpcw().candidateQueue.length; i++) { 30 | candidateQueue.add(new Server(ce.getTpcw().candidateQueue[i])); 31 | } 32 | } 33 | 34 | // there is only one server in the writequeue. 35 | public Server getWriteQueue() { 36 | return writeQueue; 37 | } 38 | 39 | public synchronized Server getNextReadServer() { 40 | nextReadServer = (nextReadServer + 1) % readQueue.size(); 41 | Server server = readQueue.get(nextReadServer); 42 | LOG.debug("choose read server as " + server.getIp()); 43 | return server; 44 | } 45 | 46 | public synchronized void addServer(Server server) { 47 | readQueue.add(server); 48 | } 49 | 50 | public synchronized Server removeServer() { 51 | Server server = readQueue.remove(readQueue.size() - 1); 52 | candidateQueue.add(server); 53 | return server; 54 | } 55 | 56 | public synchronized List getReadQueue() { 57 | return readQueue; 58 | } 59 | 60 | // readQueue is shared by the UserSessions and Executor. 61 | // However, candidateQueue is only called by Executor. 62 | public List getCandidateQueue() { 63 | return candidateQueue; 64 | } 65 | 66 | public synchronized void detectFailure() { 67 | /** 68 | * Create a rules engine and register the business rule 69 | */ 70 | RulesEngine rulesEngine = RulesEngineBuilder.aNewRulesEngine().build(); 71 | AvailabilityNotEnoughRule availabilityRule = new AvailabilityNotEnoughRule(); 72 | availabilityRule.setInput(c, readQueue.size()); 73 | rulesEngine.registerRule(availabilityRule); 74 | rulesEngine.fireRules(); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /target/classes/META-INF/maven/com.bittiger/elasticDB/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.bittiger 5 | elasticDB 6 | jar 7 | 1.0-SNAPSHOT 8 | elasticDB 9 | http://maven.apache.org 10 | 11 | 12 | junit 13 | junit 14 | 3.8.1 15 | test 16 | 17 | 18 | mysql 19 | mysql-connector-java 20 | 5.1.6 21 | 22 | 23 | org.slf4j 24 | slf4j-api 25 | 1.7.7 26 | 27 | 28 | org.slf4j 29 | slf4j-log4j12 30 | 1.7.7 31 | 32 | 33 | org.easyrules 34 | easyrules-jmx 35 | 2.3.0 36 | 37 | 38 | args4j 39 | args4j 40 | 2.33 41 | 42 | 43 | 44 | 45 | 46 | maven-assembly-plugin 47 | 48 | 49 | 50 | com.bittiger.client.ClientEmulator 51 | 52 | 53 | 54 | jar-with-dependencies 55 | 56 | 57 | 58 | 59 | make-assembly 60 | package 61 | 62 | single 63 | 64 | 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-compiler-plugin 70 | 2.3.2 71 | 72 | 1.6 73 | 1.6 74 | 75 | log4j.properties 76 | true 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/wq2.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.util.StringTokenizer; 4 | import java.util.Calendar; 5 | import java.sql.PreparedStatement; 6 | import java.text.ParseException; 7 | 8 | public class wq2 implements QueryMetaData { 9 | public String query = "insert into customer values" 10 | + "(?,'?','?','?','?',?,'?','?','?','?','?','?','?','?','?','?','?')"; 11 | ParmGenerator pg = new ParmGenerator(); 12 | 13 | public String getQueryStr() throws ParseException { 14 | PopulateTable pt = new PopulateTable(); 15 | String qString = ""; 16 | int count = 0; 17 | StringTokenizer st = new StringTokenizer(query, "?", false); 18 | int id = pt.randomBetweenInclusive(288000, 2147483647); 19 | String C_UNAME = pt.DigSyl(id + 1, 0); 20 | Calendar cal = Calendar.getInstance(); 21 | Calendar C_SINCE = pt.randomDateAdjust(cal, 22 | -(pt.randomBetweenInclusive(1, 173))); 23 | Calendar C_LAST_VISIT = pt.randomDateAdjust(C_SINCE, 24 | pt.randomBetweenInclusive(0, 60)); 25 | while (st.hasMoreTokens()) { 26 | qString += st.nextToken(); 27 | count++; 28 | switch (count) { 29 | case 1: 30 | qString += id; 31 | break; 32 | case 2: 33 | qString += C_UNAME; 34 | break; 35 | case 3: 36 | qString += pt.DigSyl(id + 1, 0).toLowerCase(); 37 | break; 38 | case 4: 39 | qString += pt.randomAstring(8, 15); 40 | break; 41 | case 5: 42 | qString += pt.randomAstring(8, 15); 43 | break; 44 | case 6: 45 | qString += pt.randomBetweenInclusive(1, 2 * 140000); 46 | break; 47 | case 7: 48 | qString += pt.randomNstring(9, 16); 49 | break; 50 | case 8: 51 | qString += C_UNAME + "@" + pt.randomAstring(2, 9) + ".com"; 52 | break; 53 | case 9: 54 | qString += pt.sqlDate(C_SINCE); 55 | break; 56 | case 10: 57 | qString += pt.sqlDate(pt.currentDateCheck(C_LAST_VISIT)); 58 | break; 59 | case 11: 60 | qString += pt.sqlDateTime(cal); 61 | break; 62 | case 12: 63 | qString += pt.sqlDate(pt.randomHourAdjust(cal, 2)); 64 | break; 65 | case 13: 66 | qString += pt.randomFloatTwoWithin(0, 0, 0, 50); 67 | break; 68 | case 14: 69 | qString += (float) 0.00; 70 | break; 71 | case 15: 72 | qString += pt.randomFloatTwoWithin(0, 0, 999, 99); 73 | break; 74 | case 16: 75 | qString += pt.sqlDate(pt.randomDate(1, 1, 1880)); 76 | break; 77 | case 17: 78 | qString += pt.randomAstring(100, 500); 79 | break; 80 | case 18: 81 | break; 82 | default: 83 | System.out.println("More token than expected"); 84 | System.exit(100); 85 | } 86 | } 87 | return qString; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /scripts/prepareMasterSlaves.sh: -------------------------------------------------------------------------------- 1 | SCRIPT_HOME=/home/ubuntu/elasticDB/scripts 2 | 3 | echo "SCRIPT_HOME is set to $SCRIPT_HOME" 4 | 5 | CURRENT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 6 | 7 | echo "CURRENT_HOME is set to $CURRENT_HOME" 8 | 9 | source $CURRENT_HOME/set_env.sh 10 | 11 | echo "step 0 clean master" 12 | for target in $MASTER 13 | do 14 | echo "clean DB in $MASTER" 15 | ssh root@$MASTER "/etc/init.d/mysql start" 16 | ssh root@$target "$SCRIPT_HOME/cleanDB.sh" 17 | done 18 | 19 | echo "step 1 stop master/slave process" 20 | ssh root@$MASTER "/etc/init.d/mysql stop" 21 | 22 | for slave in ${SLAVE[@]} ${CANDIDATE[@]} 23 | do 24 | echo "step 1 stop slave $slave" 25 | ssh root@$slave "/etc/init.d/mysql stop" 26 | done 27 | 28 | echo "step 2 initialize master" 29 | for target in $MASTER 30 | do 31 | echo "init $MASTER" 32 | ssh root@$target "$SCRIPT_HOME/initMaster.sh 1" 33 | ssh root@$target "mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD" < $SCRIPT_HOME/grantMaster.sql" 34 | done 35 | 36 | echo "step 3 get master status" 37 | string=$(ssh root@$MASTER "echo "show master status" | mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD"") 38 | var=$(echo $string | awk -F" " '{print $1,$2,$3,$4,$5,$6}') 39 | set -- $var 40 | echo "bin is $5, pos is $6" 41 | # sed -i has problem in mac, we need to use -e if we would like to be compatible with linux 42 | sed -e "s/vader-1-vm3/$MASTER/g" $CURRENT_HOME/slave-template.sql > $CURRENT_HOME/grantSlave.sql 43 | sed -e "s/mysql-bin.000002/$5/g" $CURRENT_HOME/grantSlave.sql > $CURRENT_HOME/grantSlave.sql-bin 44 | sed -e "s/=445/=$6/g" $CURRENT_HOME/grantSlave.sql-bin > $CURRENT_HOME/grantSlave.sql 45 | 46 | echo "step 4 restart slaves" 47 | for (( i = 0 ; i < ${#SLAVE[@]} ; i++ )) 48 | do 49 | target=${SLAVE[$i]} 50 | echo "restart $target" 51 | scp $CURRENT_HOME/grantSlave.sql root@$target:$SCRIPT_HOME/grantSlave.sql 52 | servernum=$(echo $i+2 | bc) 53 | ssh root@$target "$SCRIPT_HOME/initSlave.sh $MASTER `expr $servernum`" 54 | ssh root@$target "mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD" < $SCRIPT_HOME/grantSlave.sql" 55 | ssh root@$target "rm -rf $SCRIPT_HOME/grantSlave.sql" 56 | echo "$target restarts" 57 | done 58 | 59 | echo "step 5 restart candidates" 60 | for (( i = 0 ; i < ${#CANDIDATE[@]} ; i++ )) 61 | do 62 | target=${CANDIDATE[$i]} 63 | echo "restart $target" 64 | scp $CURRENT_HOME/grantSlave.sql root@$target:$SCRIPT_HOME/grantSlave.sql 65 | servernum=$(echo $i+100 | bc) 66 | ssh root@$target "$SCRIPT_HOME/initSlave.sh $MASTER `expr $servernum`" 67 | ssh root@$target "mysql --user="$MYSQL_USERNAME" --password="$MYSQL_PASSWORD" < $SCRIPT_HOME/grantSlave.sql" 68 | ssh root@$target "rm -rf $SCRIPT_HOME/grantSlave.sql" 69 | echo "$target restarts" 70 | done 71 | 72 | #finally remove the temp files 73 | rm -rf $CURRENT_HOME/grantSlave.sql* 74 | 75 | echo "finish" 76 | 77 | -------------------------------------------------------------------------------- /scripts/my.cnf: -------------------------------------------------------------------------------- 1 | # 2 | # The MySQL database server configuration file. 3 | # 4 | # You can copy this to one of: 5 | # - "/etc/mysql/my.cnf" to set global options, 6 | # - "~/.my.cnf" to set user-specific options. 7 | # 8 | # One can use all long options that the program supports. 9 | # Run program with --help to get a list of available options and with 10 | # --print-defaults to see which it would actually understand and use. 11 | # 12 | # For explanations see 13 | # http://dev.mysql.com/doc/mysql/en/server-system-variables.html 14 | 15 | # This will be passed to all mysql clients 16 | # It has been reported that passwords should be enclosed with ticks/quotes 17 | # escpecially if they contain "#" chars... 18 | # Remember to edit /etc/mysql/debian.cnf when changing the socket location. 19 | [client] 20 | port = 3306 21 | socket = /var/run/mysqld/mysqld.sock 22 | 23 | # Here is entries for some specific programs 24 | # The following values assume you have at least 32M ram 25 | 26 | # This was formally known as [safe_mysqld]. Both versions are currently parsed. 27 | [mysqld_safe] 28 | socket = /var/run/mysqld/mysqld.sock 29 | nice = 0 30 | 31 | [mysqld] 32 | # 33 | # * Basic Settings 34 | # 35 | log-bin=mysql-bin 36 | server-id=1 37 | user = mysql 38 | pid-file = /var/run/mysqld/mysqld.pid 39 | socket = /var/run/mysqld/mysqld.sock 40 | port = 3306 41 | basedir = /usr 42 | datadir = /var/lib/mysql 43 | tmpdir = /tmp 44 | lc-messages-dir = /usr/share/mysql 45 | skip-external-locking 46 | # 47 | # Instead of skip-networking the default is now to listen only on 48 | # localhost which is more compatible and is not less secure. 49 | bind-address = 0.0.0.0 50 | # 51 | # * Fine Tuning 52 | # 53 | key_buffer = 16M 54 | max_allowed_packet = 16M 55 | thread_stack = 192K 56 | thread_cache_size = 8 57 | # This replaces the startup script and checks MyISAM tables if needed 58 | # the first time they are touched 59 | myisam-recover = BACKUP 60 | #max_connections = 100 61 | #table_cache = 64 62 | #thread_concurrency = 10 63 | # 64 | # * Query Cache Configuration 65 | # 66 | query_cache_limit = 1M 67 | query_cache_size = 16M 68 | # 69 | # * Logging and Replication 70 | # 71 | # Both location gets rotated by the cronjob. 72 | # Be aware that this log type is a performance killer. 73 | # As of 5.1 you can enable the log at runtime! 74 | #general_log_file = /var/log/mysql/mysql.log 75 | #general_log = 1 76 | # 77 | # Error log - should be very few entries. 78 | # 79 | log_error = /var/log/mysql/error.log 80 | # 81 | # Here you can see queries with especially long duration 82 | #log_slow_queries = /var/log/mysql/mysql-slow.log 83 | #long_query_time = 2 84 | #log-queries-not-using-indexes 85 | # 86 | # The following can be used as easy to replay backup logs or for replication. 87 | # note: if you are setting up a replication slave, see README.Debian about 88 | # other settings you may need to change. 89 | #server-id = 1 90 | #log_bin = /var/log/mysql/mysql-bin.log 91 | expire_logs_days = 10 92 | max_binlog_size = 100M 93 | #binlog_do_db = include_database_name 94 | #binlog_ignore_db = include_database_name 95 | # 96 | # * InnoDB 97 | # 98 | # InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. 99 | # Read the manual for more InnoDB related options. There are many! 100 | # 101 | # * Security Features 102 | # 103 | # Read the manual, too, if you want chroot! 104 | # chroot = /var/lib/mysql/ 105 | # 106 | # For generating SSL certificates I recommend the OpenSSL GUI "tinyca". 107 | # 108 | # ssl-ca=/etc/mysql/cacert.pem 109 | # ssl-cert=/etc/mysql/server-cert.pem 110 | # ssl-key=/etc/mysql/server-key.pem 111 | 112 | 113 | 114 | [mysqldump] 115 | quick 116 | quote-names 117 | max_allowed_packet = 16M 118 | 119 | [mysql] 120 | #no-auto-rehash # faster start of mysql but no tab completition 121 | 122 | [isamchk] 123 | key_buffer = 16M 124 | 125 | # 126 | # * IMPORTANT: Additional settings that can override those from this file! 127 | # The files must end with '.cnf', otherwise they'll be ignored. 128 | # 129 | !includedir /etc/mysql/conf.d/ 130 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/ParmGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.text.ParseException; 4 | import java.util.Calendar; 5 | import java.util.Random; 6 | 7 | public class ParmGenerator { 8 | Random rd = new Random(); 9 | StringPool sp = new StringPool(); 10 | PopulateTable pt = new PopulateTable(); 11 | TableMetaData tmd = new TableMetaData(); 12 | 13 | // item 14 | public String getItemSubject() { 15 | return sp.subjects[rd.nextInt(sp.subjects.length)]; 16 | } 17 | 18 | public String getItemTitle() { 19 | int count = rd.nextInt(5); 20 | String title = ""; 21 | for (int i = 0; i <= count; i++) { 22 | title += "BA"; // this is base on the wgen 23 | } 24 | return title; 25 | } 26 | 27 | public String getItemPublishDate() throws Exception { 28 | Calendar cal = pt.randomDate(1, 1, 1930); 29 | return getSimpleDate(cal); 30 | } 31 | 32 | public String getItemThumbnail() { 33 | String url = "http://localhost:8080/TPCW/image.jpg"; 34 | int end = rd.nextInt(url.length()); 35 | return url.substring(0, end); 36 | } 37 | 38 | public String getItemID() { 39 | return "" + rd.nextInt(tmd.itemCount); 40 | } 41 | 42 | // author 43 | public String getAuthorLastName() { 44 | int numAuthor = tmd.getRowCount("author"); 45 | String name = pt.A_LNAME(rd.nextInt(numAuthor) + 1, numAuthor); 46 | int end = rd.nextInt(name.length()); 47 | return name.substring(0, end); 48 | } 49 | 50 | public String getAuthorFirstName() { 51 | return pt.randomAstring(3, 20); 52 | } 53 | 54 | public String getAuthorDOB() throws Exception { 55 | Calendar cal = pt.randomDate(1, 1, 1800, 1, 1, 1990); 56 | return getSimpleDate(cal); 57 | } 58 | 59 | // orders 60 | public String getOrderID() { 61 | return "" + rd.nextInt(tmd.ordersCount); 62 | } 63 | 64 | public String getOrderlineDiscount() { 65 | int discount = rd.nextInt(3) + 1; 66 | return "0." + discount; 67 | } 68 | 69 | public int getOrderlineQuanty() { 70 | return pt.randomBetweenInclusive(1, 300); 71 | } 72 | 73 | public String getOrderDate() throws Exception { 74 | Calendar cal = Calendar.getInstance(); 75 | Calendar O_DATE = pt.randomDateAdjust(cal, 76 | -pt.randomBetweenInclusive(0, 7)); 77 | return getSimpleDate(O_DATE); 78 | } 79 | 80 | public float getOrderTotal() { 81 | float O_SUB_TOTAL = pt.randomFloatTwoWithin(10, 0, 9999, 99); 82 | float O_TAX = pt.O_TAX(O_SUB_TOTAL); 83 | return pt.O_TOTAL(O_SUB_TOTAL, O_TAX); 84 | } 85 | 86 | public String getOrderStatus() { 87 | return sp.status[rd.nextInt(sp.status.length)]; 88 | } 89 | 90 | public float getOrderSubtotal() { 91 | return pt.randomFloatTwoWithin(10, 0, 9999, 99); 92 | } 93 | 94 | // cc_xacts 95 | public String getCXType() { 96 | return sp.cxtype[rd.nextInt(sp.cxtype.length)]; 97 | } 98 | 99 | public String getCXName() { 100 | return pt.randomAstring(14, 30); 101 | } 102 | 103 | // customer 104 | 105 | public String getCustomerID() { 106 | return "" + rd.nextInt(tmd.customerCount); 107 | } 108 | 109 | public String getCustomerUserName() { 110 | int numCustomer = tmd.getRowCount("customer"); 111 | String C_UNAME = pt.DigSyl(rd.nextInt(numCustomer) + 1, 0); 112 | int end = rd.nextInt(C_UNAME.length()); 113 | return C_UNAME.substring(0, end); 114 | } 115 | 116 | public String getCustomerSince() throws Exception { 117 | Calendar cal = Calendar.getInstance(); 118 | Calendar C_SINCE = pt.randomDateAdjust(cal, 119 | -(pt.randomBetweenInclusive(1, 173))); 120 | return getSimpleDate(C_SINCE); 121 | } 122 | 123 | public float getCustomerYTDpmt() { 124 | return pt.randomFloatTwoWithin(0, 0, 999, 99); 125 | } 126 | 127 | public int getCustomerBalance() { 128 | return rd.nextInt(100); 129 | } 130 | 131 | public String getCountryCurrency() { 132 | int i = sp.currentExchange.length; 133 | String[] cx = sp.currentExchange[rd.nextInt(i)]; 134 | return cx[2]; 135 | } 136 | 137 | public String getCountryID() { 138 | return "" + rd.nextInt(tmd.countryCount); 139 | } 140 | 141 | public String getCountryName() { 142 | int i = sp.currentExchange.length; 143 | String[] cx = sp.currentExchange[rd.nextInt(i)]; 144 | return cx[0]; 145 | } 146 | 147 | // utility 148 | public String getSimpleDate(Calendar cal) throws ParseException { 149 | return sp.month[cal.get(Calendar.MONTH)] + "/" + cal.get(Calendar.DATE) 150 | + "/" + cal.get(Calendar.YEAR); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/StringPool.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | public class StringPool { 4 | 5 | public String[] syllables = {"BA", "OG", "AL", "RI", "RE", "SE", "AT", "UL", "IN", "NG"}; 6 | 7 | public String[] characters = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z", 8 | "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z", 9 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 10 | "!", "@", "#", "$", "%", "^", "&", "(", ")", "_", "-", "=", "+", "{", "}", "[", "]", "|", ":", ";", ",", ".", "?", "/", "~", " "}; 11 | 12 | public String[] numbers = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; 13 | 14 | public String[] month = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}; 15 | 16 | public String[] shiptype = {"AIR","UPS","FEDEX","SHIP","COURIER","MAIL"}; 17 | 18 | public String[] cxtype = {"VISA","MASTERCARD","DISCOVER","AMEX","DINERS"}; 19 | 20 | public String[] status = {"PROCESSING","SHIPPED","PENDING","DENIED"}; 21 | 22 | public String[] subjects = {"ARTS","BIOGRAPHIES","BUSINESS","CHILDREN","COMPUTERS","COOKING","HEALTH","HISTORY","HOME","HUMOR", 23 | "LITERATURE","MYSTERY","NON-FICTION","PARENTING","POLITICS","REFERENCE","RELIGION","ROMANCE","SELF-HELP","SCIENCE-NATURE", 24 | "SCIENCE-FICTION","SPORTS","YOUTH","TRAVEL"}; 25 | 26 | public String[] backings = {"HARDBACK","PAPERBACK","USED","AUDIO","LIMITED-EDITION"}; 27 | 28 | public String[][] currentExchange = { 29 | {"United States","1","Dollars"},{"United Kingdom","0.625461","Pounds"}, 30 | {"Canada","1.46712","Dollars"},{"Germany","1.86125","Deutsche Marks"}, 31 | {"France","6.24238","Francs"},{"Japan","121.907","Yen"}, 32 | {"Netherlands","2.09715","Guilders"},{"Italy","1842.64","Lira"}, 33 | {"Switzerland","1.51645","Francs"},{"Australia","1.54208","Dollars"}, 34 | {"Algeria","65.3851","Dinars"},{"Argentina","0.998","Pesos"}, 35 | {"Armenia","540.92","Dram"},{"Austria","13.0949","Schillings"}, 36 | {"Azerbaijan","3977","Manat"},{"Bahamas","1","Dollars"}, 37 | {"Bahrain","0.3757","Dinar"},{"Bangla Desh","48.65","Taka"}, 38 | {"Barbados","2","Dollars"},{"Belarus","248000","Rouble"}, 39 | {"Belgium","38.3892","Francs"},{"Bermuda","1","Dollars"}, 40 | {"Bolivia","5.74","Boliviano"},{"Botswana","4.7304","Pula"}, 41 | {"Brazil","1.71","Real"},{"Bulgaria","1846","Lev"}, 42 | {"Cayman Islands","0.8282","Dollars"},{"Chad","627.1999","Franc"}, 43 | {"Chile","494.2","Pesos"},{"China","8.278","Yuan Renmimbi"}, 44 | {"Christmas Island","1.5391","Dollars"},{"Colombia","1677","Pesos"}, 45 | {"Croatia","7.3044","Kuna"},{"Cuba","23","Pesos"}, 46 | {"Cyprus","0.543","Pounds"},{"Czech Republic","36.0127","Koruna"}, 47 | {"Denmark","7.0707","Kroner"},{"Dominican Republic","15.8","Pesos"}, 48 | {"Eastern Caribbean","2.7","Dollars"},{"Ecuador","9600","Sucre"}, 49 | {"Egypt","3.33771","Pounds"},{"El Salvador","8.7","Colon"}, 50 | {"Estonia","14.9912","Kroon"},{"Ethiopia","7.7","Birr"}, 51 | {"Falkland Island","0.6255","Pound"},{"Faroe Island","7.124","Krone"}, 52 | {"Fiji","1.9724","Dollars"},{"Finland","5.65822","Markka"}, 53 | {"Gabon","627.1999","Franc"},{"Gibraltar","0.6255","Pound"}, 54 | {"Greece","309.214","Drachmas"},{"Guam","1","Dollars"}, 55 | {"Hong Kong","7.75473","Dollars"},{"Hungary","237.23","Forint"}, 56 | {"Iceland","74.147","Krona"},{"India","42.75","Rupees"}, 57 | {"Indonesia","8100","Rupiah"},{"Iran","3000","Rial"}, 58 | {"Iraq","0.3083","Dinar"},{"Ireland","0.749481","Punt"}, 59 | {"Israel","4.12","Shekels"},{"Jamaica","37.4","Dollars"}, 60 | {"Jordan","0.708","Dinar"},{"Kazakhstan","150","Tenge"}, 61 | {"Kuwait","0.3062","Dinar"},{"Lebanon","1502","Pounds"}, 62 | {"Luxembourg","38.3892","Francs"},{"Malaysia","3.8","Ringgit"}, 63 | {"Mexico","9.6287","Pesos"},{"Mauritius","25.245","Rupees"}, 64 | {"New Zealand","1.87539","Dollars"},{"Norway","7.83101","Kroner"}, 65 | {"Pakistan","52","Rupees"},{"Philippines","37.8501","Pesos"}, 66 | {"Poland","3.9525","Zloty"},{"Portugal","190.788","Escudo"}, 67 | {"Romania","15180.2","Leu"},{"Russia","24.43","Rubles"}, 68 | {"Saudi Arabia","3.7501","Riyal"},{"Singapore","1.72929","Dollars"}, 69 | {"Slovakia","43.9642","Koruna"},{"South Africa","6.25845","Rand"}, 70 | {"South Korea","1190.15","Won"},{"Spain","158.34","Pesetas"}, 71 | {"Sudan","5.282","Dinar"},{"Sweden","8.54477","Krona"}, 72 | {"Taiwan","32.77","Dollars"},{"Thailand","37.1414","Baht"}, 73 | {"Trinidad","6.1764","Dollars"},{"Turkey","401500","Lira"}, 74 | {"Venezuela","596","Bolivar"},{"Zambia","2447.7","Kwacha"}}; 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/TableMetaData.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | public class TableMetaData { 4 | // table attributes 5 | public String[] itemAtts = { "i_id number", "i_title", "i_a_id", 6 | "i_pub_date", "i_publisher", "i_subject", "i_desc", "i_related1", 7 | "i_related2", "i_related3", "i_related4", "i_related5", 8 | "i_thumbnail", "i_image", "i_srp", "i_cost", "i_avail", "i_stock", 9 | "i_isbn", "i_page", "i_backing", "i_dimentions" }; 10 | public String[] authorAtts = { "a_id", "a_fname", "a_lname", "a_mname", 11 | "a_dob", "a_bio" }; 12 | public String[] orderLineAtts = { "ol_id", "ol_o_id", "ol_i_id", "ol_qty", 13 | "ol_discount", "ol_comment" }; 14 | public String[] ccXactsAtts = { "cx_o_id", "cx_type", "cx_num", "cx_name", 15 | "cx_expiry", "cx_auth_id", "cx_xact_amt", "cx_xact_date", 16 | "cx_co_id" }; 17 | public String[] ordersAtts = { "o_id", "o_c_id", "o_date", "o_sub_total", 18 | "o_tax", "o_total", "o_ship_type", "o_ship_date", "o_bill_addr_id", 19 | "o_ship_addr_id", "o_status" }; 20 | public String[] countryAtts = { "co_id", "co_name", "co_exchange", 21 | "co_currency" }; 22 | public String[] customerAtts = { "c_id", "c_uname", "c_passwd", "c_fname", 23 | "c_lname", "c_addr_id", "c_phone", "c_email", "c_since", 24 | "c_last_visit", "c_login", "c_expiration", "c_discount", 25 | "c_balance", "c_ytd_pmt", "c_birthdate", "c_data" }; 26 | public String[] addressAtts = { "addr_id", "addr_street1", "addr_street2", 27 | "addr_city", "addr_state", "addr_zip", "addr_co_id" }; 28 | 29 | // table tow count 30 | // [java] Populating ADDRESS Table with 576000 addresses 31 | // [java] Complete (in 10,000's): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 32 | // 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 33 | // 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 34 | // [java] Populating AUTHOR Table with 2500 authors 35 | // [java] Populating COUNTRY with 92 countries 36 | // [java] Populating CUSTOMER Table with 288000 customers 37 | // [java] Complete (in 10,000's): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 38 | // 18 19 20 21 22 23 24 25 26 27 28 39 | // [java] Populating ITEM table with 10000 items 40 | // [java] Populating ORDERS, ORDER_LINES, CC_XACTS with 259200 orders 41 | // [java] Complete (in 10,000's): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 42 | // 18 19 20 21 22 23 24 25 43 | // [java] Adding Indexes 44 | // [java] Done 45 | public int itemCount = 10000; 46 | public int authorCount = 2500; 47 | public int orderLineCount = 777342; //503344; 48 | public int ccXactsCount = 259200; //126000; 49 | public int countryCount = 92; 50 | public int customerCount = 288000; // 140000; 51 | public int addressCount = 57600; 52 | public int ordersCount = 126000; 53 | 54 | public int getRowCount(String tname) { 55 | if (tname.equalsIgnoreCase("item")) 56 | return itemCount; 57 | else if (tname.equalsIgnoreCase("author")) 58 | return authorCount; 59 | else if (tname.equalsIgnoreCase("order_line")) 60 | return orderLineCount; 61 | else if (tname.equalsIgnoreCase("cc_xacts")) 62 | return ccXactsCount; 63 | else if (tname.equalsIgnoreCase("country")) 64 | return countryCount; 65 | else if (tname.equalsIgnoreCase("customer")) 66 | return customerCount; 67 | else if (tname.equalsIgnoreCase("address")) 68 | return addressCount; 69 | else if (tname.equalsIgnoreCase("orders")) 70 | return ordersCount; 71 | else 72 | return 0; 73 | } 74 | 75 | public String[] getTableAtts(String tname) { 76 | if (tname.equalsIgnoreCase("item")) 77 | return itemAtts; 78 | else if (tname.equalsIgnoreCase("author")) 79 | return authorAtts; 80 | else if (tname.equalsIgnoreCase("order_line")) 81 | return orderLineAtts; 82 | else if (tname.equalsIgnoreCase("cc_xacts")) 83 | return ccXactsAtts; 84 | else if (tname.equalsIgnoreCase("country")) 85 | return countryAtts; 86 | else if (tname.equalsIgnoreCase("customer")) 87 | return customerAtts; 88 | else if (tname.equalsIgnoreCase("address")) 89 | return addressAtts; 90 | else if (tname.equalsIgnoreCase("orders")) 91 | return ordersAtts; 92 | else 93 | return null; 94 | } 95 | 96 | public String getTableByAtts(String atts) { 97 | if (atts.startsWith("i_")) 98 | return "item"; 99 | else if (atts.startsWith("a_")) 100 | return "author"; 101 | else if (atts.startsWith("ol_")) 102 | return "order_line"; 103 | else if (atts.startsWith("cx_")) 104 | return "cc_xacts"; 105 | else if (atts.startsWith("co_")) 106 | return "country"; 107 | else if (atts.startsWith("c_")) 108 | return "customer"; 109 | else if (atts.startsWith("addr_")) 110 | return "address"; 111 | else if (atts.startsWith("o_")) 112 | return "orders"; 113 | else 114 | return null; 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/logic/Monitor.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.logic; 2 | 3 | import java.sql.Connection; 4 | import java.sql.DriverManager; 5 | import java.sql.Statement; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Vector; 9 | 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import com.bittiger.client.ClientEmulator; 14 | import com.bittiger.client.Utilities; 15 | import com.bittiger.querypool.CleanStatsQuery; 16 | import com.bittiger.querypool.StatsQuery; 17 | 18 | /** 19 | * We do not need strong consistency for stats in the monitor 20 | * 21 | */ 22 | public class Monitor { 23 | 24 | public final Vector read; 25 | public final Vector write; 26 | public final Vector notAvailable; 27 | private ClientEmulator c; 28 | Connection con; 29 | 30 | private static transient final Logger LOG = LoggerFactory 31 | .getLogger(Monitor.class); 32 | 33 | public Monitor(ClientEmulator c) { 34 | read = new Vector(); 35 | write = new Vector(); 36 | notAvailable = new Vector(); 37 | this.c = c; 38 | } 39 | 40 | public void init() { 41 | try { 42 | Class.forName("com.mysql.jdbc.Driver").newInstance(); 43 | con = DriverManager.getConnection( 44 | Utilities.getStatsUrl(c.getTpcw().writeQueue[0]), 45 | c.getTpcw().username, c.getTpcw().password); 46 | con.setAutoCommit(true); 47 | try { 48 | Statement stmt = con.createStatement(); 49 | CleanStatsQuery clean = new CleanStatsQuery(); 50 | stmt.executeUpdate(clean.getQueryStr()); 51 | stmt.close(); 52 | LOG.info("Clean stats at server " + c.getTpcw().writeQueue[0]); 53 | } catch (Exception e) { 54 | LOG.error(e.toString()); 55 | } 56 | } catch (Exception e) { 57 | LOG.error(e.toString()); 58 | } 59 | } 60 | 61 | private void updateStats(double x, double u, double r, double w, double m, double s) { 62 | try { 63 | Statement stmt = con.createStatement(); 64 | StatsQuery stats = new StatsQuery(x, u, r, w, m, s); 65 | stmt.executeUpdate(stats.getQueryStr()); 66 | stmt.close(); 67 | LOG.info("Stats: Interval:" + x + ", Queries:" + u + ", Read:" + r + ", Write:" + w + ", Nodes:" + m + ", Sessions:" + s); 68 | } catch (Exception e) { 69 | LOG.error(e.toString()); 70 | } 71 | } 72 | 73 | public void close() { 74 | try { 75 | con.close(); 76 | } catch (Exception e) { 77 | LOG.error(e.toString()); 78 | } 79 | } 80 | 81 | public void addQuery(int sessionId, String type, long start, 82 | long end) { 83 | // int id = Integer.parseInt(name.substring(name.indexOf("n") + 1)); 84 | Stats stat = new Stats(sessionId, type, start, end); 85 | if (end > 0) { 86 | if (type.contains("b")) { 87 | read.add(stat); 88 | } else { 89 | write.add(stat); 90 | } 91 | } else { 92 | notAvailable.add(stat); 93 | } 94 | LOG.debug(stat.toString()); 95 | } 96 | 97 | public String readPerformance() { 98 | StringBuffer perf = new StringBuffer(); 99 | long currTime = System.currentTimeMillis(); 100 | long validStartTime = Math.max(c.getStartTime() + c.getTpcw().warmup, 101 | currTime - c.getTpcw().interval); 102 | long validEndTime = Math.min( 103 | c.getStartTime() + c.getTpcw().warmup + c.getTpcw().mi, 104 | currTime); 105 | 106 | long totalTime = 0; 107 | int count = 0; 108 | int totCount = 0; 109 | double avgRead = 0.0; 110 | double avgWrite = 0.0; 111 | for (int i = 0; i < read.size(); i++) { 112 | Stats s = read.get(i); 113 | if ((validStartTime < s.start) && (s.start < validEndTime)) { 114 | count += 1; 115 | totalTime += s.duration; 116 | } 117 | } 118 | perf.append("R:" + count + ":" + totalTime); 119 | if (count > 0) { 120 | avgRead = totalTime / count; 121 | perf.append(":" + avgRead); 122 | } else { 123 | perf.append(":NA"); 124 | } 125 | totCount += count; 126 | 127 | totalTime = 0; 128 | count = 0; 129 | for (int i = 0; i < write.size(); i++) { 130 | Stats s = write.get(i); 131 | if ((validStartTime < s.start) && (s.start < validEndTime)) { 132 | count += 1; 133 | totalTime += s.duration; 134 | } 135 | } 136 | perf.append(",W:" + count + ":" + totalTime); 137 | if (count > 0) { 138 | avgWrite = totalTime / count; 139 | perf.append(":" + avgWrite); 140 | } else { 141 | perf.append(":NA"); 142 | } 143 | totCount += count; 144 | 145 | totalTime = 0; 146 | count = 0; 147 | for (int i = 0; i < notAvailable.size(); i++) { 148 | Stats s = notAvailable.get(i); 149 | if ((validStartTime < s.start) && (s.start < validEndTime)) { 150 | count += 1; 151 | totalTime += s.duration; 152 | } 153 | } 154 | perf.append(",NA:" + count + ":" + totalTime); 155 | if (count > 0) { 156 | perf.append(":" + totalTime / count); 157 | } else { 158 | perf.append(":NA"); 159 | } 160 | totCount += count; 161 | 162 | int x = (int) ((currTime - c.getStartTime()) / c.getTpcw().interval); 163 | updateStats(x, totCount, avgRead, avgWrite, 164 | c.getLoadBalancer().getReadQueue().size(), c.getcurrNumSessionsStats()); 165 | return perf.toString(); 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/client/TPCWProperties.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.client; 2 | 3 | import java.util.Arrays; 4 | import java.util.ResourceBundle; 5 | import java.util.StringTokenizer; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class TPCWProperties { 11 | 12 | private static ResourceBundle configuration = null; 13 | // Information about Workload 14 | public int workloads[]; 15 | public double rate[]; 16 | public double mixRate; 17 | public double TPCmean; 18 | public long warmup; 19 | public long mi; 20 | public long warmdown; 21 | public long interval; 22 | 23 | public double rwratio; 24 | public double read[]; 25 | public double write[]; 26 | 27 | // Information about server 28 | public String writeQueue[]; 29 | public String readQueue[]; 30 | public String candidateQueue[]; 31 | 32 | public String username; 33 | public String password; 34 | 35 | public int destroyerSleepInterval; 36 | public String destroyTarget; 37 | 38 | private static transient final Logger LOG = LoggerFactory 39 | .getLogger(TPCWProperties.class); 40 | 41 | public TPCWProperties(String fileName) { 42 | try { 43 | configuration = ResourceBundle.getBundle(fileName); 44 | checkPropertiesFileAndGetURLGenerator(); 45 | } catch (java.util.MissingResourceException e) { 46 | System.err 47 | .println("No properties file has been found in your classpath.

"); 48 | Runtime.getRuntime().exit(1); 49 | } 50 | } 51 | 52 | protected String getProperty(String property) { 53 | return configuration.getString(property); 54 | } 55 | 56 | public void checkPropertiesFileAndGetURLGenerator() { 57 | try { 58 | username = getProperty("username"); 59 | password = getProperty("password"); 60 | destroyerSleepInterval = Integer.parseInt(getProperty("destroyerSleepInterval")); 61 | destroyTarget = getProperty("destroyTarget"); 62 | mixRate = Double.parseDouble(getProperty("mixRate")); 63 | TPCmean = Double.parseDouble(getProperty("TPCmean")); 64 | warmup = Long.parseLong(getProperty("warmup")); 65 | warmdown = Long.parseLong(getProperty("warmdown")); 66 | mi = Long.parseLong(getProperty("mi")); 67 | interval = Long.parseLong(getProperty("interval")); 68 | 69 | StringTokenizer rl = null; 70 | int rlCnt = 0; 71 | rl = new StringTokenizer(getProperty("rate_vector"), ","); 72 | rate = new double[rl.countTokens()]; 73 | while (rl.hasMoreTokens()) { 74 | rate[rlCnt] = Double.parseDouble(rl.nextToken().trim()); 75 | rlCnt++; 76 | } 77 | // LOG.info("rate is " + Arrays.toString(rate)); 78 | 79 | StringTokenizer wl = new StringTokenizer( 80 | getProperty("workload_vector"), ","); 81 | workloads = new int[wl.countTokens()]; 82 | int wlCnt = 0; 83 | while (wl.hasMoreTokens()) { 84 | workloads[wlCnt] = Integer.parseInt(wl.nextToken().trim()); 85 | wlCnt++; 86 | } 87 | LOG.info("workloads is " + Arrays.toString(workloads)); 88 | 89 | if (workloads.length * interval != warmup + warmdown + mi) { 90 | LOG.error("workload length can not match warm up/down + mi"); 91 | Runtime.getRuntime().exit(0); 92 | } 93 | 94 | rwratio = Double.parseDouble(getProperty("rwratio")); 95 | 96 | rl = new StringTokenizer(getProperty("read"), ","); 97 | read = new double[rl.countTokens()]; 98 | rlCnt = 0; 99 | while (rl.hasMoreTokens()) { 100 | read[rlCnt] = Double.parseDouble(rl.nextToken().trim()); 101 | rlCnt++; 102 | } 103 | LOG.info("read is " + Arrays.toString(read)); 104 | 105 | rl = new StringTokenizer(getProperty("write"), ","); 106 | write = new double[rl.countTokens()]; 107 | rlCnt = 0; 108 | while (rl.hasMoreTokens()) { 109 | write[rlCnt] = Double.parseDouble(rl.nextToken().trim()); 110 | rlCnt++; 111 | } 112 | LOG.info("write is " + Arrays.toString(write)); 113 | 114 | rl = new StringTokenizer(getProperty("readQueue"), ","); 115 | readQueue = new String[rl.countTokens()]; 116 | rlCnt = 0; 117 | while (rl.hasMoreTokens()) { 118 | readQueue[rlCnt] = rl.nextToken().trim(); 119 | rlCnt++; 120 | } 121 | LOG.info("readQueue is " + Arrays.toString(readQueue)); 122 | 123 | 124 | rl = new StringTokenizer(getProperty("writeQueue"), ","); 125 | writeQueue = new String[rl.countTokens()]; 126 | rlCnt = 0; 127 | while (rl.hasMoreTokens()) { 128 | writeQueue[rlCnt] = rl.nextToken().trim(); 129 | rlCnt++; 130 | } 131 | LOG.info("writeQueue is " + Arrays.toString(writeQueue)); 132 | 133 | rl = new StringTokenizer(getProperty("candidateQueue"), ","); 134 | candidateQueue = new String[rl.countTokens()]; 135 | rlCnt = 0; 136 | while (rl.hasMoreTokens()) { 137 | candidateQueue[rlCnt] = rl.nextToken().trim(); 138 | rlCnt++; 139 | } 140 | LOG.info("candidateQueue is " + Arrays.toString(candidateQueue)); 141 | 142 | 143 | } catch (Exception e) { 144 | System.err.println("Error while checking properties: " 145 | + e.getMessage()); 146 | Runtime.getRuntime().exit(0); 147 | } 148 | } 149 | 150 | public static ResourceBundle getConfiguration() { 151 | return configuration; 152 | } 153 | 154 | public static void setConfiguration(ResourceBundle configuration) { 155 | TPCWProperties.configuration = configuration; 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/client/UserSession.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.client; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.BlockingQueue; 5 | import java.sql.Connection; 6 | import java.sql.DriverManager; 7 | import java.sql.SQLException; 8 | import java.sql.Statement; 9 | 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import com.bittiger.logic.LoadBalancer; 14 | import com.bittiger.logic.Server; 15 | import com.bittiger.querypool.QueryMetaData; 16 | 17 | public class UserSession extends Thread { 18 | private TPCWProperties tpcw = null; 19 | private ClientEmulator client = null; 20 | private Random rand = null; 21 | private boolean suspendThread = false; 22 | private BlockingQueue queue; 23 | private int id; 24 | 25 | private Connection writeConn; 26 | 27 | private static transient final Logger LOG = LoggerFactory 28 | .getLogger(ClientEmulator.class); 29 | 30 | public UserSession(int id, ClientEmulator client, 31 | BlockingQueue bQueue) { 32 | super("UserSession" + id); 33 | this.id = id; 34 | this.queue = bQueue; 35 | this.client = client; 36 | this.tpcw = client.getTpcw(); 37 | this.rand = new Random(); 38 | } 39 | 40 | private long TPCWthinkTime(double mean) { 41 | double r = rand.nextDouble(); 42 | return ((long) (((0 - mean) * Math.log(r)))); 43 | } 44 | 45 | public synchronized void notifyThread() { 46 | notify(); 47 | } 48 | 49 | public synchronized void releaseThread() { 50 | suspendThread = false; 51 | } 52 | 53 | public synchronized void holdThread() { 54 | suspendThread = true; 55 | } 56 | 57 | private String computeNextSql(double rwratio, double[] read, double[] write) { 58 | String sql = ""; 59 | // first decide read or write 60 | double rw = rand.nextDouble(); 61 | if (rw < rwratio) { 62 | sql += "bq"; 63 | double internal = rand.nextDouble(); 64 | int num = 0; 65 | for (int i = 0; i < read.length - 1; i++) { 66 | if (read[i] < internal && internal <= read[i + 1]) { 67 | num = i + 1; 68 | sql += num; 69 | break; 70 | } 71 | } 72 | 73 | } else { 74 | sql += "wq"; 75 | double internal = rand.nextDouble(); 76 | int num = 0; 77 | for (int i = 0; i < write.length - 1; i++) { 78 | if (write[i] < internal && internal <= write[i + 1]) { 79 | num = i + 1; 80 | sql += num; 81 | break; 82 | } 83 | } 84 | } 85 | return sql; 86 | } 87 | 88 | private Connection getNextConnection(String sql) { 89 | // read 90 | if (sql.contains("b")) { 91 | return getNextReadConnection(client.getLoadBalancer()); 92 | } else { 93 | if (writeConn == null) { 94 | writeConn = getNextWriteConnection(client.getLoadBalancer()); 95 | } 96 | return writeConn; 97 | } 98 | } 99 | 100 | public Connection getNextWriteConnection(LoadBalancer loadBalancer) { 101 | Server server = null; 102 | Connection connection = null; 103 | try { 104 | Class.forName("com.mysql.jdbc.Driver").newInstance(); 105 | // DriverManager.setLoginTimeout(5); 106 | server = loadBalancer.getWriteQueue(); 107 | connection = (Connection) DriverManager.getConnection( 108 | Utilities.getUrl(server), client.getTpcw().username, 109 | client.getTpcw().password); 110 | connection.setAutoCommit(true); 111 | } catch (Exception e) { 112 | LOG.error(e.toString()); 113 | } 114 | LOG.debug("choose write server as " + server.getIp()); 115 | return connection; 116 | } 117 | 118 | public Connection getNextReadConnection(LoadBalancer loadBalancer) { 119 | Server server = null; 120 | Connection connection = null; 121 | while (connection == null) { 122 | int tryTime = 0; 123 | server = loadBalancer.getNextReadServer(); 124 | while (connection == null && tryTime++ < Utilities.retryTimes) { 125 | try { 126 | Class.forName("com.mysql.jdbc.Driver").newInstance(); 127 | connection = (Connection) DriverManager.getConnection( 128 | Utilities.getUrl(server), 129 | client.getTpcw().username, 130 | client.getTpcw().password); 131 | connection.setAutoCommit(true); 132 | } catch (Exception e) { 133 | LOG.error(e.toString()); 134 | } 135 | } 136 | if (connection == null) { 137 | LOG.error(server.getIp() + " is down. "); 138 | loadBalancer.getReadQueue().remove(server); 139 | loadBalancer.detectFailure(); 140 | } else { 141 | // LOG.debug("choose read server as " + server.getIp()); 142 | return connection; 143 | } 144 | } 145 | return null; 146 | } 147 | 148 | public void run() { 149 | while (!client.isEndOfSimulation()) { 150 | try { 151 | synchronized (this) { 152 | while (suspendThread) 153 | wait(); 154 | } 155 | // decide of closed or open system 156 | double r = rand.nextDouble(); 157 | if (r < tpcw.mixRate) { 158 | int t = queue.take(); 159 | LOG.debug(t + " has been taken"); 160 | } else { 161 | Thread.sleep((long) ((float) TPCWthinkTime(tpcw.TPCmean))); 162 | } 163 | 164 | String queryclass = computeNextSql(tpcw.rwratio, tpcw.read, 165 | tpcw.write); 166 | Connection connection = getNextConnection(queryclass); 167 | String classname = "com.bittiger.querypool." + queryclass; 168 | QueryMetaData query = (QueryMetaData) Class.forName(classname) 169 | .newInstance(); 170 | String command = query.getQueryStr(); 171 | 172 | Statement stmt = connection.createStatement(); 173 | if (queryclass.contains("b")) { 174 | long start = System.currentTimeMillis(); 175 | stmt.executeQuery(command); 176 | long end = System.currentTimeMillis(); 177 | client.getMonitor().addQuery(this.id, queryclass, start, 178 | end); 179 | stmt.close(); 180 | connection.close(); 181 | } else { 182 | long start = System.currentTimeMillis(); 183 | stmt.executeUpdate(command); 184 | long end = System.currentTimeMillis(); 185 | client.getMonitor().addQuery(this.id, queryclass, start, 186 | end); 187 | stmt.close(); 188 | } 189 | } catch (Exception ex) { 190 | LOG.error("Error while running session: " + ex.getMessage()); 191 | } 192 | } 193 | try { 194 | if (writeConn != null) { 195 | writeConn.close(); 196 | } 197 | } catch (SQLException ex) { 198 | LOG.error("Error while close connection " + ex.getMessage()); 199 | } 200 | client.increaseThread(); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/client/ClientEmulator.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.client; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Timer; 6 | import java.util.concurrent.BlockingQueue; 7 | import java.util.concurrent.LinkedBlockingQueue; 8 | import java.io.IOException; 9 | 10 | import org.kohsuke.args4j.Argument; 11 | import org.kohsuke.args4j.CmdLineException; 12 | import org.kohsuke.args4j.CmdLineParser; 13 | import org.kohsuke.args4j.Option; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | import com.bittiger.logic.ActionType; 18 | import com.bittiger.logic.Controller; 19 | import com.bittiger.logic.Destroyer; 20 | import com.bittiger.logic.EventQueue; 21 | import com.bittiger.logic.Executor; 22 | import com.bittiger.logic.LoadBalancer; 23 | import com.bittiger.logic.Monitor; 24 | 25 | public class ClientEmulator { 26 | 27 | @Option(name = "-c", usage = "enable controller") 28 | private boolean enableController; 29 | @Option(name = "-d", usage = "enable destroyer") 30 | private boolean enableDestroyer; 31 | // receives other command line parameters than options 32 | @Argument 33 | private List arguments = new ArrayList(); 34 | 35 | private TPCWProperties tpcw = null; 36 | private int numOfRunningThreads = 0; 37 | private boolean endOfSimulation = false; 38 | private Monitor monitor; 39 | private Controller controller; 40 | private Executor executor; 41 | private Destroyer destroyer; 42 | private LoadBalancer loadBalancer; 43 | OpenSystemTicketProducer producer; 44 | EventQueue eventQueue = null; 45 | private long startTime; 46 | private int currNumSessionsStats = 0; 47 | 48 | private static transient final Logger LOG = LoggerFactory 49 | .getLogger(ClientEmulator.class); 50 | 51 | public ClientEmulator() throws IOException, InterruptedException { 52 | super(); 53 | tpcw = new TPCWProperties("tpcw"); 54 | eventQueue = new EventQueue(); 55 | } 56 | 57 | public synchronized void increaseThread() { 58 | numOfRunningThreads++; 59 | } 60 | 61 | private synchronized void setEndOfSimulation() { 62 | endOfSimulation = true; 63 | LOG.info("Trigger ClientEmulator.isEndOfSimulation()= " 64 | + this.isEndOfSimulation()); 65 | 66 | } 67 | 68 | public synchronized boolean isEndOfSimulation() { 69 | return endOfSimulation; 70 | } 71 | 72 | public void start(String[] args) { 73 | CmdLineParser parser = new CmdLineParser(this); 74 | try { 75 | // parse the arguments. 76 | parser.parseArgument(args); 77 | // you can parse additional arguments if you want. 78 | // parser.parseArgument("more","args"); 79 | } catch (CmdLineException e) { 80 | // if there's a problem in the command line, 81 | // you'll get this exception. this will report 82 | // an error message. 83 | System.err.println(e.getMessage()); 84 | System.err.println("java ClientEmulator [-c -d]"); 85 | // print the list of available options 86 | parser.printUsage(System.err); 87 | System.err.println(); 88 | return; 89 | } 90 | 91 | if (enableController) 92 | LOG.info("-c flag is set"); 93 | 94 | if (enableDestroyer) 95 | LOG.info("-d flag is set"); 96 | 97 | long warmup = tpcw.warmup; 98 | long mi = tpcw.mi; 99 | long warmdown = tpcw.warmdown; 100 | this.startTime = System.currentTimeMillis(); 101 | int maxNumSessions = 0; 102 | int workloads[] = tpcw.workloads; 103 | for (int i = 0; i < workloads.length; i++) { 104 | if (workloads[i] > maxNumSessions) { 105 | maxNumSessions = workloads[i]; 106 | } 107 | } 108 | LOG.info("The maximum is : " + maxNumSessions); 109 | BlockingQueue bQueue = new LinkedBlockingQueue(); 110 | 111 | // Each usersession is a user 112 | //不管怎样,先把所有的session都开了,遇到用不上max的时候就先block掉,关掉。 113 | UserSession[] sessions = new UserSession[maxNumSessions]; 114 | for (int i = 0; i < maxNumSessions; i++) { 115 | sessions[i] = new UserSession(i, this, bQueue); 116 | sessions[i].holdThread(); 117 | sessions[i].start(); 118 | } 119 | 120 | int currNumSessions = 0; 121 | int currWLInx = 0; 122 | int diffWL = 0; 123 | 124 | long endTime = startTime + warmup + mi + warmdown; 125 | long currTime; 126 | 127 | // producer is for semi-open and open models 128 | // it shares a bQueue with all the usersessions. 129 | if (tpcw.mixRate > 0) { 130 | producer = new OpenSystemTicketProducer(this, bQueue); 131 | producer.start(); 132 | } 133 | 134 | this.monitor = new Monitor(this); 135 | this.monitor.init(); 136 | Timer timer = null; 137 | if (enableController) { 138 | this.controller = new Controller(this); 139 | timer = new Timer(); 140 | timer.schedule(this.controller, warmup, tpcw.interval); 141 | this.executor = new Executor(this); 142 | this.executor.start(); 143 | if(enableDestroyer){ 144 | destroyer = new Destroyer(this); 145 | destroyer.start(); 146 | } 147 | } 148 | this.loadBalancer = new LoadBalancer(this); 149 | LOG.info("Client starts......"); 150 | while (true) { 151 | currTime = System.currentTimeMillis(); 152 | if (currTime >= endTime) { 153 | // when it reaches endTime, it ends. 154 | break; 155 | } 156 | diffWL = workloads[currWLInx] - currNumSessions; 157 | LOG.info("Workload......" + workloads[currWLInx]); 158 | if (diffWL > 0) { 159 | for (int i = currNumSessions; i < (currNumSessions + diffWL); i++) { 160 | sessions[i].releaseThread(); 161 | sessions[i].notifyThread(); 162 | } 163 | } else if (diffWL < 0) { 164 | for (int i = (currNumSessions - 1); i > workloads[currWLInx]; i--) { 165 | sessions[i].holdThread(); 166 | } 167 | } 168 | try { 169 | LOG.info("Client emulator sleep......" + tpcw.interval); 170 | Thread.sleep(tpcw.interval); 171 | } catch (InterruptedException ie) { 172 | LOG.error("ERROR:InterruptedException" + ie.toString()); 173 | } 174 | currNumSessions = workloads[currWLInx]; 175 | this.currNumSessionsStats = currNumSessions; 176 | currWLInx = ((currWLInx + 1) % workloads.length); 177 | } 178 | setEndOfSimulation(); 179 | for (int i = 0; i < maxNumSessions; i++) { 180 | sessions[i].releaseThread(); 181 | sessions[i].notifyThread(); 182 | } 183 | LOG.info("Client: Shutting down threads ..."); 184 | for (int i = 0; i < maxNumSessions; i++) { 185 | try { 186 | LOG.info("UserSession " + i + " joins."); 187 | sessions[i].join(); 188 | } catch (java.lang.InterruptedException ie) { 189 | LOG.error("ClientEmulator: Thread " + i 190 | + " has been interrupted."); 191 | } 192 | } 193 | if (tpcw.mixRate > 0) { 194 | try { 195 | producer.join(); 196 | LOG.info("Producer joins"); 197 | } catch (java.lang.InterruptedException ie) { 198 | LOG.error("Producer has been interrupted."); 199 | } 200 | } 201 | if (enableController) { 202 | timer.cancel(); 203 | this.eventQueue.put(ActionType.NoOp); 204 | try { 205 | executor.join(); 206 | LOG.info("Executor joins"); 207 | if(enableDestroyer){ 208 | destroyer.join(); 209 | LOG.info("Destroyer joins"); 210 | } 211 | } catch (java.lang.InterruptedException ie) { 212 | LOG.error("Executor/Destroyer has been interrupted."); 213 | } 214 | } 215 | this.monitor.close(); 216 | LOG.info("Done\n"); 217 | Runtime.getRuntime().exit(0); 218 | } 219 | 220 | public int getcurrNumSessionsStats() { 221 | return this.currNumSessionsStats; 222 | } 223 | 224 | public Monitor getMonitor() { 225 | return monitor; 226 | } 227 | 228 | public void setMonitor(Monitor monitor) { 229 | this.monitor = monitor; 230 | } 231 | 232 | public Controller getController() { 233 | return controller; 234 | } 235 | 236 | public void setController(Controller controller) { 237 | this.controller = controller; 238 | } 239 | 240 | public TPCWProperties getTpcw() { 241 | return tpcw; 242 | } 243 | 244 | public void setTpcw(TPCWProperties tpcw) { 245 | this.tpcw = tpcw; 246 | } 247 | 248 | public long getStartTime() { 249 | return startTime; 250 | } 251 | 252 | public void setStartTime(long startTime) { 253 | this.startTime = startTime; 254 | } 255 | 256 | public LoadBalancer getLoadBalancer() { 257 | return loadBalancer; 258 | } 259 | 260 | public void setLoadBalancer(LoadBalancer loadBalancer) { 261 | this.loadBalancer = loadBalancer; 262 | } 263 | 264 | public EventQueue getEventQueue() { 265 | return eventQueue; 266 | } 267 | 268 | public void setEventQueue(EventQueue eventQueue) { 269 | this.eventQueue = eventQueue; 270 | } 271 | 272 | public static void main(String[] args) throws IOException, 273 | InterruptedException { 274 | ClientEmulator client = new ClientEmulator(); 275 | client.start(args); 276 | } 277 | 278 | } 279 | -------------------------------------------------------------------------------- /src/main/java/com/bittiger/querypool/PopulateTable.java: -------------------------------------------------------------------------------- 1 | package com.bittiger.querypool; 2 | 3 | import java.io.*; 4 | import java.sql.*; 5 | import java.text.ParseException; 6 | import java.text.SimpleDateFormat; 7 | import java.util.ArrayList; 8 | import java.util.Calendar; 9 | import java.util.List; 10 | import java.util.Random; 11 | 12 | public class PopulateTable { 13 | 14 | StringPool sp = new StringPool(); // StringPool 15 | // row number variables 16 | int numCountry = 0; 17 | int numAuthor = 0; 18 | int numAddress = 0; 19 | int numItem = 0; 20 | int numCustomer = 0; 21 | int numOrders = 0; 22 | int numCCX = 0; 23 | int numOL = 0; 24 | int numEB = 0; 25 | String url = "http://localhost:8080/TPCW/image.jpg"; // for I_THUMBNAIL and 26 | // I_IMAGE 27 | Connection conn; 28 | String sql = null; 29 | Random rd = new Random(); 30 | List O_TOTAL_LIST = new ArrayList(); 31 | List O_SHIP_DATE_LIST = new ArrayList(); 32 | List I_ITEM_LIST = new ArrayList(); 33 | 34 | public PopulateTable() { 35 | } 36 | 37 | public PopulateTable(int eb, int item, int country, int author, 38 | int customer, int orders, int ol, int ccx, int address, 39 | Connection conn) throws SQLException { 40 | this.numEB = eb; 41 | this.numCountry = country; 42 | this.numAuthor = author; 43 | this.numAddress = address; 44 | this.numItem = item; 45 | this.numCustomer = customer; 46 | this.numOrders = orders; 47 | this.numCCX = ccx; 48 | this.numOL = ol; 49 | this.conn = conn; 50 | } 51 | 52 | // public void popTables(List I_ITEM_LIST) throws SQLException, 53 | // ParseException, IOException { 54 | public void popTables() throws SQLException, ParseException, IOException { 55 | // ClassLoader cl = this.getClass().getClassLoader(); 56 | // InputStream in = 57 | // cl.getResourceAsStream("P:\\workspace\\database-temp\\tpc-w\\title10000000"); 58 | BufferedReader br = new BufferedReader(new FileReader(new File( 59 | "title10000000"))); 60 | 61 | // new BufferedReader(new InputStreamReader(in)); 62 | for (int i = 0; i < numItem; i++) { 63 | I_ITEM_LIST.add(i, br.readLine()); 64 | } 65 | // this.I_ITEM_LIST = I_ITEM_LIST; 66 | System.out.println("EB:" + numEB + ",Item:" + numItem + ",Country:" 67 | + numCountry + ",Author:" + numAuthor + ",Customer:" 68 | + numCustomer + ",Orders:" + numOrders + ",OL:" + numOL 69 | + ",CCX:" + numCCX + ",Address:" + numAddress); 70 | addAuthor(numAuthor); 71 | addCountry(numCountry); 72 | addAddress(numAddress); 73 | addCustomer(numCustomer); 74 | addOrders(numOrders); 75 | addCCXacts(numCCX); 76 | addItem(numItem); 77 | addOrderLine(numOrders); // number of order line actually determined by 78 | // number of orders 79 | System.out.println("Populate tables completed!"); 80 | } 81 | 82 | public void addCountry(int numCountry) throws SQLException { 83 | sql = "insert into country values(?,?,?,?)"; 84 | PreparedStatement pstmt = conn.prepareStatement(sql); 85 | for (int i = 0; i < numCountry; i++) { 86 | pstmt.setInt(1, i + 1); // CO_ID number(4) 87 | pstmt.setString(2, sp.currentExchange[i][0]); // CO_NAME 88 | // varchar2(50) 89 | pstmt.setFloat(3, 90 | (new Float(sp.currentExchange[i][1])).floatValue()); // CO_EXCHANGE 91 | // number(6,6) 92 | pstmt.setString(4, sp.currentExchange[i][2]); // CO_CURRENCY 93 | // varchar2(18) 94 | pstmt.addBatch(); 95 | } 96 | pstmt.executeBatch(); 97 | pstmt.close(); 98 | conn.commit(); 99 | System.out.println("Country table populated"); 100 | } 101 | 102 | public void addAuthor(int numAuthor) throws SQLException, ParseException { 103 | sql = "insert into author values(?,?,?,?,?,?)"; 104 | PreparedStatement pstmt = conn.prepareStatement(sql); 105 | for (int i = 0; i < numAuthor; i++) { 106 | pstmt.setInt(1, i + 1); // A_ID number(10) 107 | pstmt.setString(2, randomAstring(3, 20)); // A_FNAME varchar2(20) 108 | pstmt.setString(3, A_LNAME(i + 1, numAuthor)); // A_LNAME 109 | // varchar2(20) 110 | pstmt.setString(4, randomAstring(1, 20)); // A_MNAME varchar2(20) 111 | pstmt.setDate(5, sqlDate(randomDate(1, 1, 1800, 1, 1, 1990))); // A_DOB 112 | // date 113 | pstmt.setString(6, randomAstring(125, 500)); // A_BIO varchar2(500) 114 | // pstmt.addBatch(); 115 | pstmt.execute(); 116 | } 117 | // pstmt.executeBatch(); 118 | pstmt.close(); 119 | conn.commit(); 120 | System.out.println("Author table populated"); 121 | } 122 | 123 | public void addAddress(int numAddress) throws SQLException { 124 | sql = "insert into address values(?,?,?,?,?,?,?)"; 125 | PreparedStatement pstmt = conn.prepareStatement(sql); 126 | for (int i = 0; i < numAddress; i++) { 127 | pstmt.setInt(1, i + 1); // ADDR_ID number(10) 128 | pstmt.setString(2, randomAstring(15, 40)); // ADDR_STREET1 129 | // varchar2(40) 130 | pstmt.setString(3, randomAstring(15, 40)); // ADDR_STRRET2 131 | // varchar2(40) 132 | pstmt.setString(4, randomAstring(4, 30)); // ADDR_CITY varchar2(30) 133 | pstmt.setString(5, randomAstring(2, 20)); // ADDR_STATE varchar2(20) 134 | pstmt.setString(6, randomAstring(5, 10)); // ADDR_ZIP varchar2(5) 135 | pstmt.setInt(7, randomBetweenInclusive(1, 92)); // ADDR_CO_ID 136 | // number(4) 137 | // pstmt.addBatch(); 138 | pstmt.execute(); 139 | } 140 | // pstmt.executeBatch(); 141 | pstmt.close(); 142 | conn.commit(); 143 | System.out.println("Address table populated"); 144 | } 145 | 146 | public void addItem(int numItem) throws SQLException, ParseException { 147 | sql = "insert into item values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; 148 | PreparedStatement pstmt = conn.prepareStatement(sql); 149 | for (int i = 0; i < numItem; i++) { 150 | pstmt.setInt(1, i + 1); // I_ID number(10) 151 | pstmt.setString(2, I_ITEM_LIST.get(i)); // I_TITLE varchar2(60) 152 | pstmt.setInt(3, I_A_ID(i + 1, numItem)); // I_A_ID number(10) 153 | Calendar cal = randomDate(1, 1, 1930); 154 | pstmt.setDate(4, sqlDate(cal)); // I_PUB_DATE date 155 | pstmt.setString(5, randomAstring(14, 60)); // I_PUBLISHER 156 | // varchar2(60) 157 | pstmt.setString(6, sp.subjects[rd.nextInt(sp.subjects.length)]); // I_SUBJECT 158 | // varchar2(60) 159 | pstmt.setString(7, randomAstring(100, 500)); // I_DESC varcahr2(500) 160 | List relatedItemList = randomUnique(5, 10); 161 | pstmt.setInt(8, relatedItemList.get(0).intValue()); // I_RELATED1 162 | // number(10) 163 | pstmt.setInt(9, relatedItemList.get(1).intValue()); // I_RELATED2 164 | // number(10) 165 | pstmt.setInt(10, relatedItemList.get(2).intValue()); // I_RELATED3 166 | // number(10) 167 | pstmt.setInt(11, relatedItemList.get(3).intValue()); // I_RELATED4 168 | // number(10) 169 | pstmt.setInt(12, relatedItemList.get(4).intValue()); // I_RELATED5 170 | // number(10) 171 | pstmt.setString(13, url); // I_THUMBNAIL varchar2(100) 172 | pstmt.setString(14, url); // I_IMAGE varchar2(100) 173 | float I_SRP = randomFloatTwoWithin(1, 0, 9999, 99); 174 | pstmt.setFloat(15, I_SRP); // I_SRP number(15,2) 175 | pstmt.setFloat(16, I_COST(I_SRP)); // I_COST number(15,2) 176 | pstmt.setDate(17, sqlDate(randomDateAdjust(cal, 30))); // I_AVAIL 177 | // date 178 | pstmt.setInt(18, randomBetweenInclusive(10, 30)); // I_STOCK 179 | // number(4) 180 | pstmt.setString(19, randomAstring(1, 13)); // I_ISBN varchar2(13) 181 | pstmt.setInt(20, randomBetweenInclusive(20, 9999)); // I_PAGE 182 | // number(4) 183 | pstmt.setString(21, sp.backings[rd.nextInt(sp.backings.length)]); // I_BACKING 184 | // varchar2(15) 185 | pstmt.setString(22, randomFloatTwoWithin(0, 1, 99, 99) + "x" 186 | + randomFloatTwoWithin(0, 1, 99, 99) + "x" 187 | + randomFloatTwoWithin(0, 1, 99, 99)); // I_DIMENSION 188 | // varchar2(25) 189 | // pstmt.addBatch(); 190 | pstmt.execute(); 191 | } 192 | // pstmt.executeBatch(); 193 | pstmt.close(); 194 | conn.commit(); 195 | System.out.println("Item table populated"); 196 | } 197 | 198 | public void addCustomer(int numCustomer) throws SQLException, 199 | ParseException { 200 | sql = "insert into customer values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; 201 | PreparedStatement pstmt = conn.prepareStatement(sql); 202 | 203 | for (int i = 0; i < numCustomer; i++) { 204 | pstmt.setInt(1, i + 1); // C_ID number(10) 205 | String C_UNAME = DigSyl(i + 1, 0); 206 | pstmt.setString(2, C_UNAME); // C_UNAME varchar2(20) 207 | pstmt.setString(3, DigSyl(i + 1, 0).toLowerCase()); // C_PASSWD 208 | // varchar2(20) 209 | pstmt.setString(4, randomAstring(8, 15)); // C_FNAME varchar2(15) 210 | pstmt.setString(5, randomAstring(8, 15)); // C_LNAME varchar2(15) 211 | pstmt.setInt(6, randomBetweenInclusive(1, 2 * numCustomer)); // C_ADDR_ID 212 | // number(10) 213 | pstmt.setString(7, randomNstring(9, 16)); // C_PHONE varchar2(16) 214 | pstmt.setString(8, C_UNAME + "@" + randomAstring(2, 9) + ".com"); // C_EMAIL 215 | // varchar2(50) 216 | Calendar cal = Calendar.getInstance(); 217 | Calendar C_SINCE = randomDateAdjust(cal, 218 | -(randomBetweenInclusive(1, 173))); 219 | pstmt.setDate(9, sqlDate(C_SINCE)); // C_SINCE date 220 | Calendar C_LAST_VISIT = randomDateAdjust(C_SINCE, 221 | randomBetweenInclusive(0, 60)); 222 | pstmt.setDate(10, sqlDate(currentDateCheck(C_LAST_VISIT))); // C_LAST_VISIT 223 | // date 224 | pstmt.setDate(11, sqlDateTime(cal)); // C_LOGIN date 225 | pstmt.setDate(12, sqlDate(randomHourAdjust(cal, 2))); // C_EXPIRATION 226 | // date 227 | pstmt.setFloat(13, randomFloatTwoWithin(0, 0, 0, 50)); // C_DISCOUNT 228 | // number(3,2) 229 | pstmt.setFloat(14, (float) 0.00); // C_BALANCE number(15,2) 230 | pstmt.setFloat(15, randomFloatTwoWithin(0, 0, 999, 99)); // C_YTD_PMT 231 | // number(15,2) 232 | pstmt.setDate(16, sqlDate(randomDate(1, 1, 1880))); // C_BIRTHDAY 233 | // date 234 | pstmt.setString(17, randomAstring(100, 500)); // C_DATA 235 | // varchar2(500) 236 | // pstmt.addBatch(); 237 | pstmt.execute(); 238 | } 239 | // pstmt.executeBatch(); 240 | pstmt.close(); 241 | conn.commit(); 242 | System.out.println("Customer table populated"); 243 | } 244 | 245 | public void addOrders(int numOrders) throws SQLException, ParseException { 246 | sql = "insert into orders values(?,?,?,?,?,?,?,?,?,?,?)"; 247 | PreparedStatement pstmt = conn.prepareStatement(sql); 248 | for (int i = 0; i < numOrders; i++) { 249 | pstmt.setInt(1, i + 1); // O_ID number(10) 250 | pstmt.setInt(2, randomBetweenInclusive(1, (int) numCustomer)); // O_C_ID 251 | // number(10) 252 | Calendar cal = Calendar.getInstance(); 253 | Calendar O_DATE = randomDateAdjust(cal, 254 | -randomBetweenInclusive(0, 7)); 255 | pstmt.setDate(3, sqlDate(O_DATE)); // O_DATE date 256 | float O_SUB_TOTAL = randomFloatTwoWithin(10, 0, 9999, 99); 257 | pstmt.setFloat(4, O_SUB_TOTAL); // O_SUB_TOTAL number(15,2) 258 | float O_TAX = O_TAX(O_SUB_TOTAL); 259 | pstmt.setFloat(5, O_TAX); // O_TAX number(15,2) 260 | float O_TOTAL = O_TOTAL(O_SUB_TOTAL, O_TAX); 261 | O_TOTAL_LIST.add(i, (Float) O_TOTAL); 262 | pstmt.setFloat(6, O_TOTAL); // O_TOTAL number(15,2) 263 | pstmt.setString(7, sp.shiptype[rd.nextInt(sp.shiptype.length)]); // O_SHIP_TYPE 264 | // archar2(10) 265 | Calendar O_SHIP_DATE = randomDateAdjust(O_DATE, 266 | randomBetweenInclusive(0, 2)); 267 | O_SHIP_DATE_LIST.add(i, sqlDateTime(O_SHIP_DATE)); 268 | pstmt.setDate(8, sqlDateTime(O_SHIP_DATE)); // O_SHIP_DATE date 269 | pstmt.setInt(9, randomBetweenInclusive(1, 2 * numCustomer)); // O_BILL_ADDR_ID 270 | // number(10) 271 | pstmt.setInt(10, randomBetweenInclusive(1, 2 * numCustomer)); // O_SHIP_ADDR_ID 272 | // number(10) 273 | pstmt.setString(11, sp.status[rd.nextInt(sp.status.length)]); // O_STATUS 274 | // pstmt.addBatch(); 275 | pstmt.execute(); 276 | } 277 | // pstmt.executeBatch(); 278 | pstmt.close(); 279 | conn.commit(); 280 | System.out.println("Orders table populated"); 281 | } 282 | 283 | public void addCCXacts(int numCCX) throws SQLException, ParseException { 284 | sql = "insert into cc_xacts values(?,?,?,?,?,?,?,?,?)"; 285 | PreparedStatement pstmt = conn.prepareStatement(sql); 286 | for (int i = 0; i < numCCX; i++) { 287 | pstmt.setInt(1, i + 1); // CX_O_ID number(10) 288 | pstmt.setString(2, sp.cxtype[rd.nextInt(sp.cxtype.length)]); // CX_TYPE 289 | // varchar2(10) 290 | pstmt.setLong(3, new Long(randomNstring(16, 16)).longValue()); // CX_NUM 291 | // number(16) 292 | pstmt.setString(4, randomAstring(14, 30)); // CX_NAME varchar2(31) 293 | Calendar cal = Calendar.getInstance(); 294 | Calendar CX_EXPIRY = randomDateAdjust(cal, 295 | -randomBetweenInclusive(10, 730)); 296 | pstmt.setDate(5, sqlDate(CX_EXPIRY)); // CX_EXPIRY date 297 | pstmt.setString(6, randomAstring(15, 15)); // CX_AUTH_ID char(15) 298 | // pstmt.setFloat(7, O_TOTAL_LIST.get(i).floatValue()); // 299 | // CX_XACT_AMT number(15,2) 300 | pstmt.setFloat(7, 1); // CX_XACT_AMT number(15,2) 301 | pstmt.setDate(8, O_SHIP_DATE_LIST.get(i)); // CX_XACT_DATE date 302 | pstmt.setInt(9, randomBetweenInclusive(1, 92)); // CX_CO_ID 303 | // number(4) 304 | // pstmt.addBatch(); 305 | pstmt.execute(); 306 | } 307 | // pstmt.executeBatch(); 308 | pstmt.close(); 309 | conn.commit(); 310 | System.out.println("CCXacts table populated"); 311 | } 312 | 313 | public void addOrderLine(int numOrders) throws SQLException, ParseException { 314 | sql = "insert into order_line values(?,?,?,?,?,?)"; 315 | PreparedStatement pstmt = conn.prepareStatement(sql); 316 | for (int j = 0; j < numOrders; j++) { 317 | numOL = rd.nextInt(5) + 1; 318 | List ol_id_list = randomUnique(100, 100); 319 | for (int i = 0; i < numOL + 1; i++) { 320 | pstmt.setInt(1, ol_id_list.get(i)); // OL_ID number(10) 321 | pstmt.setInt(2, j + 1); // OL_O_ID number(10) 322 | pstmt.setInt(3, randomBetweenInclusive(1, numItem)); // OL_I_ID 323 | // number(10) 324 | pstmt.setInt(4, randomBetweenInclusive(1, 300)); // OL_QTY 325 | // number(3) 326 | float ol_discount = randomFloatTwoWithin(0, 0, 0, 3) / 10; // sent 327 | // [0.00..0.3] 328 | // instead 329 | // of 330 | // [0.00..0.03], 331 | // so 332 | // divide 333 | // by 334 | // 10 335 | pstmt.setFloat(5, OL_DISCOUNT(ol_discount)); // OL_DISCOUNT 336 | // number(3,2) 337 | pstmt.setString(6, randomAstring(20, 100)); // OL_COMMENTS 338 | // varchar2(100) 339 | // pstmt.addBatch(); 340 | pstmt.execute(); 341 | } 342 | } 343 | // pstmt.executeBatch(); 344 | pstmt.close(); 345 | conn.commit(); 346 | System.out.println("Order_line table populated"); 347 | } 348 | 349 | public String DigSyl(int D, int N) { // TCP-W 350 | String DString = (new Integer(D)).toString(); 351 | int ddigit = DString.length(); 352 | if (N > ddigit) { 353 | for (int i = 0; i < N - ddigit; i++) { 354 | DString = "0" + DString; 355 | } 356 | } 357 | return concateSyl(DString); 358 | } 359 | 360 | public String concateSyl(String DString) { // used by DigSyl() 361 | String str = ""; 362 | int ddigit = DString.length(); 363 | for (int i = 0; i < ddigit; i++) { 364 | int index = Character.getNumericValue(DString.charAt(i)); 365 | str += sp.syllables[index]; 366 | } 367 | return str; 368 | } 369 | 370 | public String randomAstring(int x, int y) { // TCP-W 371 | int strLength = randomBetweenInclusive(x, y); 372 | String str = ""; 373 | for (int i = 0; i < strLength; i++) { 374 | str += sp.characters[rd.nextInt(sp.characters.length)]; 375 | } 376 | return str; 377 | } 378 | 379 | public String randomNstring(int x, int y) { // TCP-W 380 | int strLength = randomBetweenInclusive(x, y); 381 | String str = ""; 382 | for (int i = 0; i < strLength; i++) { 383 | str += sp.numbers[rd.nextInt(sp.numbers.length)]; 384 | } 385 | return str; 386 | } 387 | 388 | public String randomPermutation(int x, int y) { // TPC-W 389 | String str = ""; 390 | String numStr = "0123456789".substring(x, y + 1); 391 | while (numStr.length() > 0) { 392 | int index = rd.nextInt(numStr.length()); 393 | str += numStr.substring(index, index + 1); 394 | numStr = numStr.substring(0, index) + numStr.substring(index + 1); 395 | } 396 | return str; 397 | } 398 | 399 | public String DBGEN(int I_ID, int numItem) { // TPC-W 400 | // generate partial I_ITEM as WGEN 401 | if (I_ID <= numItem / 5) 402 | return DigSyl(I_ID, 7); 403 | else 404 | return DigSyl(randomBetweenInclusive(1, (int) (I_ID / 5)), 7); 405 | } 406 | 407 | public Calendar randomDate(int smon, int sdate, int syear, int emon, 408 | int edate, int eyear) throws ParseException { 409 | // random day between start date and end date 410 | Calendar cal = Calendar.getInstance(); 411 | int year = randomBetweenInclusive(smon, eyear); 412 | if (year == syear) { 413 | cal.set(Calendar.MONTH, randomBetweenInclusive(smon, 12)); 414 | if (emon == 12) 415 | cal.set(Calendar.DATE, randomBetweenInclusive(sdate, 31)); 416 | else 417 | cal.set(Calendar.DATE, randomDate(emon, year)); 418 | } else { 419 | int mon = randomBetweenInclusive(1, 12); 420 | cal.set(Calendar.MONTH, mon); 421 | cal.set(Calendar.DATE, randomDate(mon, year)); 422 | } 423 | return cal; 424 | } 425 | 426 | public int randomDate(int mon, int year) { 427 | if (mon == 2) { 428 | if (year % 4 == 0) 429 | return randomBetweenInclusive(1, 29); 430 | else 431 | return randomBetweenInclusive(1, 28); 432 | } else { 433 | if (mon == 1 || mon == 3 || mon == 5 || mon == 7 || mon == 8 434 | || mon == 10 || mon == 12) 435 | return randomBetweenInclusive(1, 31); 436 | else 437 | return randomBetweenInclusive(1, 30); 438 | } 439 | } 440 | 441 | public Calendar randomDate(int smon, int sdate, int syear) 442 | throws ParseException { 443 | // random day between start date and current date 444 | Calendar cal = Calendar.getInstance(); 445 | int emon = cal.get(Calendar.MONTH); 446 | int edate = cal.get(Calendar.DAY_OF_MONTH); 447 | int eyear = cal.get(Calendar.YEAR); 448 | return randomDate(smon, sdate, syear, emon, edate, eyear); 449 | } 450 | 451 | public Calendar randomDateAdjust(Calendar cal, int diff) 452 | throws ParseException { 453 | // adjust cal date by diff 454 | cal.add(Calendar.DATE, diff); 455 | return cal; 456 | } 457 | 458 | public Calendar randomHourAdjust(Calendar cal, int diff) 459 | throws ParseException { 460 | // adjust cal hour by diff 461 | cal.add(Calendar.HOUR, diff); 462 | return cal; 463 | } 464 | 465 | public java.sql.Date sqlDate(Calendar cal) throws ParseException { 466 | // convert Calendar to java.sql.Date 467 | SimpleDateFormat formatter = new SimpleDateFormat("MMM/dd/yyyy"); 468 | String dateStr = sp.month[cal.get(Calendar.MONTH)] + "/" 469 | + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR); 470 | java.util.Date utilDate = formatter.parse(dateStr); 471 | java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime()); 472 | return sqlDate; 473 | } 474 | 475 | public java.sql.Date sqlDateTime(Calendar cal) throws ParseException { 476 | // convert Calendar to jave.sql.Date including time 477 | SimpleDateFormat formatter = new SimpleDateFormat( 478 | "MMM/dd/yyyy HH:MM:SS aa"); 479 | String AM_PM = "AM"; 480 | if (cal.get(Calendar.AM) == 1) 481 | AM_PM = "PM"; 482 | String dateStr = sp.month[cal.get(Calendar.MONTH)] + "/" 483 | + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) + " " 484 | + cal.get(Calendar.HOUR) + ":" + cal.get(Calendar.MINUTE) + ":" 485 | + cal.get(Calendar.SECOND) + " " + AM_PM; 486 | java.util.Date utilDate = formatter.parse(dateStr); 487 | java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime()); 488 | return sqlDate; 489 | } 490 | 491 | public Calendar currentDateCheck(Calendar cal) { 492 | // make sure if cal is no later than current date 493 | Calendar current = Calendar.getInstance(); 494 | if (current.compareTo(cal) < 0) 495 | return current; 496 | else 497 | return cal; 498 | } 499 | 500 | public int I_A_ID(int iid, int numItem) { 501 | if (iid <= numItem / 4) 502 | return iid; 503 | else 504 | return rd.nextInt(numItem / 4) + 1; 505 | } 506 | 507 | public int randomBetweenInclusive(int s, int e) { 508 | // generate a random integer between s and e both inclusive 509 | int result = rd.nextInt(e - s + 1) + s; 510 | // System.out.println("s ="+s+", e ="+e+", result = "+result); 511 | return result; 512 | } 513 | 514 | public float randomFloatTwoWithin(int s, int sp, int e, int ep) { 515 | // generate a random float with 2 digit precision 516 | String floatStr = ((Integer) (rd.nextInt(e - s + 1) + s)).toString() 517 | + "." + ((Integer) (rd.nextInt(ep - sp + 1) + sp)).toString(); 518 | return new Float(floatStr).floatValue(); 519 | } 520 | 521 | public List randomUnique(int num, int range) { 522 | // generate certain num of unique integers fall within the range 523 | // [1..range] 524 | List strList = new ArrayList(num); 525 | while (num > 0) { 526 | Integer id = (Integer) (rd.nextInt(range) + 1); 527 | if (!strList.contains(id)) { 528 | strList.add(id); 529 | num--; 530 | } 531 | } 532 | return strList; 533 | } 534 | 535 | public float I_COST(float I_SRP) { 536 | // calculated 2 digit precision I_COST 537 | float costRate = randomFloatTwoWithin(0, 0, 0, 5); 538 | String I_COST_Str = ((Float) (I_SRP - (I_SRP * costRate))).toString(); 539 | if (I_COST_Str.indexOf(".") + 2 > I_COST_Str.length()) 540 | return new Float(I_COST_Str.substring(0, 541 | I_COST_Str.indexOf(".") + 3)).floatValue(); 542 | else 543 | return new Float(I_COST_Str).floatValue(); 544 | } 545 | 546 | public float O_TAX(float O_SUB_TOTAL) { 547 | // calculate two digit precision O_TAX 548 | String O_TAX_Str = ((Float) (O_SUB_TOTAL * (float) 0.0825)).toString(); 549 | if (O_TAX_Str.indexOf(".") + 2 > O_TAX_Str.length()) 550 | return new Float(O_TAX_Str.substring(0, O_TAX_Str.indexOf(".") + 3)) 551 | .floatValue(); 552 | else 553 | return new Float(O_TAX_Str).floatValue(); 554 | } 555 | 556 | public float O_TOTAL(float O_SUB_TOTAL, float O_TAX) { 557 | // calculate 2 digit precision O_TOTAL 558 | String O_TOTAL_Str = ((Float) (O_SUB_TOTAL + O_TAX + (float) 3.00 + 1)) 559 | .toString(); 560 | if (O_TOTAL_Str.indexOf(".") + 2 > O_TOTAL_Str.length()) 561 | return new Float(O_TOTAL_Str.substring(0, 562 | O_TOTAL_Str.indexOf(".") + 3)).floatValue(); 563 | else 564 | return new Float(O_TOTAL_Str).floatValue(); 565 | } 566 | 567 | public float OL_DISCOUNT(float OL_DISCOUNT) { 568 | // calculate 2 digit precision OL_DISCOUNT 569 | String OL_DISC_Str = ((Float) OL_DISCOUNT).toString(); 570 | if (OL_DISC_Str.indexOf(".") + 2 > OL_DISC_Str.length()) 571 | return new Float(OL_DISC_Str.substring(0, 572 | OL_DISC_Str.indexOf(".") + 3)).floatValue(); 573 | else 574 | return new Float(OL_DISC_Str).floatValue(); 575 | } 576 | 577 | public String A_LNAME(int A_ID, int numAuthor) { 578 | // generate A_LNAME as WGEN 579 | if (A_ID <= numAuthor / 2.5) 580 | return DigSyl(A_ID, 7); 581 | else 582 | return DigSyl(randomBetweenInclusive(1, (int) (A_ID / 2.5)), 7); 583 | } 584 | } 585 | -------------------------------------------------------------------------------- /tpcw/tpcw.patch: -------------------------------------------------------------------------------- 1 | diff --git a/TPCW_Database.tpcw.java b/TPCW_Database.tpcw.java 2 | new file mode 100644 3 | index 0000000..e03a3ca 4 | --- /dev/null 5 | +++ b/TPCW_Database.tpcw.java 6 | @@ -0,0 +1,1358 @@ 7 | +/* 8 | + * TPCW_Database.java - Contains all of the code involved with database 9 | + * accesses, including all of the JDBC calls. These 10 | + * functions are called by many of the servlets. 11 | + * 12 | + ************************************************************************ 13 | + * 14 | + * This is part of the the Java TPC-W distribution, 15 | + * written by Harold Cain, Tim Heil, Milo Martin, Eric Weglarz, and Todd 16 | + * Bezenek. University of Wisconsin - Madison, Computer Sciences 17 | + * Dept. and Dept. of Electrical and Computer Engineering, as a part of 18 | + * Prof. Mikko Lipasti's Fall 1999 ECE 902 course. 19 | + * 20 | + * Copyright (C) 1999, 2000 by Harold Cain, Timothy Heil, Milo Martin, 21 | + * Eric Weglarz, Todd Bezenek. 22 | + * 23 | + * This source code is distributed "as is" in the hope that it will be 24 | + * useful. It comes with no warranty, and no author or distributor 25 | + * accepts any responsibility for the consequences of its use. 26 | + * 27 | + * Everyone is granted permission to copy, modify and redistribute 28 | + * this code under the following conditions: 29 | + * 30 | + * This code is distributed for non-commercial use only. 31 | + * Please contact the maintainer for restrictions applying to 32 | + * commercial use of these tools. 33 | + * 34 | + * Permission is granted to anyone to make or distribute copies 35 | + * of this code, either as received or modified, in any 36 | + * medium, provided that all copyright notices, permission and 37 | + * nonwarranty notices are preserved, and that the distributor 38 | + * grants the recipient permission for further redistribution as 39 | + * permitted by this document. 40 | + * 41 | + * Permission is granted to distribute this code in compiled 42 | + * or executable form under the same conditions that apply for 43 | + * source code, provided that either: 44 | + * 45 | + * A. it is accompanied by the corresponding machine-readable 46 | + * source code, 47 | + * B. it is accompanied by a written offer, with no time limit, 48 | + * to give anyone a machine-readable copy of the corresponding 49 | + * source code in return for reimbursement of the cost of 50 | + * distribution. This written offer must permit verbatim 51 | + * duplication by anyone, or 52 | + * C. it is distributed by someone who received only the 53 | + * executable form, and is accompanied by a copy of the 54 | + * written offer of source code that they received concurrently. 55 | + * 56 | + * In other words, you are welcome to use, share and improve this codes. 57 | + * You are forbidden to forbid anyone else to use, share and improve what 58 | + * you give them. 59 | + * 60 | + ************************************************************************ 61 | + * 62 | + * Changed 2003 by Jan Kiefer. 63 | + * 64 | + ************************************************************************/ 65 | + 66 | +import java.io.*; 67 | +import java.net.URL; 68 | +import java.sql.*; 69 | +import java.lang.Math.*; 70 | +import java.util.*; 71 | +import java.sql.Date; 72 | +import java.sql.Timestamp; 73 | + 74 | +public class TPCW_Database { 75 | + 76 | + static String driverName = "@jdbc.driver@"; 77 | + static String jdbcPath = "@jdbc.path@"; 78 | + // Pool of *available* connections. 79 | + static Vector availConn = new Vector(0); 80 | + static int checkedOut = 0; 81 | + static int totalConnections = 0; 82 | + static int createdConnections = 0; 83 | + static int closedConnections = 0; 84 | + 85 | + // private static final boolean use_connection_pool = false; 86 | + private static final boolean use_connection_pool = true; 87 | + public static final int maxConn = @jdbc.connPoolMax@; 88 | + 89 | + // Here's what the db line looks like for postgres 90 | + //public static final String url = "jdbc:postgresql://eli.ece.wisc.edu/tpcwb"; 91 | + 92 | + 93 | + // Get a connection from the pool. 94 | + public static synchronized Connection getConnection() { 95 | + if (!use_connection_pool) { 96 | + return getNewConnection(); 97 | + } else { 98 | + Connection con = null; 99 | + while (availConn.size() > 0) { 100 | + // Pick the first Connection in the Vector 101 | + // to get round-robin usage 102 | + con = (Connection) availConn.firstElement(); 103 | + availConn.removeElementAt(0); 104 | + try { 105 | + if (con.isClosed()) { 106 | + continue; 107 | + } 108 | + } 109 | + catch (SQLException e) { 110 | + e.printStackTrace(); 111 | + continue; 112 | + } 113 | + 114 | + // Got a connection. 115 | + checkedOut++; 116 | + return(con); 117 | + } 118 | + 119 | + if (maxConn == 0 || checkedOut < maxConn) { 120 | + con = getNewConnection(); 121 | + totalConnections++; 122 | + } 123 | + 124 | + 125 | + if (con != null) { 126 | + checkedOut++; 127 | + } 128 | + 129 | + return con; 130 | + } 131 | + } 132 | + 133 | + // Return a connection to the pool. 134 | + public static synchronized void returnConnection(Connection con) 135 | + throws java.sql.SQLException 136 | + { 137 | + if (!use_connection_pool) { 138 | + con.close(); 139 | + } else { 140 | + checkedOut--; 141 | + availConn.addElement(con); 142 | + } 143 | + } 144 | + 145 | + // Get a new connection to DB2 146 | + public static Connection getNewConnection() { 147 | + try { 148 | + Class.forName(driverName); 149 | + // Class.forName("postgresql.Driver"); 150 | + 151 | + // Create URL for specifying a DBMS 152 | + Connection con; 153 | + while(true) { 154 | + try { 155 | + // con = DriverManager.getConnection("jdbc:postgresql://eli.ece.wisc.edu/tpcw", "milo", ""); 156 | + con = DriverManager.getConnection(jdbcPath); 157 | + break; 158 | + } catch (java.sql.SQLException ex) { 159 | + System.err.println("Error getting connection: " + 160 | + ex.getMessage() + " : " + 161 | + ex.getErrorCode() + 162 | + ": trying to get connection again."); 163 | + ex.printStackTrace(); 164 | + java.lang.Thread.sleep(1000); 165 | + } 166 | + } 167 | + con.setAutoCommit(false); 168 | + createdConnections++; 169 | + return con; 170 | + } catch (java.lang.Exception ex) { 171 | + ex.printStackTrace(); 172 | + } 173 | + return null; 174 | + } 175 | + 176 | + public static String[] getName(int c_id) { 177 | + String name[] = new String[2]; 178 | + try { 179 | + // Prepare SQL 180 | + // out.println("About to call getConnection!"); 181 | + // out.flush(); 182 | + Connection con = getConnection(); 183 | + // out.println("About to preparestatement!"); 184 | + // out.flush(); 185 | + PreparedStatement get_name = con.prepareStatement 186 | + (@sql.getName@); 187 | + 188 | + // Set parameter 189 | + get_name.setInt(1, c_id); 190 | + // out.println("About to execute query!"); 191 | + // out.flush(); 192 | + 193 | + ResultSet rs = get_name.executeQuery(); 194 | + 195 | + // Results 196 | + rs.next(); 197 | + name[0] = rs.getString("c_fname"); 198 | + name[1] = rs.getString("c_lname"); 199 | + rs.close(); 200 | + get_name.close(); 201 | + con.commit(); 202 | + returnConnection(con); 203 | + } catch (java.lang.Exception ex) { 204 | + ex.printStackTrace(); 205 | + } 206 | + return name; 207 | + } 208 | + 209 | + public static Book getBook(int i_id) { 210 | + Book book = null; 211 | + try { 212 | + // Prepare SQL 213 | + Connection con = getConnection(); 214 | + PreparedStatement statement = con.prepareStatement 215 | + (@sql.getBook@); 216 | + 217 | + // Set parameter 218 | + statement.setInt(1, i_id); 219 | + ResultSet rs = statement.executeQuery(); 220 | + 221 | + // Results 222 | + rs.next(); 223 | + book = new Book(rs); 224 | + rs.close(); 225 | + statement.close(); 226 | + con.commit(); 227 | + returnConnection(con); 228 | + } catch (java.lang.Exception ex) { 229 | + ex.printStackTrace(); 230 | + } 231 | + return book; 232 | + } 233 | + 234 | + public static Customer getCustomer(String UNAME){ 235 | + Customer cust = null; 236 | + try { 237 | + // Prepare SQL 238 | + Connection con = getConnection(); 239 | + PreparedStatement statement = con.prepareStatement 240 | + (@sql.getCustomer@); 241 | + 242 | + // Set parameter 243 | + statement.setString(1, UNAME); 244 | + ResultSet rs = statement.executeQuery(); 245 | + 246 | + // Results 247 | + if(rs.next()) 248 | + cust = new Customer(rs); 249 | + else { 250 | + System.err.println("ERROR: NULL returned in getCustomer!"); 251 | + rs.close(); 252 | + statement.close(); 253 | + returnConnection(con); 254 | + return null; 255 | + } 256 | + 257 | + statement.close(); 258 | + con.commit(); 259 | + returnConnection(con); 260 | + } catch (java.lang.Exception ex) { 261 | + ex.printStackTrace(); 262 | + } 263 | + return cust; 264 | + } 265 | + 266 | + public static Vector doSubjectSearch(String search_key) { 267 | + Vector vec = new Vector(); 268 | + try { 269 | + // Prepare SQL 270 | + Connection con = getConnection(); 271 | + PreparedStatement statement = con.prepareStatement 272 | + (@sql.doSubjectSearch@); 273 | + 274 | + // Set parameter 275 | + statement.setString(1, search_key); 276 | + ResultSet rs = statement.executeQuery(); 277 | + 278 | + // Results 279 | + while(rs.next()) { 280 | + vec.addElement(new Book(rs)); 281 | + } 282 | + rs.close(); 283 | + statement.close(); 284 | + con.commit(); 285 | + returnConnection(con); 286 | + } catch (java.lang.Exception ex) { 287 | + ex.printStackTrace(); 288 | + } 289 | + return vec; 290 | + } 291 | + 292 | + public static Vector doTitleSearch(String search_key) { 293 | + Vector vec = new Vector(); 294 | + try { 295 | + // Prepare SQL 296 | + Connection con = getConnection(); 297 | + PreparedStatement statement = con.prepareStatement 298 | + (@sql.doTitleSearch@); 299 | + 300 | + // Set parameter 301 | + statement.setString(1, search_key+"%"); 302 | + ResultSet rs = statement.executeQuery(); 303 | + 304 | + // Results 305 | + while(rs.next()) { 306 | + vec.addElement(new Book(rs)); 307 | + } 308 | + rs.close(); 309 | + statement.close(); 310 | + con.commit(); 311 | + returnConnection(con); 312 | + } catch (java.lang.Exception ex) { 313 | + ex.printStackTrace(); 314 | + } 315 | + return vec; 316 | + } 317 | + 318 | + public static Vector doAuthorSearch(String search_key) { 319 | + Vector vec = new Vector(); 320 | + try { 321 | + // Prepare SQL 322 | + Connection con = getConnection(); 323 | + PreparedStatement statement = con.prepareStatement 324 | + (@sql.doAuthorSearch@); 325 | + 326 | + // Set parameter 327 | + statement.setString(1, search_key+"%"); 328 | + ResultSet rs = statement.executeQuery(); 329 | + 330 | + // Results 331 | + while(rs.next()) { 332 | + vec.addElement(new Book(rs)); 333 | + } 334 | + rs.close(); 335 | + statement.close(); 336 | + con.commit(); 337 | + returnConnection(con); 338 | + } catch (java.lang.Exception ex) { 339 | + ex.printStackTrace(); 340 | + } 341 | + return vec; 342 | + } 343 | + 344 | + public static Vector getNewProducts(String subject) { 345 | + Vector vec = new Vector(); // Vector of Books 346 | + try { 347 | + // Prepare SQL 348 | + Connection con = getConnection(); 349 | + PreparedStatement statement = con.prepareStatement 350 | + (@sql.getNewProducts@); 351 | + 352 | + // Set parameter 353 | + statement.setString(1, subject); 354 | + ResultSet rs = statement.executeQuery(); 355 | + 356 | + // Results 357 | + while(rs.next()) { 358 | + vec.addElement(new ShortBook(rs)); 359 | + } 360 | + rs.close(); 361 | + statement.close(); 362 | + con.commit(); 363 | + returnConnection(con); 364 | + } catch (java.lang.Exception ex) { 365 | + ex.printStackTrace(); 366 | + } 367 | + return vec; 368 | + } 369 | + 370 | + public static Vector getBestSellers(String subject) { 371 | + Vector vec = new Vector(); // Vector of Books 372 | + try { 373 | + // Prepare SQL 374 | + Connection con = getConnection(); 375 | + //The following is the original, unoptimized best sellers query. 376 | + PreparedStatement statement = con.prepareStatement 377 | + (@sql.getBestSellers@); 378 | + //This is Mikko's optimized version, which depends on the fact that 379 | + //A table named "bestseller" has been created. 380 | + /*PreparedStatement statement = con.prepareStatement 381 | + ("SELECT bestseller.i_id, i_title, a_fname, a_lname, ol_qty " + 382 | + "FROM item, bestseller, author WHERE item.i_subject = ?" + 383 | + " AND item.i_id = bestseller.i_id AND item.i_a_id = author.a_id " + 384 | + " ORDER BY ol_qty DESC FETCH FIRST 50 ROWS ONLY");*/ 385 | + 386 | + // Set parameter 387 | + statement.setString(1, subject); 388 | + ResultSet rs = statement.executeQuery(); 389 | + 390 | + // Results 391 | + while(rs.next()) { 392 | + vec.addElement(new ShortBook(rs)); 393 | + } 394 | + rs.close(); 395 | + statement.close(); 396 | + con.commit(); 397 | + returnConnection(con); 398 | + } catch (java.lang.Exception ex) { 399 | + ex.printStackTrace(); 400 | + } 401 | + return vec; 402 | + } 403 | + 404 | + public static void getRelated(int i_id, Vector i_id_vec, Vector i_thumbnail_vec) { 405 | + try { 406 | + // Prepare SQL 407 | + Connection con = getConnection(); 408 | + PreparedStatement statement = con.prepareStatement 409 | + (@sql.getRelated@); 410 | + 411 | + // Set parameter 412 | + statement.setInt(1, i_id); 413 | + ResultSet rs = statement.executeQuery(); 414 | + 415 | + // Clear the vectors 416 | + i_id_vec.removeAllElements(); 417 | + i_thumbnail_vec.removeAllElements(); 418 | + 419 | + // Results 420 | + while(rs.next()) { 421 | + i_id_vec.addElement(new Integer(rs.getInt(1))); 422 | + i_thumbnail_vec.addElement(rs.getString(2)); 423 | + } 424 | + rs.close(); 425 | + statement.close(); 426 | + con.commit(); 427 | + returnConnection(con); 428 | + } catch (java.lang.Exception ex) { 429 | + ex.printStackTrace(); 430 | + } 431 | + } 432 | + 433 | + public static void adminUpdate(int i_id, double cost, String image, String thumbnail) { 434 | + try { 435 | + // Prepare SQL 436 | + Connection con = getConnection(); 437 | + PreparedStatement statement = con.prepareStatement 438 | + (@sql.adminUpdate@); 439 | + 440 | + // Set parameter 441 | + statement.setDouble(1, cost); 442 | + statement.setString(2, image); 443 | + statement.setString(3, thumbnail); 444 | + statement.setInt(4, i_id); 445 | + statement.executeUpdate(); 446 | + statement.close(); 447 | + PreparedStatement related = con.prepareStatement 448 | + (@sql.adminUpdate.related@); 449 | + 450 | + // Set parameter 451 | + related.setInt(1, i_id); 452 | + related.setInt(2, i_id); 453 | + ResultSet rs = related.executeQuery(); 454 | + 455 | + int[] related_items = new int[5]; 456 | + // Results 457 | + int counter = 0; 458 | + int last = 0; 459 | + while(rs.next()) { 460 | + last = rs.getInt(1); 461 | + related_items[counter] = last; 462 | + counter++; 463 | + } 464 | + 465 | + // This is the case for the situation where there are not 5 related books. 466 | + for (int i=counter; i<5; i++) { 467 | + last++; 468 | + related_items[i] = last; 469 | + } 470 | + rs.close(); 471 | + related.close(); 472 | + 473 | + { 474 | + // Prepare SQL 475 | + statement = con.prepareStatement 476 | + (@sql.adminUpdate.related1@); 477 | + 478 | + // Set parameter 479 | + statement.setInt(1, related_items[0]); 480 | + statement.setInt(2, related_items[1]); 481 | + statement.setInt(3, related_items[2]); 482 | + statement.setInt(4, related_items[3]); 483 | + statement.setInt(5, related_items[4]); 484 | + statement.setInt(6, i_id); 485 | + statement.executeUpdate(); 486 | + } 487 | + statement.close(); 488 | + con.commit(); 489 | + returnConnection(con); 490 | + } catch (java.lang.Exception ex) { 491 | + ex.printStackTrace(); 492 | + } 493 | + } 494 | + 495 | + public static String GetUserName(int C_ID){ 496 | + String u_name = null; 497 | + try { 498 | + // Prepare SQL 499 | + Connection con = getConnection(); 500 | + PreparedStatement get_user_name = con.prepareStatement 501 | + (@sql.getUserName@); 502 | + 503 | + // Set parameter 504 | + get_user_name.setInt(1, C_ID); 505 | + ResultSet rs = get_user_name.executeQuery(); 506 | + 507 | + // Results 508 | + rs.next(); 509 | + u_name = rs.getString("c_uname"); 510 | + rs.close(); 511 | + 512 | + get_user_name.close(); 513 | + con.commit(); 514 | + returnConnection(con); 515 | + } catch (java.lang.Exception ex) { 516 | + ex.printStackTrace(); 517 | + } 518 | + return u_name; 519 | + } 520 | + 521 | + public static String GetPassword(String C_UNAME){ 522 | + String passwd = null; 523 | + try { 524 | + // Prepare SQL 525 | + Connection con = getConnection(); 526 | + PreparedStatement get_passwd = con.prepareStatement 527 | + (@sql.getPassword@); 528 | + 529 | + // Set parameter 530 | + get_passwd.setString(1, C_UNAME); 531 | + ResultSet rs = get_passwd.executeQuery(); 532 | + 533 | + // Results 534 | + rs.next(); 535 | + passwd = rs.getString("c_passwd"); 536 | + rs.close(); 537 | + 538 | + get_passwd.close(); 539 | + con.commit(); 540 | + returnConnection(con); 541 | + } catch (java.lang.Exception ex) { 542 | + ex.printStackTrace(); 543 | + } 544 | + return passwd; 545 | + } 546 | + 547 | + //This function gets the value of I_RELATED1 for the row of 548 | + //the item table corresponding to I_ID 549 | + private static int getRelated1(int I_ID, Connection con){ 550 | + int related1 = -1; 551 | + try { 552 | + PreparedStatement statement = con.prepareStatement 553 | + (@sql.getRelated1@); 554 | + statement.setInt(1, I_ID); 555 | + ResultSet rs = statement.executeQuery(); 556 | + rs.next(); 557 | + related1 = rs.getInt(1);//Is 1 the correct index? 558 | + rs.close(); 559 | + statement.close(); 560 | + 561 | + }catch (java.lang.Exception ex) { 562 | + ex.printStackTrace(); 563 | + } 564 | + return related1; 565 | + } 566 | + 567 | + public static Order GetMostRecentOrder(String c_uname, Vector order_lines){ 568 | + try { 569 | + order_lines.removeAllElements(); 570 | + int order_id; 571 | + Order order; 572 | + 573 | + // Prepare SQL 574 | + Connection con = getConnection(); 575 | + 576 | + // System.out.println("cust_id: " + getCustomer(c_uname).c_id); 577 | + 578 | + { 579 | + // *** Get the o_id of the most recent order for this user 580 | + PreparedStatement get_most_recent_order_id = con.prepareStatement 581 | + (@sql.getMostRecentOrder.id@); 582 | + 583 | + // Set parameter 584 | + get_most_recent_order_id.setString(1, c_uname); 585 | + ResultSet rs = get_most_recent_order_id.executeQuery(); 586 | + 587 | + if (rs.next()) { 588 | + order_id = rs.getInt("o_id"); 589 | + } else { 590 | + // There is no most recent order 591 | + rs.close(); 592 | + get_most_recent_order_id.close(); 593 | + con.commit(); 594 | + returnConnection(con); 595 | + return null; 596 | + } 597 | + rs.close(); 598 | + get_most_recent_order_id.close(); 599 | + } 600 | + 601 | + { 602 | + // *** Get the order info for this o_id 603 | + PreparedStatement get_order = con.prepareStatement 604 | + (@sql.getMostRecentOrder.order@); 605 | + 606 | + // Set parameter 607 | + get_order.setInt(1, order_id); 608 | + ResultSet rs2 = get_order.executeQuery(); 609 | + 610 | + // Results 611 | + if (!rs2.next()) { 612 | + // FIXME - This case is due to an error due to a database population error 613 | + con.commit(); 614 | + rs2.close(); 615 | + // get_order.close(); 616 | + returnConnection(con); 617 | + return null; 618 | + } 619 | + order = new Order(rs2); 620 | + rs2.close(); 621 | + get_order.close(); 622 | + } 623 | + 624 | + { 625 | + // *** Get the order_lines for this o_id 626 | + PreparedStatement get_order_lines = con.prepareStatement 627 | + (@sql.getMostRecentOrder.lines@); 628 | + 629 | + // Set parameter 630 | + get_order_lines.setInt(1, order_id); 631 | + ResultSet rs3 = get_order_lines.executeQuery(); 632 | + 633 | + // Results 634 | + while(rs3.next()) { 635 | + order_lines.addElement(new OrderLine(rs3)); 636 | + } 637 | + rs3.close(); 638 | + get_order_lines.close(); 639 | + } 640 | + 641 | + con.commit(); 642 | + returnConnection(con); 643 | + return order; 644 | + } catch (java.lang.Exception ex) { 645 | + ex.printStackTrace(); 646 | + } 647 | + return null; 648 | + } 649 | + 650 | + // ********************** Shopping Cart code below ************************* 651 | + 652 | + // Called from: TPCW_shopping_cart_interaction 653 | + public static int createEmptyCart(){ 654 | + int SHOPPING_ID = 0; 655 | + // boolean success = false; 656 | + Connection con = null; 657 | + try { 658 | + con = getConnection(); 659 | + } 660 | + catch (java.lang.Exception ex) { 661 | + ex.printStackTrace(); 662 | + } 663 | + 664 | + //while(success == false) { 665 | + try { 666 | + PreparedStatement get_next_id = con.prepareStatement 667 | + (@sql.createEmptyCart@); 668 | + synchronized(Cart.class) { 669 | + ResultSet rs = get_next_id.executeQuery(); 670 | + rs.next(); 671 | + SHOPPING_ID = rs.getInt(1); 672 | + rs.close(); 673 | + 674 | + PreparedStatement insert_cart = con.prepareStatement 675 | + (@sql.createEmptyCart.insert@); 676 | + insert_cart.executeUpdate(); 677 | + get_next_id.close(); 678 | + con.commit(); 679 | + } 680 | + returnConnection(con); 681 | + }catch (java.lang.Exception ex) { 682 | + ex.printStackTrace(); 683 | + } 684 | + return SHOPPING_ID; 685 | + } 686 | + 687 | + public static Cart doCart(int SHOPPING_ID, Integer I_ID, Vector ids, Vector quantities) { 688 | + Cart cart = null; 689 | + try { 690 | + Connection con = getConnection(); 691 | + 692 | + if (I_ID != null) { 693 | + addItem(con, SHOPPING_ID, I_ID.intValue()); 694 | + } 695 | + refreshCart(con, SHOPPING_ID, ids, quantities); 696 | + addRandomItemToCartIfNecessary(con, SHOPPING_ID); 697 | + resetCartTime(con, SHOPPING_ID); 698 | + cart = TPCW_Database.getCart(con, SHOPPING_ID, 0.0); 699 | + 700 | + // Close connection 701 | + con.commit(); 702 | + returnConnection(con); 703 | + } catch (java.lang.Exception ex) { 704 | + ex.printStackTrace(); 705 | + } 706 | + return cart; 707 | + } 708 | + 709 | + //This function finds the shopping cart item associated with SHOPPING_ID 710 | + //and I_ID. If the item does not already exist, we create one with QTY=1, 711 | + //otherwise we increment the quantity. 712 | + 713 | + private static void addItem(Connection con, int SHOPPING_ID, int I_ID){ 714 | + try { 715 | + // Prepare SQL 716 | + PreparedStatement find_entry = con.prepareStatement 717 | + (@sql.addItem@); 718 | + 719 | + // Set parameter 720 | + find_entry.setInt(1, SHOPPING_ID); 721 | + find_entry.setInt(2, I_ID); 722 | + ResultSet rs = find_entry.executeQuery(); 723 | + 724 | + // Results 725 | + if(rs.next()) { 726 | + //The shopping cart id, item pair were already in the table 727 | + int currqty = rs.getInt("scl_qty"); 728 | + currqty+=1; 729 | + PreparedStatement update_qty = con.prepareStatement 730 | + (@sql.addItem.update@); 731 | + update_qty.setInt(1, currqty); 732 | + update_qty.setInt(2, SHOPPING_ID); 733 | + update_qty.setInt(3, I_ID); 734 | + update_qty.executeUpdate(); 735 | + update_qty.close(); 736 | + } else {//We need to add a new row to the table. 737 | + 738 | + //Stick the item info in a new shopping_cart_line 739 | + PreparedStatement put_line = con.prepareStatement 740 | + (@sql.addItem.put@); 741 | + put_line.setInt(1, SHOPPING_ID); 742 | + put_line.setInt(2, 1); 743 | + put_line.setInt(3, I_ID); 744 | + put_line.executeUpdate(); 745 | + put_line.close(); 746 | + } 747 | + rs.close(); 748 | + find_entry.close(); 749 | + } catch (java.lang.Exception ex) { 750 | + ex.printStackTrace(); 751 | + } 752 | + } 753 | + 754 | + private static void refreshCart(Connection con, int SHOPPING_ID, Vector ids, 755 | + Vector quantities){ 756 | + int i; 757 | + try { 758 | + for(i = 0; i < ids.size(); i++){ 759 | + String I_IDstr = (String) ids.elementAt(i); 760 | + String QTYstr = (String) quantities.elementAt(i); 761 | + int I_ID = Integer.parseInt(I_IDstr); 762 | + int QTY = Integer.parseInt(QTYstr); 763 | + 764 | + if(QTY == 0) { // We need to remove the item from the cart 765 | + PreparedStatement statement = con.prepareStatement 766 | + (@sql.refreshCart.remove@); 767 | + statement.setInt(1, SHOPPING_ID); 768 | + statement.setInt(2, I_ID); 769 | + statement.executeUpdate(); 770 | + statement.close(); 771 | + } 772 | + else { //we update the quantity 773 | + PreparedStatement statement = con.prepareStatement 774 | + (@sql.refreshCart.update@); 775 | + statement.setInt(1, QTY); 776 | + statement.setInt(2, SHOPPING_ID); 777 | + statement.setInt(3, I_ID); 778 | + statement.executeUpdate(); 779 | + statement.close(); 780 | + } 781 | + } 782 | + } catch (java.lang.Exception ex) { 783 | + ex.printStackTrace(); 784 | + } 785 | + } 786 | + 787 | + private static void addRandomItemToCartIfNecessary(Connection con, int SHOPPING_ID){ 788 | + // check and see if the cart is empty. If it's not, we do 789 | + // nothing. 790 | + int related_item = 0; 791 | + 792 | + try { 793 | + // Check to see if the cart is empty 794 | + PreparedStatement get_cart = con.prepareStatement 795 | + (@sql.addRandomItemToCartIfNecessary@); 796 | + get_cart.setInt(1, SHOPPING_ID); 797 | + ResultSet rs = get_cart.executeQuery(); 798 | + rs.next(); 799 | + if (rs.getInt(1) == 0) { 800 | + // Cart is empty 801 | + int rand_id = TPCW_Util.getRandomI_ID(); 802 | + related_item = getRelated1(rand_id,con); 803 | + addItem(con, SHOPPING_ID, related_item); 804 | + } 805 | + 806 | + rs.close(); 807 | + get_cart.close(); 808 | + }catch (java.lang.Exception ex) { 809 | + ex.printStackTrace(); 810 | + System.out.println("Adding entry to shopping cart failed: shopping id = " + SHOPPING_ID + " related_item = " + related_item); 811 | + } 812 | + } 813 | + 814 | + 815 | + // Only called from this class 816 | + private static void resetCartTime(Connection con, int SHOPPING_ID){ 817 | + try { 818 | + PreparedStatement statement = con.prepareStatement 819 | + (@sql.resetCartTime@); 820 | + 821 | + // Set parameter 822 | + statement.setInt(1, SHOPPING_ID); 823 | + statement.executeUpdate(); 824 | + statement.close(); 825 | + }catch (java.lang.Exception ex) { 826 | + ex.printStackTrace(); 827 | + } 828 | + } 829 | + 830 | + public static Cart getCart(int SHOPPING_ID, double c_discount) { 831 | + Cart mycart = null; 832 | + try { 833 | + Connection con = getConnection(); 834 | + mycart = getCart(con, SHOPPING_ID, c_discount); 835 | + con.commit(); 836 | + returnConnection(con); 837 | + }catch (java.lang.Exception ex) { 838 | + ex.printStackTrace(); 839 | + } 840 | + return mycart; 841 | + } 842 | + 843 | + //time .05s 844 | + private static Cart getCart(Connection con, int SHOPPING_ID, double c_discount){ 845 | + Cart mycart = null; 846 | + try { 847 | + PreparedStatement get_cart = con.prepareStatement 848 | + (@sql.getCart@); 849 | + get_cart.setInt(1, SHOPPING_ID); 850 | + ResultSet rs = get_cart.executeQuery(); 851 | + mycart = new Cart(rs, c_discount); 852 | + rs.close(); 853 | + get_cart.close(); 854 | + }catch (java.lang.Exception ex) { 855 | + ex.printStackTrace(); 856 | + } 857 | + return mycart; 858 | + } 859 | + 860 | + // ************** Customer / Order code below ************************* 861 | + 862 | + //This should probably return an error code if the customer 863 | + //doesn't exist, but ... 864 | + public static void refreshSession(int C_ID) { 865 | + try { 866 | + // Prepare SQL 867 | + Connection con = getConnection(); 868 | + PreparedStatement updateLogin = con.prepareStatement 869 | + (@sql.refreshSession@); 870 | + 871 | + // Set parameter 872 | + updateLogin.setInt(1, C_ID); 873 | + updateLogin.executeUpdate(); 874 | + 875 | + con.commit(); 876 | + updateLogin.close(); 877 | + returnConnection(con); 878 | + } catch (java.lang.Exception ex) { 879 | + ex.printStackTrace(); 880 | + } 881 | + } 882 | + 883 | + public static Customer createNewCustomer(Customer cust) { 884 | + try { 885 | + // Get largest customer ID already in use. 886 | + Connection con = getConnection(); 887 | + 888 | + cust.c_discount = (int) (java.lang.Math.random() * 51); 889 | + cust.c_balance =0.0; 890 | + cust.c_ytd_pmt = 0.0; 891 | + // FIXME - Use SQL CURRENT_TIME to do this 892 | + cust.c_last_visit = new Date(System.currentTimeMillis()); 893 | + cust.c_since = new Date(System.currentTimeMillis()); 894 | + cust.c_login = new Date(System.currentTimeMillis()); 895 | + cust.c_expiration = new Date(System.currentTimeMillis() + 896 | + 7200000);//milliseconds in 2 hours 897 | + PreparedStatement insert_customer_row = con.prepareStatement 898 | + (@sql.createNewCustomer@); 899 | + insert_customer_row.setString(4,cust.c_fname); 900 | + insert_customer_row.setString(5,cust.c_lname); 901 | + insert_customer_row.setString(7,cust.c_phone); 902 | + insert_customer_row.setString(8,cust.c_email); 903 | + insert_customer_row.setDate(9, new 904 | + java.sql.Date(cust.c_since.getTime())); 905 | + insert_customer_row.setDate(10, new java.sql.Date(cust.c_last_visit.getTime())); 906 | + insert_customer_row.setDate(11, new java.sql.Date(cust.c_login.getTime())); 907 | + insert_customer_row.setDate(12, new java.sql.Date(cust.c_expiration.getTime())); 908 | + insert_customer_row.setDouble(13, cust.c_discount); 909 | + insert_customer_row.setDouble(14, cust.c_balance); 910 | + insert_customer_row.setDouble(15, cust.c_ytd_pmt); 911 | + insert_customer_row.setDate(16, new java.sql.Date(cust.c_birthdate.getTime())); 912 | + insert_customer_row.setString(17, cust.c_data); 913 | + 914 | + cust.addr_id = enterAddress(con, 915 | + cust.addr_street1, 916 | + cust.addr_street2, 917 | + cust.addr_city, 918 | + cust.addr_state, 919 | + cust.addr_zip, 920 | + cust.co_name); 921 | + PreparedStatement get_max_id = con.prepareStatement 922 | + (@sql.createNewCustomer.maxId@); 923 | + 924 | + synchronized(Customer.class) { 925 | + // Set parameter 926 | + ResultSet rs = get_max_id.executeQuery(); 927 | + 928 | + // Results 929 | + rs.next(); 930 | + cust.c_id = rs.getInt(1);//Is 1 the correct index? 931 | + rs.close(); 932 | + cust.c_id+=1; 933 | + cust.c_uname = TPCW_Util.DigSyl(cust.c_id, 0); 934 | + cust.c_passwd = cust.c_uname.toLowerCase(); 935 | + 936 | + 937 | + insert_customer_row.setInt(1, cust.c_id); 938 | + insert_customer_row.setString(2,cust.c_uname); 939 | + insert_customer_row.setString(3,cust.c_passwd); 940 | + insert_customer_row.setInt(6, cust.addr_id); 941 | + insert_customer_row.executeUpdate(); 942 | + con.commit(); 943 | + insert_customer_row.close(); 944 | + } 945 | + get_max_id.close(); 946 | + returnConnection(con); 947 | + } catch (java.lang.Exception ex) { 948 | + ex.printStackTrace(); 949 | + } 950 | + return cust; 951 | + } 952 | + 953 | + //BUY CONFIRM 954 | + 955 | + public static BuyConfirmResult doBuyConfirm(int shopping_id, 956 | + int customer_id, 957 | + String cc_type, 958 | + long cc_number, 959 | + String cc_name, 960 | + Date cc_expiry, 961 | + String shipping) { 962 | + 963 | + BuyConfirmResult result = new BuyConfirmResult(); 964 | + try { 965 | + Connection con = getConnection(); 966 | + double c_discount = getCDiscount(con, customer_id); 967 | + result.cart = getCart(con, shopping_id, c_discount); 968 | + int ship_addr_id = getCAddr(con, customer_id); 969 | + result.order_id = enterOrder(con, customer_id, result.cart, ship_addr_id, shipping, c_discount); 970 | + enterCCXact(con, result.order_id, cc_type, cc_number, cc_name, cc_expiry, result.cart.SC_TOTAL, ship_addr_id); 971 | + clearCart(con, shopping_id); 972 | + con.commit(); 973 | + returnConnection(con); 974 | + } catch (java.lang.Exception ex) { 975 | + ex.printStackTrace(); 976 | + } 977 | + return result; 978 | + } 979 | + 980 | + public static BuyConfirmResult doBuyConfirm(int shopping_id, 981 | + int customer_id, 982 | + String cc_type, 983 | + long cc_number, 984 | + String cc_name, 985 | + Date cc_expiry, 986 | + String shipping, 987 | + String street_1, String street_2, 988 | + String city, String state, 989 | + String zip, String country) { 990 | + 991 | + 992 | + BuyConfirmResult result = new BuyConfirmResult(); 993 | + try { 994 | + Connection con = getConnection(); 995 | + double c_discount = getCDiscount(con, customer_id); 996 | + result.cart = getCart(con, shopping_id, c_discount); 997 | + int ship_addr_id = enterAddress(con, street_1, street_2, city, state, zip, country); 998 | + result.order_id = enterOrder(con, customer_id, result.cart, ship_addr_id, shipping, c_discount); 999 | + enterCCXact(con, result.order_id, cc_type, cc_number, cc_name, cc_expiry, result.cart.SC_TOTAL, ship_addr_id); 1000 | + clearCart(con, shopping_id); 1001 | + con.commit(); 1002 | + returnConnection(con); 1003 | + } catch (java.lang.Exception ex) { 1004 | + ex.printStackTrace(); 1005 | + } 1006 | + return result; 1007 | + } 1008 | + 1009 | + 1010 | + //DB query time: .05s 1011 | + public static double getCDiscount(Connection con, int c_id) { 1012 | + double c_discount = 0.0; 1013 | + try { 1014 | + // Prepare SQL 1015 | + PreparedStatement statement = con.prepareStatement 1016 | + (@sql.getCDiscount@); 1017 | + 1018 | + // Set parameter 1019 | + statement.setInt(1, c_id); 1020 | + ResultSet rs = statement.executeQuery(); 1021 | + 1022 | + // Results 1023 | + rs.next(); 1024 | + c_discount = rs.getDouble(1); 1025 | + rs.close(); 1026 | + statement.close(); 1027 | + } catch (java.lang.Exception ex) { 1028 | + ex.printStackTrace(); 1029 | + } 1030 | + return c_discount; 1031 | + } 1032 | + 1033 | + //DB time: .05s 1034 | + public static int getCAddrID(Connection con, int c_id) { 1035 | + int c_addr_id = 0; 1036 | + try { 1037 | + // Prepare SQL 1038 | + PreparedStatement statement = con.prepareStatement 1039 | + (@sql.getCAddrId@); 1040 | + 1041 | + // Set parameter 1042 | + statement.setInt(1, c_id); 1043 | + ResultSet rs = statement.executeQuery(); 1044 | + 1045 | + // Results 1046 | + rs.next(); 1047 | + c_addr_id = rs.getInt(1); 1048 | + rs.close(); 1049 | + statement.close(); 1050 | + } catch (java.lang.Exception ex) { 1051 | + ex.printStackTrace(); 1052 | + } 1053 | + return c_addr_id; 1054 | + } 1055 | + 1056 | + public static int getCAddr(Connection con, int c_id) { 1057 | + int c_addr_id = 0; 1058 | + try { 1059 | + // Prepare SQL 1060 | + PreparedStatement statement = con.prepareStatement 1061 | + (@sql.getCAddr@); 1062 | + 1063 | + // Set parameter 1064 | + statement.setInt(1, c_id); 1065 | + ResultSet rs = statement.executeQuery(); 1066 | + 1067 | + // Results 1068 | + rs.next(); 1069 | + c_addr_id = rs.getInt(1); 1070 | + rs.close(); 1071 | + statement.close(); 1072 | + } catch (java.lang.Exception ex) { 1073 | + ex.printStackTrace(); 1074 | + } 1075 | + return c_addr_id; 1076 | + } 1077 | + 1078 | + public static void enterCCXact(Connection con, 1079 | + int o_id, // Order id 1080 | + String cc_type, 1081 | + long cc_number, 1082 | + String cc_name, 1083 | + Date cc_expiry, 1084 | + double total, // Total from shopping cart 1085 | + int ship_addr_id) { 1086 | + 1087 | + // Updates the CC_XACTS table 1088 | + if(cc_type.length() > 10) 1089 | + cc_type = cc_type.substring(0,10); 1090 | + if(cc_name.length() > 30) 1091 | + cc_name = cc_name.substring(0,30); 1092 | + 1093 | + try { 1094 | + // Prepare SQL 1095 | + PreparedStatement statement = con.prepareStatement 1096 | + (@sql.enterCCXact@); 1097 | + 1098 | + // Set parameter 1099 | + statement.setInt(1, o_id); // cx_o_id 1100 | + statement.setString(2, cc_type); // cx_type 1101 | + statement.setLong(3, cc_number); // cx_num 1102 | + statement.setString(4, cc_name); // cx_name 1103 | + statement.setDate(5, cc_expiry); // cx_expiry 1104 | + statement.setDouble(6, total); // cx_xact_amount 1105 | + statement.setInt(7, ship_addr_id); // ship_addr_id 1106 | + statement.executeUpdate(); 1107 | + statement.close(); 1108 | + } catch (java.lang.Exception ex) { 1109 | + ex.printStackTrace(); 1110 | + } 1111 | + } 1112 | + 1113 | + public static void clearCart(Connection con, int shopping_id) { 1114 | + // Empties all the lines from the shopping_cart_line for the 1115 | + // shopping id. Does not remove the actually shopping cart 1116 | + try { 1117 | + // Prepare SQL 1118 | + PreparedStatement statement = con.prepareStatement 1119 | + (@sql.clearCart@); 1120 | + 1121 | + // Set parameter 1122 | + statement.setInt(1, shopping_id); 1123 | + statement.executeUpdate(); 1124 | + statement.close(); 1125 | + } catch (java.lang.Exception ex) { 1126 | + ex.printStackTrace(); 1127 | + } 1128 | + } 1129 | + 1130 | + public static int enterAddress(Connection con, // Do we need to do this as part of a transaction? 1131 | + String street1, String street2, 1132 | + String city, String state, 1133 | + String zip, String country) { 1134 | + // returns the address id of the specified address. Adds a 1135 | + // new address to the table if needed 1136 | + int addr_id = 0; 1137 | + 1138 | + // Get the country ID from the country table matching this address. 1139 | + 1140 | + // Is it safe to assume that the country that we are looking 1141 | + // for will be there? 1142 | + try { 1143 | + PreparedStatement get_co_id = con.prepareStatement 1144 | + (@sql.enterAddress.id@); 1145 | + get_co_id.setString(1, country); 1146 | + ResultSet rs = get_co_id.executeQuery(); 1147 | + rs.next(); 1148 | + int addr_co_id = rs.getInt("co_id"); 1149 | + rs.close(); 1150 | + get_co_id.close(); 1151 | + 1152 | + //Get address id for this customer, possible insert row in 1153 | + //address table 1154 | + PreparedStatement match_address = con.prepareStatement 1155 | + (@sql.enterAddress.match@); 1156 | + match_address.setString(1, street1); 1157 | + match_address.setString(2, street2); 1158 | + match_address.setString(3, city); 1159 | + match_address.setString(4, state); 1160 | + match_address.setString(5, zip); 1161 | + match_address.setInt(6, addr_co_id); 1162 | + rs = match_address.executeQuery(); 1163 | + if(!rs.next()){//We didn't match an address in the addr table 1164 | + PreparedStatement insert_address_row = con.prepareStatement 1165 | + (@sql.enterAddress.insert@); 1166 | + insert_address_row.setString(2, street1); 1167 | + insert_address_row.setString(3, street2); 1168 | + insert_address_row.setString(4, city); 1169 | + insert_address_row.setString(5, state); 1170 | + insert_address_row.setString(6, zip); 1171 | + insert_address_row.setInt(7, addr_co_id); 1172 | + 1173 | + PreparedStatement get_max_addr_id = con.prepareStatement 1174 | + (@sql.enterAddress.maxId@); 1175 | + synchronized(Address.class) { 1176 | + ResultSet rs2 = get_max_addr_id.executeQuery(); 1177 | + rs2.next(); 1178 | + addr_id = rs2.getInt(1)+1; 1179 | + rs2.close(); 1180 | + //Need to insert a new row in the address table 1181 | + insert_address_row.setInt(1, addr_id); 1182 | + insert_address_row.executeUpdate(); 1183 | + } 1184 | + get_max_addr_id.close(); 1185 | + insert_address_row.close(); 1186 | + } else { //We actually matched 1187 | + addr_id = rs.getInt("addr_id"); 1188 | + } 1189 | + match_address.close(); 1190 | + rs.close(); 1191 | + } catch (java.lang.Exception ex) { 1192 | + ex.printStackTrace(); 1193 | + } 1194 | + return addr_id; 1195 | + } 1196 | + 1197 | + 1198 | + public static int enterOrder(Connection con, int customer_id, Cart cart, int ship_addr_id, String shipping, double c_discount) { 1199 | + // returns the new order_id 1200 | + int o_id = 0; 1201 | + // - Creates an entry in the 'orders' table 1202 | + try { 1203 | + PreparedStatement insert_row = con.prepareStatement 1204 | + (@sql.enterOrder.insert@); 1205 | + insert_row.setInt(2, customer_id); 1206 | + insert_row.setDouble(3, cart.SC_SUB_TOTAL); 1207 | + insert_row.setDouble(4, cart.SC_TOTAL); 1208 | + insert_row.setString(5, shipping); 1209 | + insert_row.setInt(6, TPCW_Util.getRandom(7)); 1210 | + insert_row.setInt(7, getCAddrID(con, customer_id)); 1211 | + insert_row.setInt(8, ship_addr_id); 1212 | + 1213 | + PreparedStatement get_max_id = con.prepareStatement 1214 | + (@sql.enterOrder.maxId@); 1215 | + //selecting from order_line is really slow! 1216 | + synchronized(Order.class) { 1217 | + ResultSet rs = get_max_id.executeQuery(); 1218 | + rs.next(); 1219 | + o_id = rs.getInt(1) + 1; 1220 | + rs.close(); 1221 | + 1222 | + insert_row.setInt(1, o_id); 1223 | + insert_row.executeUpdate(); 1224 | + } 1225 | + get_max_id.close(); 1226 | + insert_row.close(); 1227 | + } catch (java.lang.Exception ex) { 1228 | + ex.printStackTrace(); 1229 | + } 1230 | + 1231 | + Enumeration e = cart.lines.elements(); 1232 | + int counter = 0; 1233 | + while(e.hasMoreElements()) { 1234 | + // - Creates one or more 'order_line' rows. 1235 | + CartLine cart_line = (CartLine) e.nextElement(); 1236 | + addOrderLine(con, counter, o_id, cart_line.scl_i_id, 1237 | + cart_line.scl_qty, c_discount, 1238 | + TPCW_Util.getRandomString(20, 100)); 1239 | + counter++; 1240 | + 1241 | + // - Adjusts the stock for each item ordered 1242 | + int stock = getStock(con, cart_line.scl_i_id); 1243 | + if ((stock - cart_line.scl_qty) < 10) { 1244 | + setStock(con, cart_line.scl_i_id, 1245 | + stock - cart_line.scl_qty + 21); 1246 | + } else { 1247 | + setStock(con, cart_line.scl_i_id, stock - cart_line.scl_qty); 1248 | + } 1249 | + } 1250 | + return o_id; 1251 | + } 1252 | + 1253 | + public static void addOrderLine(Connection con, 1254 | + int ol_id, int ol_o_id, int ol_i_id, 1255 | + int ol_qty, double ol_discount, String ol_comment) { 1256 | + int success = 0; 1257 | + try { 1258 | + PreparedStatement insert_row = con.prepareStatement 1259 | + (@sql.addOrderLine@); 1260 | + 1261 | + insert_row.setInt(1, ol_id); 1262 | + insert_row.setInt(2, ol_o_id); 1263 | + insert_row.setInt(3, ol_i_id); 1264 | + insert_row.setInt(4, ol_qty); 1265 | + insert_row.setDouble(5, ol_discount); 1266 | + insert_row.setString(6, ol_comment); 1267 | + insert_row.executeUpdate(); 1268 | + insert_row.close(); 1269 | + } catch (java.lang.Exception ex) { 1270 | + ex.printStackTrace(); 1271 | + } 1272 | + } 1273 | + 1274 | + public static int getStock(Connection con, int i_id) { 1275 | + int stock = 0; 1276 | + try { 1277 | + PreparedStatement get_stock = con.prepareStatement 1278 | + (@sql.getStock@); 1279 | + 1280 | + // Set parameter 1281 | + get_stock.setInt(1, i_id); 1282 | + ResultSet rs = get_stock.executeQuery(); 1283 | + 1284 | + // Results 1285 | + rs.next(); 1286 | + stock = rs.getInt("i_stock"); 1287 | + rs.close(); 1288 | + get_stock.close(); 1289 | + } catch (java.lang.Exception ex) { 1290 | + ex.printStackTrace(); 1291 | + } 1292 | + return stock; 1293 | + } 1294 | + 1295 | + public static void setStock(Connection con, int i_id, int new_stock) { 1296 | + try { 1297 | + PreparedStatement update_row = con.prepareStatement 1298 | + (@sql.setStock@); 1299 | + update_row.setInt(1, new_stock); 1300 | + update_row.setInt(2, i_id); 1301 | + update_row.executeUpdate(); 1302 | + update_row.close(); 1303 | + } catch (java.lang.Exception ex) { 1304 | + ex.printStackTrace(); 1305 | + } 1306 | + } 1307 | + 1308 | + public static void verifyDBConsistency(){ 1309 | + try { 1310 | + Connection con = getConnection(); 1311 | + int this_id; 1312 | + int id_expected = 1; 1313 | + //First verify customer table 1314 | + PreparedStatement get_ids = con.prepareStatement 1315 | + (@sql.verifyDBConsistency.custId@); 1316 | + ResultSet rs = get_ids.executeQuery(); 1317 | + while(rs.next()){ 1318 | + this_id = rs.getInt("c_id"); 1319 | + while(this_id != id_expected){ 1320 | + System.out.println("Missing C_ID " + id_expected); 1321 | + id_expected++; 1322 | + } 1323 | + id_expected++; 1324 | + } 1325 | + 1326 | + id_expected = 1; 1327 | + //Verify the item table 1328 | + get_ids = con.prepareStatement 1329 | + (@sql.verifyDBConsistency.itemId@); 1330 | + rs = get_ids.executeQuery(); 1331 | + while(rs.next()){ 1332 | + this_id = rs.getInt("i_id"); 1333 | + while(this_id != id_expected){ 1334 | + System.out.println("Missing I_ID " + id_expected); 1335 | + id_expected++; 1336 | + } 1337 | + id_expected++; 1338 | + } 1339 | + 1340 | + id_expected = 1; 1341 | + //Verify the address table 1342 | + get_ids = con.prepareStatement 1343 | + (@sql.verifyDBConsistency.addrId@); 1344 | + rs = get_ids.executeQuery(); 1345 | + while(rs.next()){ 1346 | + this_id = rs.getInt("addr_id"); 1347 | + // System.out.println(this_cid+"\n"); 1348 | + while(this_id != id_expected){ 1349 | + System.out.println("Missing ADDR_ID " + id_expected); 1350 | + id_expected++; 1351 | + } 1352 | + id_expected++; 1353 | + } 1354 | + 1355 | + 1356 | + 1357 | + con.commit(); 1358 | + returnConnection(con); 1359 | + } catch (java.lang.Exception ex) { 1360 | + ex.printStackTrace(); 1361 | + } 1362 | + } 1363 | +} 1364 | + 1365 | diff --git a/main.properties b/main.properties 1366 | index d34127b..6875cf6 100644 1367 | --- a/main.properties 1368 | +++ b/main.properties 1369 | @@ -10,13 +10,13 @@ 1370 | ############################################################################## 1371 | 1372 | # 1373 | -cpServ=/usr/share/java/servlet-2.3.jar 1374 | +cpServ=/usr/share/java/servlet-api-3.0.jar 1375 | 1376 | # 1377 | -cpJDBC=/usr/share/java/mkjdbc.jar 1378 | +cpJDBC=/home/ubuntu/elasticDB/tpcw/mysql-connector-java-5.1.32.jar 1379 | 1380 | # 1381 | -webappDir=/usr/share/tomcat4/dist/webapps 1382 | +webappDir=/var/lib/tomcat7/webapps 1383 | 1384 | # 1385 | perlPath=/usr/bin/perl 1386 | @@ -25,7 +25,7 @@ perlPath=/usr/bin/perl 1387 | imagesDir=${webappDir}/tpcw/Images 1388 | 1389 | # 1390 | -sqlFilter=sql-mckoi.properties 1391 | +sqlFilter=sql-mysql.properties 1392 | 1393 | #dbName=std 1394 | -dbName=mckoi 1395 | +dbName=tpcw 1396 | diff --git a/tpcw.properties b/tpcw.properties 1397 | index f8c2c06..2b1c9ca 100644 1398 | --- a/tpcw.properties 1399 | +++ b/tpcw.properties 1400 | @@ -11,16 +11,16 @@ 1401 | 1402 | # set the JDBC parameters 1403 | #jdbc.driver=com.mysql.jdbc.Driver 1404 | -jdbc.driver=com.mckoi.JDBCDriver 1405 | -jdbc.path=jdbc:mckoi://localhost/?user=admin&password=admin 1406 | +jdbc.driver=com.mysql.jdbc.Driver 1407 | +jdbc.path=jdbc:mysql://localhost:3306/tpcw?user=root&password=TigerBit!2016 1408 | jdbc.connPoolMax=100 1409 | 1410 | sql.bigCharType=varchar(500) 1411 | #sql.bigCharType=tinyblob 1412 | 1413 | # set the values you want for tpcw 1414 | -num.item=1000 1415 | -num.eb=10 1416 | +num.item=10000 1417 | +num.eb=100 1418 | 1419 | # use the right session string for your servlet container 1420 | #sessionIdString=$sessionid$ 1421 | --------------------------------------------------------------------------------