package org.mobicents.smsc.tools.stresstool; import java.awt.EventQueue; import java.util.ArrayList; import java.util.Date; import java.util.Queue; import java.util.Random; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.log4j.Logger; import org.mobicents.protocols.ss7.map.api.primitives.AddressNature; import org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan; import org.mobicents.protocols.ss7.map.primitives.ISDNAddressStringImpl; import org.mobicents.protocols.ss7.map.service.sms.LocationInfoWithLMSIImpl; import org.mobicents.smsc.cassandra.DBOperations; import org.mobicents.smsc.cassandra.PersistenceException; import org.mobicents.smsc.cassandra.PreparedStatementCollection; import org.mobicents.smsc.library.ErrorCode; import org.mobicents.smsc.library.SmType; import org.mobicents.smsc.library.Sms; import org.mobicents.smsc.library.SmsSet; import org.mobicents.smsc.library.SmsSetCache; import org.mobicents.smsc.library.TargetAddress; import com.cloudhopper.smpp.tlv.Tlv; /** * host, port, keyspace * -hlocalhost -p9042 -ksaturn -mDataTableDaysTimeArea * -s<smsSetRange> * -c<recordCount> -t<threadCountW> -T<threadCountR> * @author sergey vetuyutnev * */ public class StressTool3 { private String host = "localhost"; private int port = 9042; private String keyspace = "saturn"; private String user = "cassandra"; private String pass = "cassandra"; private int dataTableDaysTimeArea = 10; private int smsSetRange = 10; private int recordCount = 500000; private int threadCountW = 8; // saving private int threadCountR = 10; // reading private int threadCountA = 10; // Alert private CTask task = CTask.Live_Sms_Cycle; private static final Logger logger = Logger.getLogger(StressTool3.class); private String persistFile = "stresstool.xml"; private static final String TAB_INDENT = "\t"; private TT_DBOperationsProxy3 dbOperations; public static void main(final String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { StressTool3 tool = new StressTool3(); 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_DBOperationsProxy3(); this.dbOperations.start(host, port, keyspace, user, pass, 60, 60, 60 * 10, 1, 10000000000L); // ..................................... // unit test # 1 // Date dt = new Date(113, 11, 3, 12, 30, 25); // long l1 = this.dbOperations.getDueSlotForTime(dt); // Date dt2 = this.dbOperations.getTimeForDueSlot(l1); // // unit test # 2 // long l2 = this.dbOperations.getProcessingDueSlot(); // this.dbOperations.setProcessingDueSlot(15); // long l3 = this.dbOperations.getProcessingDueSlot(); // ..................................... ProcessTask ta = null; if (this.task == CTask.Live_Sms_Cycle) { ta = new TX(); } if (ta != null) { while (!ta.isReady()) { logInfo(ta.getResults()); Thread.sleep(10000); } ta.terminate(); } 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; // } } } } } enum CTask { Live_Sms_Cycle, }; class TX implements ProcessTask, Runnable { private ArrayList<TX1> tx1 = new ArrayList<TX1>(); private ArrayList<TX2> tx2 = new ArrayList<TX2>(); private TX3 tx3; private ArrayList<TX4> tx4 = new ArrayList<TX4>(); 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) { tx3 = new TX3(0, recordCount); Thread t = new Thread(tx3); t.start(); } if (threadCountA > 0) { int num = 1000000; for (int i1 = 0; i1 < threadCountA; i1++) { TX2 ta = new TX2(num, num + recordCount); tx2.add(ta); Thread t = new Thread(ta); t.start(); } } for (int i1 = 0; i1 < threadCountR; i1++) { TX4 ta = new TX4(); tx4.add(ta); Thread t = new Thread(ta); t.start(); } } @Override public boolean isReady() { for (TX1 el : tx1) { if (!el.isReady()) return false; } if (tx3 != null && !tx3.isReady()) return false; return true; } @Override public String getResults() { int i1 = 0; for (TX1 el : tx1) { i1 += el.curNum - el.startNum; } int i2 = recordCount; int i3 = 0; for (TX2 el : tx2) { i3 += el.numProcessed; } String s1 = "Processed TX1 " + i1 + " out of " + i2 + ", processed TX3 " + (tx3 != null ? (tx3.curNum) : "") + " out of " + (tx3 != null ? (tx3.endNum - tx3.startNum) : "") + ", queue=" + queue.size() + ", T2-numProcessed=" + i3; return s1; } @Override public void run() { } @Override public void terminate() { for (ProcessTask pt : tx1) { pt.terminate(); } if (tx3 != null) { tx3.terminate(); } } } class TX1 implements ProcessTask, Runnable { private int startNum; private int endNum; private int curNum; private boolean ready; private boolean toTernminate; 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 (!toTernminate) { Integer ii1 = this.curNum; String s1 = ii1.toString(); int messageId = 0; int cnt = 3; try { PreparedStatementCollection psc = dbOperations.getStatementCollection(new Date()); 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 < cnt; 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; TargetAddress lock = SmsSetCache.getInstance().addSmsSet(new TargetAddress(smsSet)); try { synchronized (lock) { dueSlot = dbOperations.c2_getDueSlotForTargetId(psc, sms.getSmsSet().getTargetId()); if (dueSlot == 0 || dueSlot <= dbOperations.c2_getCurrentDueSlot()) { dueSlot = dbOperations.c2_getDueSlotForNewSms(); dbOperations.c2_updateDueSlotForTargetId(sms.getSmsSet().getTargetId(), dueSlot); } sms.setDueSlot(dueSlot); } } finally { SmsSetCache.getInstance().removeSmsSet(lock); } dbOperations.c2_registerDueSlotWriting(dueSlot); try { dbOperations.c2_createRecordCurrent(sms); } finally { dbOperations.c2_unregisterDueSlotWriting(dueSlot); } } } catch (PersistenceException e) { logger.error("Exception in task X1: " + e.toString(), e); } this.curNum += cnt; if (this.curNum >= this.endNum) break; } } finally { ready = true; } } @Override public void terminate() { toTernminate = true; } } class TX2 implements ProcessTask, Runnable { private int startNum; private int endNum; private int numProcessed; private boolean toTernminate; private Random rnd = new Random(); public TX2(int startNum, int endNum) { this.startNum = startNum; this.endNum = endNum; } @Override public boolean isReady() { return true; } @Override public String getResults() { return ""; } @Override public void run() { try { while (!toTernminate) { int num = rnd.nextInt(endNum - startNum) + startNum; try { PreparedStatementCollection psc = dbOperations.getStatementCollection(new Date()); long dueSlot; Integer ii1 = num; String s1 = ii1.toString(); SmsSet smsSet0 = new SmsSet(); smsSet0.setDestAddr(s1); smsSet0.setDestAddrNpi(1); smsSet0.setDestAddrTon(1); TargetAddress lock = SmsSetCache.getInstance().addSmsSet(new TargetAddress(smsSet0)); try { synchronized (lock) { dueSlot = dbOperations.c2_getDueSlotForTargetId(psc, smsSet0.getTargetId()); if (dueSlot != 0 && dueSlot > dbOperations.c2_getCurrentDueSlot()) { dbOperations.c2_registerDueSlotWriting(dueSlot); try { if (dueSlot != 0 && dueSlot > dbOperations.c2_getCurrentDueSlot()) { SmsSet smsSet = dbOperations.c2_getRecordListForTargeId(dueSlot, smsSet0.getTargetId()); if (smsSet != null) { ArrayList<SmsSet> lstS = new ArrayList<SmsSet>(); lstS.add(smsSet); ArrayList<SmsSet> lst = dbOperations.c2_sortRecordList(lstS); for (int i1 = 0; i1 < smsSet.getSmsCount(); i1++) { Sms sms = smsSet.getSms(i1); dbOperations.c2_updateInSystem(sms, DBOperations.IN_SYSTEM_INPROCESS, false); } this.numProcessed += smsSet.getSmsCount(); for (SmsSet t1 : lst) { if (!t1.isProcessingStarted()) { t1.setProcessingStarted(); queue.add(t1); } } } } } finally { dbOperations.c2_unregisterDueSlotWriting(dueSlot); } } } } finally { SmsSetCache.getInstance().removeSmsSet(lock); } } catch (PersistenceException e) { logger.error("Exception in task X2: " + e.toString(), e); } Thread.sleep(10); } } catch (InterruptedException e) { e.printStackTrace(); } finally { } } @Override public void terminate() { toTernminate = true; } } private Queue<SmsSet> queue = new ConcurrentLinkedQueue<SmsSet>(); class TX3 implements ProcessTask, Runnable { private int startNum; private int endNum; private int curNum; private boolean ready; private boolean toTernminate; public TX3(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 (!toTernminate) { try { long processedDueSlot = dbOperations.c2_getCurrentDueSlot(); long possibleDueSlot = dbOperations.c2_getIntimeDueSlot(); if (processedDueSlot >= possibleDueSlot || queue.size() > 10000) { Thread.sleep(10); } else { processedDueSlot++; if (!dbOperations.c2_checkDueSlotNotWriting(processedDueSlot)) { Thread.sleep(10); continue; } ArrayList<SmsSet> lstS = dbOperations.c2_getRecordList(processedDueSlot); ArrayList<SmsSet> lst = dbOperations.c2_sortRecordList(lstS); this.curNum += lstS.size(); for (SmsSet ti : lst) { if (!ti.isProcessingStarted()) { ti.setProcessingStarted(); queue.add(ti); } } dbOperations.c2_setCurrentDueSlot(processedDueSlot); } } catch (Throwable e) { logger.error("Exception in task X3: " + e.toString(), e); } if (this.curNum >= this.endNum) break; } } catch (Throwable e) { e.printStackTrace(); } finally { ready = true; } } @Override public void terminate() { toTernminate = true; } } class TX4 implements ProcessTask, Runnable { public TX4() { } @Override public boolean isReady() { return true; } @Override public String getResults() { return ""; } @Override public void run() { int j1 = 0; while (true) { SmsSet smsSet = queue.poll(); if (smsSet != null) { j1++; try { TargetAddress lock = SmsSetCache.getInstance().addSmsSet(new TargetAddress(smsSet)); try { synchronized (lock) { int j2 = j1 % 3; long ii = smsSet.getSmsCount(); if (j2 == 0) { // postpone of delivering Date dt = new Date(new Date().getTime() + 1000 * 60 * 10); for (int i1 = 0; i1 < ii; i1++) { Sms sms = smsSet.getSms(i1); sms.setDeliveryDate(new Date()); dbOperations.c2_updateInSystem(sms, DBOperations.IN_SYSTEM_SENT, false); // + 10 min sms.setDueSlot(dbOperations.c2_getDueSlotForTime(dt)); dbOperations.c2_createRecordCurrent(sms); } } else { smsSet.setType(SmType.SMS_FOR_SS7); if (j1 % 3 == 1) { smsSet.setStatus(ErrorCode.ABSENT_SUBSCRIBER); } else { smsSet.setStatus(ErrorCode.SUCCESS); smsSet.setImsi("123456789012324"); ISDNAddressStringImpl networkNodeNumber = new ISDNAddressStringImpl(AddressNature.international_number, NumberingPlan.ISDN, "1231223123"); LocationInfoWithLMSIImpl locationInfoWithLMSI = new LocationInfoWithLMSIImpl(networkNodeNumber, null, null, false, null); smsSet.setLocationInfoWithLMSI(locationInfoWithLMSI); } for (int i1 = 0; i1 < ii; i1++) { Sms sms = smsSet.getSms(i1); sms.setDeliveryDate(new Date()); dbOperations.c2_updateInSystem(sms, DBOperations.IN_SYSTEM_SENT, false); dbOperations.c2_createRecordArchive(sms, null, null, false, false); } } SmsSetCache.getInstance().removeProcessingSmsSet(smsSet.getTargetId()); } } finally { SmsSetCache.getInstance().removeSmsSet(lock); } } 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 } } }