/*
* TeleStax, Open Source Cloud Communications Copyright 2012.
* and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.mobicents.smsc.slee.resources.scheduler;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.slee.Address;
import javax.slee.facilities.Tracer;
import javax.slee.resource.ActivityFlags;
import javax.slee.resource.ActivityHandle;
import javax.slee.resource.ConfigProperties;
import javax.slee.resource.EventFlags;
import javax.slee.resource.FailureReason;
import javax.slee.resource.FireableEventType;
import javax.slee.resource.InvalidConfigurationException;
import javax.slee.resource.Marshaler;
import javax.slee.resource.ReceivableService;
import javax.slee.resource.ResourceAdaptor;
import javax.slee.resource.ResourceAdaptorContext;
import javax.slee.resource.SleeEndpoint;
import javax.slee.transaction.SleeTransaction;
import javax.slee.transaction.SleeTransactionManager;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import org.mobicents.smsc.cassandra.DBOperations;
import org.mobicents.smsc.cassandra.PersistenceException;
import org.mobicents.smsc.domain.SmsRouteManagement;
import org.mobicents.smsc.domain.SmscCongestionControl;
import org.mobicents.smsc.domain.SmscPropertiesManagement;
import org.mobicents.smsc.domain.SmscStatAggregator;
import org.mobicents.smsc.domain.SmscStatProvider;
import org.mobicents.smsc.library.SbbStates;
import org.mobicents.smsc.library.SmType;
import org.mobicents.smsc.library.SmsSet;
import org.mobicents.smsc.library.SmsSetCache;
import org.mobicents.smsc.slee.common.ra.EventIDCache;
import org.mobicents.smsc.slee.services.smpp.server.events.SmsSetEvent;
/**
*
* @author sergey vetyutnev
*
*/
public class SchedulerResourceAdaptor implements ResourceAdaptor {
private static final int ACTIVITY_FLAGS = ActivityFlags
.setRequestEndedCallback(ActivityFlags.REQUEST_ENDED_CALLBACK);
private static final int EVENT_FLAGS = EventFlags.setRequestProcessingSuccessfulCallback(EventFlags
.setRequestProcessingFailedCallback(EventFlags.REQUEST_EVENT_UNREFERENCED_CALLBACK));
private static final String EVENT_VENDOR = "org.mobicents";
private static final String EVENT_VERSION = "1.0";
private static final String EVENT_SMPP_SM = "org.mobicents.smsc.slee.services.smpp.server.events.SMPP_SM";
private static final String EVENT_SS7_SM = "org.mobicents.smsc.slee.services.smpp.server.events.SS7_SM";
private static final String EVENT_SIP_SM = "org.mobicents.smsc.slee.services.smpp.server.events.SIP_SM";
protected Tracer tracer = null;
private ResourceAdaptorContext raContext = null;
private SleeTransactionManager sleeTransactionManager = null;
private SleeEndpoint sleeEndpoint = null;
private EventIDCache eventIdCache;
private ScheduledExecutorService scheduler = null;
private SchedulerRaSbbInterface schedulerRaSbbInterface = null;
private SchedulerRaUsageParameters usageParameters;
// private DBOperations_C1 dbOperations_C1 = null;
protected DBOperations dbOperations_C2 = null;
private Date garbageCollectionTime = new Date();
private SmscStatAggregator smscStatAggregator = SmscStatAggregator.getInstance();
private SmscCongestionControl smscCongestionControl = SmscCongestionControl.getInstance();
public SchedulerResourceAdaptor() {
this.schedulerRaSbbInterface = new SchedulerRaSbbInterface() {
@Override
public void injectSmsOnFly(SmsSet smsSet, boolean callFromSbb) throws Exception {
doInjectSmsOnFly(smsSet, callFromSbb);
}
@Override
public void injectSmsDatabase(SmsSet smsSet) throws Exception {
doInjectSmsDatabase(smsSet);
}
@Override
public void setDestCluster(SmsSet smsSet) {
doSetDestCluster(smsSet);
}
};
}
@Override
public void activityEnded(ActivityHandle activityHandle) {
if (this.tracer.isFineEnabled()) {
this.tracer.fine("Activity with handle " + activityHandle + " ended.");
}
}
@Override
public void activityUnreferenced(ActivityHandle activityHandle) {
if (this.tracer.isFineEnabled()) {
this.tracer.fine("Activity unreferenced with handle " + activityHandle + ".");
}
}
@Override
public void administrativeRemove(ActivityHandle activityHandle) {
if (this.tracer.isFineEnabled()) {
this.tracer.fine("Activity administrative remove with handle " + activityHandle + ".");
}
}
@Override
public void eventProcessingFailed(ActivityHandle activityHandle, FireableEventType arg1, Object arg2, Address arg3,
ReceivableService arg4, int arg5, FailureReason arg6) {
if (this.tracer.isFineEnabled()) {
this.tracer.fine("Event processing failed on activity with handle " + activityHandle + ".");
}
// something bad happened, push back to DB:
// TODO: markAsNotInSystem();
this.sleeEndpoint.endActivity(activityHandle);
}
@Override
public void eventProcessingSuccessful(ActivityHandle activityHandle, FireableEventType arg1, Object arg2,
Address arg3, ReceivableService arg4, int flags) {
if (this.tracer.isFineEnabled()) {
this.tracer.fine("Event processing succeeded on activity with handle " + activityHandle + ".");
}
if (EventFlags.hasSbbProcessedEvent(flags)) {
// SBB did process
} else {
// nothing happened
// TODO: markAsNotInSystem();
}
this.sleeEndpoint.endActivity(activityHandle);
}
@Override
public void eventUnreferenced(ActivityHandle activityHandle, FireableEventType arg1, Object arg2, Address arg3,
ReceivableService arg4, int arg5) {
if (this.tracer.isFineEnabled()) {
this.tracer.fine("Event unreferenced on activity with handle " + activityHandle + ".");
}
}
@Override
public Object getActivity(ActivityHandle activityHandle) {
return ((SchedulerActivityHandle) activityHandle).getActivity();
}
@Override
public ActivityHandle getActivityHandle(Object activity) {
if (activity instanceof SchedulerActivityImpl) {
final SchedulerActivityImpl wrapper = ((SchedulerActivityImpl) activity);
// if (wrapper.getRa() == this) {
return wrapper.getActivityHandle();
// }
}
return null;
}
@Override
public Marshaler getMarshaler() {
return null;
}
@Override
public Object getResourceAdaptorInterface(String arg0) {
return this.schedulerRaSbbInterface;
}
@Override
public void queryLiveness(ActivityHandle activityHandle) {
}
@Override
public void raActive() {
clearActivityCount();
SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
this.dbOperations_C2 = DBOperations.getInstance();
if (!this.dbOperations_C2.isStarted()) {
throw new RuntimeException("DBOperations_2 not started yet!");
}
scheduler = Executors.newScheduledThreadPool(1);
long timerDur = smscPropertiesManagement.getFetchPeriod();
long maxTimerDur = this.dbOperations_C2.getSlotMSecondsTimeArea() * 2 / 3;
if (timerDur > maxTimerDur)
timerDur = maxTimerDur;
scheduler.scheduleAtFixedRate(new TickTimerTask(), 500, timerDur, TimeUnit.MILLISECONDS);
if (tracer.isInfoEnabled()) {
tracer.info("SchedulerResourceAdaptor " + raContext.getEntityName() + " Activated");
}
smscPropertiesManagement.setSmscStopped(false);
}
@Override
public void raInactive() {
if (tracer.isInfoEnabled()) {
tracer.info("Starting of inactivating SchedulerResourceAdaptor RA Entity " + this.raContext.getEntityName());
}
SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
smscPropertiesManagement.setSmscStopped(true);
for (int i1 = 0; i1 < 60; i1++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (SmsSetCache.getInstance().getProcessingSmsSetSize() == 0)
break;
}
if (tracer.isInfoEnabled()) {
tracer.info("Finishing of inactivating SchedulerResourceAdaptor RA Entity " + this.raContext.getEntityName());
}
}
@Override
public void raConfigurationUpdate(ConfigProperties properties) {
throw new UnsupportedOperationException();
}
@Override
public void raConfigure(ConfigProperties properties) {
if (tracer.isFineEnabled()) {
tracer.fine("Configuring RA Entity " + this.raContext.getEntityName());
}
}
@Override
public void raStopping() {
if (tracer.isInfoEnabled()) {
tracer.info("Stopping Scheduler RA Entity " + this.raContext.getEntityName());
}
this.scheduler.shutdown();
try {
this.scheduler.awaitTermination(120, TimeUnit.SECONDS);
} catch (InterruptedException e) {
tracer.severe("InterruptedException while awaiting termination of tasks", e);
}
if (tracer.isInfoEnabled()) {
tracer.info("Stopped Scheduler RA Entity " + this.raContext.getEntityName());
}
}
@Override
public void raUnconfigure() {
if (tracer.isInfoEnabled()) {
tracer.info("Unconfigure RA Entity " + this.raContext.getEntityName());
}
}
@Override
public void raVerifyConfiguration(ConfigProperties properties) throws InvalidConfigurationException {
if (tracer.isInfoEnabled()) {
tracer.info("Verify configuration in RA Entity " + this.raContext.getEntityName());
}
}
@Override
public void serviceActive(ReceivableService arg0) {
// TODO Auto-generated method stub
}
@Override
public void serviceInactive(ReceivableService arg0) {
// TODO Auto-generated method stub
}
@Override
public void serviceStopping(ReceivableService arg0) {
// TODO Auto-generated method stub
}
@Override
public void setResourceAdaptorContext(ResourceAdaptorContext raContext) {
this.tracer = raContext.getTracer(getClass().getSimpleName());
this.raContext = raContext;
this.eventIdCache = new EventIDCache(this.raContext, EVENT_VENDOR, EVENT_VERSION);
this.sleeTransactionManager = this.raContext.getSleeTransactionManager();
this.sleeEndpoint = this.raContext.getSleeEndpoint();
this.usageParameters = (SchedulerRaUsageParameters) this.raContext.getDefaultUsageParameterSet();
}
@Override
public void unsetResourceAdaptorContext() {
this.tracer = null;
this.eventIdCache = null;
this.raContext = null;
this.sleeTransactionManager = null;
this.sleeEndpoint = null;
}
// /////////////////
// Helper classes //
// /////////////////
protected class TickTimerTask implements Runnable {
@Override
public void run() {
onTimerTick();
}
}
private OneWaySmsSetCollection savedOneWaySmsSetCollection = null;
private String shownServicesDownList = null;
private long shownServicesDownTime = 0;
// /////////////////
// Helper methods //
// /////////////////
protected void onTimerTick() {
// checking if all SBBs are already running
if (!SbbStates.isAllServicesUp()) {
String s1 = SbbStates.getServicesDownList();
if (!s1.equals(shownServicesDownList) || System.currentTimeMillis() - shownServicesDownTime > 10000) {
// we are displaying this message every 10 seconds or if ServicesDownList has changed
this.tracer.info("Not all SBB are running now: " + s1);
shownServicesDownList = s1;
shownServicesDownTime = System.currentTimeMillis();
}
return;
}
try {
// garbageCollectionTime
Date current = new Date(new Date().getTime() - 1000 * 60);
if (garbageCollectionTime.before(current)) {
garbageCollectionTime = new Date();
SmsSetCache.getInstance().garbadeCollectProcessingSmsSet();
}
// checking if cassandra database is available
if (!dbOperations_C2.isDatabaseAvailable())
return;
// checking if we need to advance dueSlot
SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
int val = smscPropertiesManagement.getSkipUnsentMessages();
if (val >= 0) {
smscPropertiesManagement.setSkipUnsentMessages(-1);
// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
// } else {
long processedDueSlot = dbOperations_C2.c2_getCurrentDueSlot();
Date processedTime = dbOperations_C2.c2_getTimeForDueSlot(processedDueSlot);
long possibleDueSlot = dbOperations_C2.c2_getIntimeDueSlot();
// we do a possible time 10 seconds before the time that is possible for running
Date possibleTime = new Date(dbOperations_C2.c2_getTimeForDueSlot(possibleDueSlot).getTime() - 10000);
Date newTime = new Date(possibleTime.getTime() - val * 1000);
if (newTime.getTime() > processedTime.getTime()) {
long newDueSlot = dbOperations_C2.c2_getDueSlotForTime(newTime);
dbOperations_C2.c2_setCurrentDueSlot(newDueSlot);
this.tracer.warning("currentDueSlot has been changed after a user request: from " + processedTime + " to "
+ newTime);
} else {
this.tracer.warning("There was a user request to change currentDueSlot: from " + processedTime + " to "
+ newTime + ". But the new time must be after the current one and the request was rejected.");
}
// }
}
// checking if SmsRouteManagement is already started
SmsRouteManagement smsRouteManagement = SmsRouteManagement.getInstance();
if (smsRouteManagement.getSmsRoutingRule() == null)
return;
OneWaySmsSetCollection schedulableSms;
int maxCnt;
int fetchMaxRows = smscPropertiesManagement.getFetchMaxRows();
int activityCount = SmsSetCache.getInstance().getProcessingSmsSetSize();
int fetchAvailRows = smscPropertiesManagement.getMaxActivityCount() - activityCount;
maxCnt = Math.min(fetchMaxRows, fetchAvailRows);
if (fetchAvailRows <= 0) {
smscCongestionControl.registerMaxActivityCount1_0Threshold();
} else {
smscCongestionControl.registerMaxActivityCount1_0BackToNormal();
}
if (savedOneWaySmsSetCollection != null && savedOneWaySmsSetCollection.size() > 0) {
schedulableSms = savedOneWaySmsSetCollection;
} else {
// checking if SMSC is inactivated by SLEE
if (smscPropertiesManagement.isSmscStopped())
return;
// checking if SMSC is paused by a used
if (smscPropertiesManagement.isDeliveryPause())
return;
try {
if (this.tracer.isFineEnabled())
this.tracer.fine("Fetching: Starting fetching messages from database: fetchMaxRows="
+ fetchMaxRows + ", activityCount=" + activityCount + ", fetchAvailRows="
+ fetchAvailRows);
if (maxCnt <= 0)
return;
int readTryCount = 0;
while (true) {
schedulableSms = this.fetchSchedulable(maxCnt);
int cnt = 0;
if (schedulableSms != null)
cnt = schedulableSms.size();
readTryCount++;
if (cnt == 0 && readTryCount < 100)
// we will 100 times reread new empty due_Slot
continue;
if (this.tracer.isFineEnabled()) {
String s1 = "Fetching: Fetched " + cnt + " messages (max requested messages=" + maxCnt
+ ", fetched messages=" + cnt + ")";
this.tracer.fine(s1);
}
break;
}
} catch (PersistenceException e1) {
this.tracer.severe(
"PersistenceException when fetching SmsSet list from a database: " + e1.getMessage(), e1);
return;
}
}
int count = 0;
Date curDate = new Date();
try {
while (true) {
SmsSet smsSet = schedulableSms.next();
if (smsSet == null)
break;
try {
if (!smsSet.isProcessingStarted()) {
smsSet.setProcessingStarted();
if (!doInjectSmsDatabase(smsSet, curDate, false)) {
return;
}
}
} catch (Exception e) {
this.tracer.severe("Exception when injectSms: " + e.getMessage(), e);
}
count++;
if (count >= maxCnt) {
savedOneWaySmsSetCollection = schedulableSms;
break;
}
}
} finally {
if (count > 0) {
SmscStatProvider smscStatProvider = SmscStatProvider.getInstance();
smscStatProvider.setMessageScheduledTotal(smscStatProvider.getMessageScheduledTotal() + count);
if (this.tracer.isInfoEnabled()) {
String s2 = "Fetching: Scheduled '" + count + "' out of '" + schedulableSms.size()
+ ", fetchMaxRows=" + fetchMaxRows + ", activityCount=" + activityCount
+ ", fetchAvailRows=" + fetchAvailRows + "'.";
this.tracer.info(s2);
}
} else {
if (this.tracer.isFineEnabled()) {
String s2 = "Fetching: Scheduled '" + count + "' out of '" + schedulableSms.size()
+ ", fetchMaxRows=" + fetchMaxRows + ", activityCount=" + activityCount
+ ", fetchAvailRows=" + fetchAvailRows + "'.";
this.tracer.fine(s2);
}
}
}
} catch (Throwable e1) {
this.tracer.severe(
"Exception in SchedulerResourceAdaptor when fetching records and issuing events: "
+ e1.getMessage(), e1);
}
// stat update
SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
// } else {
long processedDueSlot = dbOperations_C2.c2_getCurrentDueSlot();
long possibleDueSlot = dbOperations_C2.c2_getIntimeDueSlot();
Date processedDate = dbOperations_C2.c2_getTimeForDueSlot(processedDueSlot);
Date possibleDate = dbOperations_C2.c2_getTimeForDueSlot(possibleDueSlot);
int lag = (int) ((possibleDate.getTime() - processedDate.getTime()) / 1000);
smscStatAggregator.updateSmscDeliveringLag(lag);
// }
}
protected void endAcitivity(SchedulerActivityHandle activityHandle) throws Exception {
this.sleeEndpoint.endActivity(activityHandle);
this.decrementActivityCount();
}
public void doInjectSmsOnFly(SmsSet smsSet, boolean callFromSbb) throws Exception {
SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
// // TODO: implement it
// } else {
if (!dbOperations_C2.c2_checkProcessingSmsSet(smsSet))
return;
// }
doInjectSms(smsSet, callFromSbb);
}
public void doInjectSmsDatabase(SmsSet smsSet) throws Exception {
// SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
//
// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
// // TODO: implement it
// } else {
// if (!dbOperations_C2.c2_checkProcessingSmsSet(smsSet))
// return;
// }
doInjectSmsDatabase(smsSet, new Date(), true);
}
protected boolean doInjectSmsDatabase(SmsSet smsSet, Date curDate, boolean callFromSbb) throws Exception {
// TODO: ValidityPeriod was removed !!!
// // removing SMS that are out of validity period
// boolean withValidityTimeout = false;
// for (int i1 = 0; i1 < smsSet.getSmsCount(); i1++) {
// Sms sms = smsSet.getSms(i1);
// if (sms.getValidityPeriod() != null && sms.getValidityPeriod().before(curDate)) {
// withValidityTimeout = true;
// break;
// }
// }
//
// if (withValidityTimeout) {
// SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
//
// ArrayList<Sms> good = new ArrayList<Sms>();
// ArrayList<Sms> expired = new ArrayList<Sms>();
// TargetAddress lock = SmsSetCache.getInstance().addSmsSet(new TargetAddress(smsSet));
// synchronized (lock) {
// try {
// for (int i1 = 0; i1 < smsSet.getSmsCount(); i1++) {
// Sms sms = smsSet.getSms(i1);
// if (sms.getValidityPeriod() != null && sms.getValidityPeriod().before(curDate)) {
// expired.add(sms);
// } else {
// good.add(sms);
// }
// }
//
// ErrorCode smStatus = ErrorCode.RESERVED_127;
// String reason = "Validity period is expired";
//
// if (expired.size() > 0) {
// smsSet.setStatus(smStatus);
// }
// if (good.size() == 0) {
// // no good nonexpired messages - we need to remove
// // SmsSet record
//
//// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
//// dbOperations_C1.fetchSchedulableSms(smsSet, false);
////
//// dbOperations_C1.setDeliveryFailure(smsSet, smStatus, curDate);
//// } else {
//
// // TODO: remove it !!!!
// // smsSet.setStatus(smStatus);
// // TODO: remove it !!!!
// SmsSetCache.getInstance().removeProcessingSmsSet(smsSet.getTargetId());
//
//// }
// }
//
// for (Sms sms : expired) {
// StringBuilder sb = new StringBuilder();
// sb.append("onDeliveryError: errorAction=validityExpired");
// sb.append(", smStatus=");
// sb.append(smStatus);
// sb.append(", targetId=");
// sb.append(smsSet.getTargetId());
// sb.append(", smsSet=");
// sb.append(smsSet);
// sb.append(", reason=");
// sb.append(reason);
// if (this.tracer.isInfoEnabled())
// this.tracer.info(sb.toString());
//
// CdrGenerator.generateCdr(sms, CdrGenerator.CDR_FAILED, reason, smscPropertiesManagement.getGenerateReceiptCdr(),
// MessageUtil.isNeedWriteArchiveMessage(sms, smscPropertiesManagement.getGenerateCdr()));
//
// // adding an error receipt if it is needed
// if (sms.getStored()) {
//// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
//// dbOperations_C1.archiveFailuredSms(sms);
//// dbOperations_C1.deleteSmsSet(smsSet);
//// } else {
//
// if (sms.getStored()) {
// dbOperations_C2.c2_updateInSystem(sms, DBOperations.IN_SYSTEM_SENT,
// smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast);
// sms.setDeliveryDate(curDate);
// if (MessageUtil.isNeedWriteArchiveMessage(sms,
// smscPropertiesManagement.getGenerateArchiveTable())) {
// dbOperations_C2.c2_createRecordArchive(sms);
// }
// }
//
//// }
// }
//
// // mproc rules applying for delivery phase
// MProcResult mProcResult = MProcManagement.getInstance().applyMProcDelivery(sms, true, null);
// FastList<Sms> addedMessages = mProcResult.getMessageList();
// if (addedMessages != null) {
// for (FastList.Node<Sms> n = addedMessages.head(), end = addedMessages.tail(); (n = n.getNext()) != end;) {
// Sms smst = n.getValue();
// TargetAddress ta = new TargetAddress(smst.getSmsSet().getDestAddrTon(), smst.getSmsSet().getDestAddrNpi(),
// smst.getSmsSet().getDestAddr(), smst.getSmsSet().getNetworkId());
// TargetAddress lock2 = SmsSetCache.getInstance().addSmsSet(ta);
// try {
// synchronized (lock2) {
//
//// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
//// } else {
//
// boolean storeAndForwMode = MessageUtil.isStoreAndForward(smst);
// if (!storeAndForwMode) {
// try {
// this.schedulerRaSbbInterface.injectSmsOnFly(smst.getSmsSet(), false);
// } catch (Exception e) {
// this.tracer.severe(
// "Exception when runnung injectSmsOnFly() for applyMProcDelivery created messages: "
// + e.getMessage(), e);
// }
// } else {
// if (smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast) {
// try {
// smst.setStoringAfterFailure(true);
// this.schedulerRaSbbInterface.injectSmsOnFly(smst.getSmsSet(), false);
// } catch (Exception e) {
// this.tracer.severe(
// "Exception when runnung injectSmsOnFly() for applyMProcDelivery created messages: "
// + e.getMessage(), e);
// }
// } else {
// smst.setStored(true);
// this.schedulerRaSbbInterface.setDestCluster(smst.getSmsSet());
// try {
// dbOperations_C2
// .c2_scheduleMessage_ReschedDueSlot(
// smst,
// smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast,
// true);
// } catch (PersistenceException e) {
// this.tracer.severe(
// "PersistenceException when adding applyMProcDelivery created messages"
// + e.getMessage(), e);
// }
// }
// }
//
//// }
//
// }
// } finally {
// SmsSetCache.getInstance().removeSmsSet(lock2);
// }
// }
// }
//
// int registeredDelivery = sms.getRegisteredDelivery();
// if (!smscPropertiesManagement.getReceiptsDisabling() && MessageUtil.isReceiptOnFailure(registeredDelivery)) {
// TargetAddress ta = new TargetAddress(sms.getSourceAddrTon(), sms.getSourceAddrNpi(), sms.getSourceAddr(), smsSet.getNetworkId());
// TargetAddress lock2 = SmsSetCache.getInstance().addSmsSet(ta);
// try {
// synchronized (lock2) {
// try {
// Sms receipt;
//
//
//// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
//// receipt = MessageUtil.createReceiptSms(sms, false);
//// SmsSet backSmsSet = dbOperations_C1.obtainSmsSet(ta);
//// receipt.setSmsSet(backSmsSet);
//// receipt.setStored(true);
//// dbOperations_C1.createLiveSms(receipt);
//// dbOperations_C1.setNewMessageScheduled(receipt.getSmsSet(),
//// MessageUtil.computeDueDate(MessageUtil.computeFirstDueDelay(smscPropertiesManagement.getFirstDueDelay())));
//// } else {
//
//
// receipt = MessageUtil.createReceiptSms(sms, false, ta,
// smscPropertiesManagement.getOrigNetworkIdForReceipts());
// boolean storeAndForwMode = MessageUtil.isStoreAndForward(sms);
// if (!storeAndForwMode) {
// try {
// this.schedulerRaSbbInterface.injectSmsOnFly(receipt.getSmsSet(), false);
// } catch (Exception e) {
// this.tracer.severe(
// "Exception when runnung injectSmsOnFly() for receipt in doInjectSmsDatabase(): "
// + e.getMessage(), e);
// }
// } else {
// if (smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast) {
// try {
// receipt.setStoringAfterFailure(true);
// this.schedulerRaSbbInterface.injectSmsOnFly(receipt.getSmsSet(), false);
// } catch (Exception e) {
// this.tracer.severe(
// "Exception when runnung injectSmsOnFly() for receipt in doInjectSmsDatabase(): "
// + e.getMessage(), e);
// }
// } else {
// receipt.setStored(true);
// this.setDestCluster(receipt.getSmsSet());
// dbOperations_C2
// .c2_scheduleMessage_ReschedDueSlot(
// receipt,
// smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast,
// true);
// }
// }
//
//// }
//
//
// this.tracer.info("Adding an error receipt: source=" + receipt.getSourceAddr() + ", dest="
// + receipt.getSmsSet().getDestAddr());
// } catch (PersistenceException e) {
// this.tracer.severe(
// "PersistenceException when freeSmsSetFailured(SmsSet smsSet) - adding delivery receipt" + e.getMessage(), e);
// }
// }
// } finally {
// SmsSetCache.getInstance().removeSmsSet(lock2);
// }
// }
// }
//
// if (good.size() == 0) {
// // all messages are expired
// return true;
// } else {
// smsSet.clearSmsList();
// for (Sms sms : good) {
// smsSet.addSms(sms);
// }
// }
// } finally {
// SmsSetCache.getInstance().removeSmsSet(lock);
// }
// }
// }
return doInjectSms(smsSet, callFromSbb);
}
private boolean doInjectSms(SmsSet smsSet, boolean callFromSbb) throws NotSupportedException, SystemException, Exception, RollbackException, HeuristicMixedException,
HeuristicRollbackException {
if(!callFromSbb){
//If this call is from SBB it comes with Transaction and no need to start one
SleeTransaction sleeTx = this.sleeTransactionManager.beginSleeTransaction();
}
try {
this.doSetDestCluster(smsSet);
String eventName = null;
switch (smsSet.getType()) {
case SMS_FOR_ESME:
eventName = EVENT_SMPP_SM;
break;
case SMS_FOR_SS7:
eventName = EVENT_SS7_SM;
break;
case SMS_FOR_SIP:
eventName = EVENT_SIP_SM;
break;
}
final FireableEventType eventTypeId = this.eventIdCache.getEventId(eventName);
SmsSetEvent event = new SmsSetEvent();
event.setSmsSet(smsSet);
SchedulerActivityImpl activity = new SchedulerActivityImpl(this);
this.sleeEndpoint.startActivityTransacted(activity.getActivityHandle(), activity, ACTIVITY_FLAGS);
try {
this.sleeEndpoint.fireEventTransacted(activity.getActivityHandle(), eventTypeId, event, null, null);
} catch (Exception e) {
if (this.tracer.isSevereEnabled()) {
this.tracer.severe("Failed to fire SmsSet event Class=: " + eventTypeId.getEventClassName(), e);
}
try {
this.sleeEndpoint.endActivityTransacted(activity.getActivityHandle());
} catch (Exception ee) {
}
}
markAsInSystem(smsSet);
} catch (Exception e) {
if (!callFromSbb) {
this.sleeTransactionManager.rollback();
}
throw e;
}
if(!callFromSbb){
//If this call is from SBB it comes with Transaction and no need to commit here
this.sleeTransactionManager.commit();
}
this.incrementActivityCount();
return true;
}
public void setDestCluster(SmsSet smsSet) {
doSetDestCluster(smsSet);
}
private void doSetDestCluster(SmsSet smsSet) {
// Step 1: Check first if this SMS is for SMPP
SmsRouteManagement smsRouteManagement = SmsRouteManagement.getInstance();
//Quick and dirty fix for SMSC-171
String orignatingEsmeName = smsSet.getSms(0).getOrigEsmeName();
String destClusterName = smsRouteManagement.getEsmeClusterName(smsSet.getDestAddrTon(),
smsSet.getDestAddrNpi(), smsSet.getDestAddr(), orignatingEsmeName, smsSet.getNetworkId());
// Step 2: If no SMPP's found, check if its for SIP
// TODO: we possibly do not need to send a SIP-originated message back to SIP
if (destClusterName == null) {
destClusterName = smsRouteManagement.getSipClusterName(smsSet.getDestAddrTon(),
smsSet.getDestAddrNpi(), smsSet.getDestAddr(), smsSet.getNetworkId());
if (destClusterName == null) {
// Step 2: If no SIP's found, its for SS7
smsSet.setType(SmType.SMS_FOR_SS7);
} else {
smsSet.setType(SmType.SMS_FOR_SIP);
}
} else {
// smsSet.setType(destClusterName != null ? SmType.SMS_FOR_ESME
// : SmType.SMS_FOR_SS7);
smsSet.setType(SmType.SMS_FOR_ESME);
}
smsSet.setDestClusterName(destClusterName);
}
protected OneWaySmsSetCollection fetchSchedulable(int maxRecordCount) throws PersistenceException {
SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
// List<SmsSet> res0 = dbOperations_C1.fetchSchedulableSmsSets(maxRecordCount, this.tracer);
// OneWaySmsSetCollection res = new OneWaySmsSetCollection();
// res.setListSmsSet(res0);
// return res;
// } else {
long processedDueSlot = dbOperations_C2.c2_getCurrentDueSlot();
long possibleDueSlot = dbOperations_C2.c2_getIntimeDueSlot();
if (processedDueSlot >= possibleDueSlot) {
return new OneWaySmsSetCollection();
}
processedDueSlot++;
if (!dbOperations_C2.c2_checkDueSlotNotWriting(processedDueSlot)) {
return new OneWaySmsSetCollection();
}
ArrayList<SmsSet> lstS = dbOperations_C2.c2_getRecordList(processedDueSlot);
ArrayList<SmsSet> lst = dbOperations_C2.c2_sortRecordList(lstS);
OneWaySmsSetCollection res = new OneWaySmsSetCollection();
res.setListSmsSet(lst);
dbOperations_C2.c2_setCurrentDueSlot(processedDueSlot);
return res;
// }
}
protected void markAsInSystem(SmsSet smsSet) throws PersistenceException {
SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
// if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
// TargetAddress lock = SmsSetCache.getInstance().addSmsSet(new TargetAddress(smsSet));
//
// synchronized (lock) {
// try {
// boolean b1 = dbOperations_C1.checkSmsSetExists(new TargetAddress(smsSet));
//
// if (!b1)
// throw new PersistenceException("SmsSet record is not found when markAsInSystem()");
//
// dbOperations_C1.setDeliveryStart(smsSet, new Date());
//
// } finally {
// SmsSetCache.getInstance().removeSmsSet(lock);
// }
// }
// } else {
// // we do not mark IN_SYSTEM when C2
// }
}
private void clearActivityCount() {
long cnt = this.getActivityCount();
this.usageParameters.incrementActivityCount(-cnt);
}
private void incrementActivityCount() {
this.usageParameters.incrementActivityCount(1);
}
private void decrementActivityCount() {
this.usageParameters.incrementActivityCount(-1);
}
private long getActivityCount() {
return this.usageParameters.getActivityCount();
}
public class OneWaySmsSetCollection {
private List<SmsSet> lst = new ArrayList<SmsSet>();
private int uploadedCount;
public void setListSmsSet(List<SmsSet> val) {
this.lst = val;
uploadedCount = 0;
}
public void add(SmsSet smsSet) {
lst.add(smsSet);
}
public SmsSet next() {
if (uploadedCount >= lst.size())
return null;
else {
return lst.get(uploadedCount++);
}
}
public int size() {
return lst.size() - uploadedCount;
}
}
}