package org.mobicents.smsc.tools.stresstool;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ThreadLocalRandom;
import org.apache.log4j.Logger;
import org.mobicents.smsc.cassandra.PersistenceException;
import org.mobicents.smsc.cassandra.Schema;
import org.mobicents.smsc.library.Sms;
import org.mobicents.smsc.library.SmsSet;
import com.cloudhopper.smpp.tlv.Tlv;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
/**
* host, port, keyspace
* -hlocalhost -p9042 -ksaturn -mDataTableDaysTimeArea
* -s<smsSetRange>
* -c<recordCount> -t<threadCountW> -T<threadCountR>
* @author sergey vetuyutnev
*
*/
public class StressTool2 {
private String host = "localhost";
private int port = 9042;
private String keyspace = "saturn";
private int dataTableDaysTimeArea = 10;
private int smsSetRange = 10;
private int recordCount = 500000;
private int threadCountW = 0;
private int threadCountR = 10;
private CTask task = CTask.Live_Sms_Special;
private static final Logger logger = Logger.getLogger(StressTool2.class);
private String persistFile = "stresstool.xml";
private static final String TAB_INDENT = "\t";
private TT_DBOperationsProxy2 dbOperations;
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
StressTool2 tool = new StressTool2();
tool.start(args);
} catch (Exception e) {
logger.error("General exception: " + e.toString(), e);
e.printStackTrace();
}
}
});
}
public void start(String[] args) throws Exception {
this.parseParameters(args);
logInfo("Stress tool starting ...");
logInfo("host : " + host);
logInfo("port : " + port);
logInfo("keyspace : " + keyspace);
logInfo("dataTableDaysTimeArea : " + dataTableDaysTimeArea);
logInfo("smsSetRange : " + smsSetRange);
logInfo("recordCount : " + recordCount);
logInfo("threadCountW : " + threadCountW);
logInfo("threadCountR : " + threadCountR);
logInfo("task : " + task);
// -dDataTableDaysTimeArea
this.dbOperations = new TT_DBOperationsProxy2();
this.dbOperations.start(host, port, keyspace, dataTableDaysTimeArea, 30);
ProcessTask ta = null;
if (this.task == CTask.Live_Sms_Filling) {
ta = new TA();
// } else if (this.task == CTask.Live_Sms_Deleting) {
// ta = new TB();
} else if (this.task == CTask.Live_Sms_Cycle) {
ta = new TX();
} else if (this.task == CTask.Live_Sms_Special) {
TY1 ty1 = new TY1();
ta = ty1;
Thread t = new Thread(ty1);
t.start();
}
if (ta != null) {
while (!ta.isReady()) {
logInfo(ta.getResults());
Thread.sleep(10000);
}
}
this.dbOperations.stop();
}
private void logInfo(String s) {
logger.info(s);
System.out.print("\n");
System.out.print(s);
}
private void parseParameters(String[] args) {
for (String s : args) {
if(s.length()>2){
String s1 = s.substring(0, 2);
String s2 = s.substring(2);
if (s1.equals("-h")) {
this.host = s2;
} else if (s1.equals("-p")) {
this.port = Integer.parseInt(s2);
} else if (s1.equals("-k")) {
this.keyspace = s2;
} else if (s1.equals("-s")) {
this.smsSetRange = Integer.parseInt(s2);
} else if (s1.equals("-c")) {
this.recordCount = Integer.parseInt(s2);
} else if (s1.equals("-t")) {
this.threadCountW = Integer.parseInt(s2);
} else if (s1.equals("-T")) {
this.threadCountR = Integer.parseInt(s2);
} else if (s1.equals("-m")) {
this.dataTableDaysTimeArea = Integer.parseInt(s2);
} else if (s1.equals("-d")) {
if (s2.equals("a")) {
this.task = CTask.Live_Sms_Filling;
} else if (s2.equals("b")) {
this.task = CTask.Live_Sms_Deleting;
}
}
}
}
}
private String generateAddr() {
Integer res = ThreadLocalRandom.current().nextInt(this.smsSetRange) + 1000000000;
return res.toString();
}
enum CTask {
Live_Sms_Filling,
Live_Sms_Deleting,
Live_Sms_Cycle,
Live_Sms_Special,
};
class TA implements ProcessTask, Runnable {
private ArrayList<TA> threads = new ArrayList<TA>();
private int startNum;
private int endNum;
private int curNum;
private boolean ready;
private boolean isMaster = false;
public TA() {
isMaster = true;
int num = 1000000;
int step = recordCount / threadCountW;
for (int i1 = 0; i1 < threadCountW; i1++) {
TA ta = new TA(num, num + step);
num += step;
threads.add(ta);
Thread t = new Thread(ta);
t.start();
}
}
public TA(int startNum, int endNum) {
this.startNum = startNum;
this.endNum = endNum;
this.curNum = startNum;
}
@Override
public boolean isReady() {
if (this.isMaster) {
for (TA el : threads) {
if (!el.isReady())
return false;
}
return true;
} else
return ready;
}
@Override
public String getResults() {
int i1 = 0;
for (TA el : threads) {
i1 += el.curNum - el.startNum;
}
int i2 = recordCount;
return "Processed " + i1 + " out of " + i2;
}
@Override
public void run() {
// Date dt = new Date();
// try {
// dbOperations.getSmsListForDueSlot(dt, 22, 1000);
// } catch (PersistenceException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
try {
while (true) {
SmsSet smsSet = new SmsSet();
Integer ii1 = this.curNum;
String s1 = ii1.toString();
smsSet.setDestAddr(s1);
smsSet.setDestAddrNpi(1);
smsSet.setDestAddrTon(1);
Sms sms = new Sms();
sms.setSmsSet(smsSet);
sms.setMessageId(this.curNum);
sms.setDbId(UUID.randomUUID());
sms.setShortMessage(new byte[10]);
try {
Date dt = new Date();
long dueSlot = dbOperations.calculateSlot(dt);
dbOperations.createRecord(dueSlot, sms);
} catch (PersistenceException e) {
logger.error("Exception in task A: " + e.toString(), e);
}
this.curNum++;
if (this.curNum >= this.endNum)
break;
}
} finally {
ready = true;
}
}
@Override
public void terminate() {
// TODO Auto-generated method stub
}
}
class TX implements ProcessTask, Runnable {
private ArrayList<TX1> tx1 = new ArrayList<TX1>();
private TX2 tx2;
private ArrayList<TX3> tx3 = new ArrayList<TX3>();
public TX() {
if (threadCountW > 0) {
int num = 1000000;
int step = recordCount / threadCountW;
for (int i1 = 0; i1 < threadCountW; i1++) {
TX1 ta = new TX1(num, num + step);
num += step;
tx1.add(ta);
Thread t = new Thread(ta);
t.start();
}
}
if (threadCountR > 0) {
tx2 = new TX2(0, recordCount);
Thread t = new Thread(tx2);
t.start();
}
for (int i1 = 0; i1 < threadCountR; i1++) {
TX3 ta = new TX3();
tx3.add(ta);
Thread t = new Thread(ta);
t.start();
}
}
@Override
public boolean isReady() {
for (TX1 el : tx1) {
if (!el.isReady())
return false;
}
if (tx2 != null && !tx2.isReady())
return false;
return true;
}
@Override
public String getResults() {
int i1 = 0;
for (TX1 el : tx1) {
i1 += el.curNum - el.startNum;
}
int i2 = recordCount;
String s1 = "Processed TX1 " + i1 + " out of " + i2 + ", processed TX2 " + (tx2 != null ? (tx2.curNum) : "") + " out of "
+ (tx2 != null ? (tx2.endNum - tx2.startNum) : "") + ", queue=" + queue.size();
return s1;
}
@Override
public void run() {
}
@Override
public void terminate() {
// TODO Auto-generated method stub
}
}
class TX1 implements ProcessTask, Runnable {
private int startNum;
private int endNum;
private int curNum;
private boolean ready;
public TX1(int startNum, int endNum) {
this.startNum = startNum;
this.endNum = endNum;
this.curNum = startNum;
}
@Override
public boolean isReady() {
return ready;
}
@Override
public String getResults() {
return "";
}
@Override
public void run() {
try {
while (true) {
Integer ii1 = this.curNum;
String s1 = ii1.toString();
int messageId = 0;
try {
// long dueSlot = dbOperations.calculateSlot(dt);
SmsSet smsSet = new SmsSet();
smsSet.setDestAddr(s1);
smsSet.setDestAddrNpi(1);
smsSet.setDestAddrTon(1);
ArrayList<byte[]> bb = new ArrayList<byte[]>();
byte[] bf1 = new byte[10];
byte[] bf2 = new byte[20];
byte[] bf3 = new byte[30];
bf1[0] = 10;
bf2[1] = 20;
bf3[3] = 30;
bb.add(bf1);
bb.add(bf2);
bb.add(bf3);
for (int i1 = 0; i1 < 3; i1++) {
Sms sms = new Sms();
sms.setSmsSet(smsSet);
sms.setMessageId(this.curNum);
sms.setDbId(UUID.randomUUID());
sms.setShortMessage(bb.get(i1));
sms.setDataCoding(0);
sms.setEsmClass(20);
sms.setMessageId(++messageId);
sms.setMoMessageRef(13);
sms.setOrigEsmeName("A1");
sms.setOrigSystemId("E1");
sms.setPriority(3);
sms.setProtocolId(14);
sms.setRegisteredDelivery(15);
if (i1 == 0)
sms.setScheduleDeliveryTime(new Date());
Integer I2 = messageId + 20000;
sms.setSourceAddr(I2.toString());
sms.setSourceAddrNpi(4);
sms.setSourceAddrTon(1);
sms.setSubmitDate(new Date());
sms.setValidityPeriod(new Date(new Date().getTime() + 3600000 * 24));
if (i1 == 0) {
Tlv tlv = new Tlv((short) 0, bf3);
sms.getTlvSet().addOptionalParameter(tlv);
}
long dueSlot = dbOperations.calculateSlot(sms.getSubmitDate());
dbOperations.createRecord(dueSlot, sms);
}
} catch (PersistenceException e) {
logger.error("Exception in task X1: " + e.toString(), e);
}
this.curNum++;
if (this.curNum >= this.endNum)
break;
}
} finally {
ready = true;
}
}
@Override
public void terminate() {
// TODO Auto-generated method stub
}
}
private Queue<NN_LoadedTargetId> queue = new ConcurrentLinkedQueue<NN_LoadedTargetId>();
class TX2 implements ProcessTask, Runnable {
private int startNum;
private int endNum;
private int curNum;
private boolean ready;
public TX2(int startNum, int endNum) {
this.startNum = startNum;
this.endNum = endNum;
this.curNum = startNum;
}
@Override
public boolean isReady() {
return ready;
}
@Override
public String getResults() {
return "";
}
@Override
public void run() {
long curDueSlot = dbOperations.calculateSlot(new Date());
curDueSlot = curDueSlot - 1000;
try {
while (true) {
try {
int cnt = 1000;
List<NN_LoadedTargetId> lst = dbOperations.getTargetIdListForDueSlot(new Date[] { new Date() }, curDueSlot, curDueSlot + 2, cnt);
if (lst.size() == 0)
curDueSlot++;
this.curNum += lst.size();
for (NN_LoadedTargetId ti : lst) {
queue.add(ti);
}
} catch (PersistenceException e) {
logger.error("Exception in task X2: " + e.toString(), e);
}
if (this.curNum >= this.endNum)
break;
while (queue.size() > 10000) {
Thread.sleep(10);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
ready = true;
}
}
@Override
public void terminate() {
// TODO Auto-generated method stub
}
}
class TX3 implements ProcessTask, Runnable {
public TX3() {
}
@Override
public boolean isReady() {
return true;
}
@Override
public String getResults() {
return "";
}
@Override
public void run() {
while (true) {
NN_LoadedTargetId ti = queue.poll();
if (ti != null) {
try {
SmsSet smsSet = dbOperations.getSmsSetForTargetId(new Date[] { new Date() }, ti);
if (smsSet != null) {
long ii = smsSet.getSmsCount();
for (int i1 = 0; i1 < ii; i1++) {
Sms sms = smsSet.getSms(i1);
dbOperations.deleteIdFromDests(sms);
}
}
} catch (PersistenceException e) {
logger.error("Exception in task X3: " + e.toString(), e);
}
} else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@Override
public void terminate() {
// TODO Auto-generated method stub
}
}
class TY1 implements ProcessTask, Runnable {
private boolean ready = false;
public TY1() {
}
@Override
public boolean isReady() {
return ready;
}
@Override
public String getResults() {
String s1;
if (startD2 != null) {
long tm = (new Date()).getTime() - startD2.getTime();
s1 = "" + (tm / 1000);
} else {
s1 = "";
}
return step + ": " + a1 + " out of " + a2 + ", dur = " + s1;
}
long a1, a2;
String step = "";
Date startD2;
@Override
public void run() {
try {
int first_slot_cnt = 1;
int due_slot_cnt = 1000;
int inner_cnt = 1000;
int sol = 2; // 1-deleting, 2-extra field
int load_count = 1000;
dbOperations.getStatementCollection(new Date());
// filling SLOTS table
step = "Filling";
String sa = "INSERT INTO \"SLOTS_2013_12_01\" (\"DUE_SLOT\", \"TARGET_ID\", \"PROCESSED\") VALUES (?, ?, ?) USING TTL 300;";
String sa2 = "INSERT INTO \"SLOTS_2013_12_01\" (\"DUE_SLOT\", \"TARGET_ID\", \"PROCESSED\") VALUES (?, ?, ?);";
PreparedStatement ps = dbOperations.getSession().prepare(sa);
PreparedStatement psa = dbOperations.getSession().prepare(sa2);
a1 = 0;
a2 = due_slot_cnt * inner_cnt;
for (long i1 = first_slot_cnt; i1 < first_slot_cnt + due_slot_cnt; i1++) {
for (int i2 = 0; i2 < inner_cnt; i2++) {
BoundStatement boundStatement;
if (i1 < first_slot_cnt + due_slot_cnt - 10) {
boundStatement = new BoundStatement(ps);
} else {
boundStatement = new BoundStatement(psa);
}
Long I1 = i1 * 1000000L + 1000000000000L + i2;
boundStatement.bind((long) i1, I1.toString(), false);
ResultSet res = dbOperations.getSession().execute(boundStatement);
a1++;
}
}
// loading data
step = "Loading";
startD2 = new Date();
a1 = 0;
a2 = due_slot_cnt * inner_cnt;
long i2 = first_slot_cnt;
PreparedStatement ps2;
if (sol == 1) {
String sb = "SELECT \"TARGET_ID\" from \"SLOTS_2013_11_03\" where \"DUE_SLOT\"=? limit " + load_count + ";";
ps = dbOperations.getSession().prepare(sb);
String sb2 = "DELETE from \"SLOTS_2013_11_03\" where \"DUE_SLOT\"=? and \"TARGET_ID\"=?;";
ps2 = dbOperations.getSession().prepare(sb2);
} else {
String sb = "SELECT \"TARGET_ID\", \"PROCESSED\" from \"SLOTS_2013_11_03\" where \"DUE_SLOT\"=?;";
ps = dbOperations.getSession().prepare(sb);
String sb2 = "UPDATE \"SLOTS_2013_11_03\" SET \"PROCESSED\"=true where \"DUE_SLOT\"=? and \"TARGET_ID\"=?;";
ps2 = dbOperations.getSession().prepare(sb2);
}
while (true) {
int cnt_read = 0;
if (sol == 1) {
BoundStatement boundStatement = new BoundStatement(ps);
boundStatement.bind(i2);
ResultSet res = dbOperations.getSession().execute(boundStatement);
for (Row row : res) {
String s = row.getString(0);
cnt_read++;
// deleting
a1++;
boundStatement = new BoundStatement(ps2);
boundStatement.bind(i2, s);
res = dbOperations.getSession().execute(boundStatement);
}
} else {
BoundStatement boundStatement = new BoundStatement(ps);
boundStatement.bind(i2);
ResultSet res = dbOperations.getSession().execute(boundStatement);
for (Row row : res) {
String s = row.getString(0);
boolean processed = row.getBool(1);
if (!processed) {
a1++;
cnt_read++;
// updating
boundStatement = new BoundStatement(ps2);
boundStatement.bind(i2, s);
res = dbOperations.getSession().execute(boundStatement);
}
}
}
if (cnt_read == 0) {
i2++;
if (i2 >= first_slot_cnt + due_slot_cnt) {
break;
}
}
}
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void terminate() {
// TODO Auto-generated method stub
}
}
}