PageRenderTime 31ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 1ms

/servers/jain-sip-ha/jboss-5/src/main/java/org/mobicents/ha/javax/sip/cache/SIPDialogCacheData.java

http://mobicents.googlecode.com/
Java | 442 lines | 372 code | 19 blank | 51 comment | 89 complexity | 78244d322a7726df0ffa95c27f9b00a4 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2011, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.mobicents.ha.javax.sip.cache;
  23. import gov.nist.core.CommonLogger;
  24. import gov.nist.core.StackLogger;
  25. import gov.nist.javax.sip.SipProviderImpl;
  26. import gov.nist.javax.sip.message.SIPResponse;
  27. import gov.nist.javax.sip.stack.AbstractHASipDialog;
  28. import gov.nist.javax.sip.stack.SIPDialog;
  29. import java.text.ParseException;
  30. import java.util.Map;
  31. import java.util.Map.Entry;
  32. import javax.sip.PeerUnavailableException;
  33. import javax.sip.SipFactory;
  34. import javax.sip.address.Address;
  35. import javax.sip.header.ContactHeader;
  36. import javax.transaction.RollbackException;
  37. import javax.transaction.Status;
  38. import javax.transaction.TransactionManager;
  39. import org.jboss.cache.Cache;
  40. import org.jboss.cache.CacheException;
  41. import org.jboss.cache.Fqn;
  42. import org.jboss.cache.Node;
  43. import org.jboss.cache.config.Configuration;
  44. import org.mobicents.cache.CacheData;
  45. import org.mobicents.cache.MobicentsCache;
  46. import org.mobicents.ha.javax.sip.ClusteredSipStack;
  47. import org.mobicents.ha.javax.sip.HASipDialog;
  48. import org.mobicents.ha.javax.sip.HASipDialogFactory;
  49. /**
  50. * @author jean.deruelle@gmail.com
  51. * @author martins
  52. *
  53. */
  54. public class SIPDialogCacheData extends CacheData {
  55. private static final String APPDATA = "APPDATA";
  56. private ClusteredSipStack clusteredSipStack;
  57. private static StackLogger logger = CommonLogger.getLogger(SIPDialogCacheData.class);
  58. public SIPDialogCacheData(Fqn nodeFqn, MobicentsCache mobicentsCache, ClusteredSipStack clusteredSipStack) {
  59. super(nodeFqn, mobicentsCache);
  60. this.clusteredSipStack = clusteredSipStack;
  61. }
  62. public SIPDialog getSIPDialog(String dialogId) throws SipCacheException {
  63. HASipDialog haSipDialog = null;
  64. final Cache jbossCache = getMobicentsCache().getJBossCache();
  65. Configuration config = jbossCache.getConfiguration();
  66. final boolean isBuddyReplicationEnabled = config.getBuddyReplicationConfig() != null && config.getBuddyReplicationConfig().isEnabled();
  67. TransactionManager transactionManager = config.getRuntimeConfig().getTransactionManager();
  68. boolean doTx = false;
  69. try {
  70. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  71. logger.logDebug("transaction manager :" + transactionManager);
  72. }
  73. if(transactionManager != null && transactionManager.getTransaction() == null) {
  74. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  75. logger.logDebug("transaction manager begin transaction");
  76. }
  77. transactionManager.begin();
  78. doTx = true;
  79. }
  80. // Issue 1517 : http://code.google.com/p/mobicents/issues/detail?id=1517
  81. // Adding code to handle Buddy replication to force data gravitation
  82. if(isBuddyReplicationEnabled) {
  83. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  84. logger.logDebug("forcing data gravitation since buddy replication is enabled");
  85. }
  86. jbossCache.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
  87. }
  88. final Node<String,Object> childNode = getNode().getChild(dialogId);
  89. if(childNode != null) {
  90. try {
  91. final Map<String, Object> dialogMetaData = childNode.getData();
  92. final Object dialogAppData = childNode.get(APPDATA);
  93. haSipDialog = createDialog(dialogId, dialogMetaData, dialogAppData);
  94. } catch (CacheException e) {
  95. throw new SipCacheException("A problem occured while retrieving the following dialog " + dialogId + " from the Cache", e);
  96. }
  97. }
  98. } catch (Exception ex) {
  99. try {
  100. if(transactionManager != null) {
  101. // Let's set it no matter what.
  102. transactionManager.setRollbackOnly();
  103. }
  104. } catch (Exception exn) {
  105. logger.logError("Problem rolling back session mgmt transaction",
  106. exn);
  107. }
  108. } finally {
  109. if (doTx) {
  110. try {
  111. if (transactionManager.getTransaction().getStatus() != Status.STATUS_MARKED_ROLLBACK) {
  112. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  113. logger.logDebug("transaction manager committing transaction");
  114. }
  115. transactionManager.commit();
  116. } else {
  117. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  118. logger.logDebug("endBatch(): rolling back batch");
  119. }
  120. transactionManager.rollback();
  121. }
  122. } catch (RollbackException re) {
  123. // Do nothing here since cache may rollback automatically.
  124. logger.logWarning("endBatch(): rolling back transaction with exception: "
  125. + re);
  126. } catch (RuntimeException re) {
  127. throw re;
  128. } catch (Exception e) {
  129. throw new RuntimeException(
  130. "endTransaction(): Caught Exception ending batch: ",
  131. e);
  132. }
  133. }
  134. }
  135. return (SIPDialog) haSipDialog;
  136. }
  137. /*
  138. * (non-Javadoc)
  139. * @see org.mobicents.ha.javax.sip.cache.SipCache#updateDialog(gov.nist.javax.sip.stack.SIPDialog)
  140. */
  141. public void updateSIPDialog(SIPDialog sipDialog) throws SipCacheException {
  142. final String dialogId = sipDialog.getDialogId();
  143. final Cache jbossCache = getMobicentsCache().getJBossCache();
  144. Configuration config = jbossCache.getConfiguration();
  145. final boolean isBuddyReplicationEnabled = config.getBuddyReplicationConfig() != null && config.getBuddyReplicationConfig().isEnabled();
  146. TransactionManager transactionManager = config.getRuntimeConfig().getTransactionManager();
  147. boolean doTx = false;
  148. try {
  149. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  150. logger.logDebug("transaction manager :" + transactionManager);
  151. }
  152. if(transactionManager != null && transactionManager.getTransaction() == null) {
  153. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  154. logger.logDebug("transaction manager begin transaction");
  155. }
  156. transactionManager.begin();
  157. doTx = true;
  158. }
  159. // Issue 1517 : http://code.google.com/p/mobicents/issues/detail?id=1517
  160. // Adding code to handle Buddy replication to force data gravitation
  161. if(isBuddyReplicationEnabled) {
  162. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  163. logger.logDebug("forcing data gravitation since buddy replication is enabled");
  164. }
  165. jbossCache.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
  166. }
  167. final Node<String,Object> childNode = getNode().getChild(dialogId);
  168. if(childNode != null) {
  169. try {
  170. final Map<String, Object> dialogMetaData = childNode.getData();
  171. final HASipDialog haSipDialog = (HASipDialog) sipDialog;
  172. final Object dialogAppData = childNode.get(APPDATA);
  173. updateDialog(haSipDialog, dialogMetaData, dialogAppData);
  174. } catch (CacheException e) {
  175. throw new SipCacheException("A problem occured while retrieving the following dialog " + dialogId + " from the Cache", e);
  176. }
  177. }
  178. } catch (Exception ex) {
  179. try {
  180. if(transactionManager != null) {
  181. // Let's set it no matter what.
  182. transactionManager.setRollbackOnly();
  183. }
  184. } catch (Exception exn) {
  185. logger.logError("Problem rolling back session mgmt transaction",
  186. exn);
  187. }
  188. } finally {
  189. if (doTx) {
  190. try {
  191. if (transactionManager.getTransaction().getStatus() != Status.STATUS_MARKED_ROLLBACK) {
  192. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  193. logger.logDebug("transaction manager committing transaction");
  194. }
  195. transactionManager.commit();
  196. } else {
  197. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  198. logger.logDebug("endBatch(): rolling back batch");
  199. }
  200. transactionManager.rollback();
  201. }
  202. } catch (RollbackException re) {
  203. // Do nothing here since cache may rollback automatically.
  204. logger.logWarning("endBatch(): rolling back transaction with exception: "
  205. + re);
  206. } catch (RuntimeException re) {
  207. throw re;
  208. } catch (Exception e) {
  209. throw new RuntimeException(
  210. "endTransaction(): Caught Exception ending batch: ",
  211. e);
  212. }
  213. }
  214. }
  215. }
  216. public HASipDialog createDialog(String dialogId, Map<String, Object> dialogMetaData, Object dialogAppData) throws SipCacheException {
  217. HASipDialog haSipDialog = null;
  218. if(dialogMetaData != null) {
  219. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  220. logger.logDebug("sipStack " + this + " dialog " + dialogId + " is present in the distributed cache, recreating it locally");
  221. }
  222. final String lastResponseStringified = (String) dialogMetaData.get(AbstractHASipDialog.LAST_RESPONSE);
  223. try {
  224. final SIPResponse lastResponse = (SIPResponse) SipFactory.getInstance().createMessageFactory().createResponse(lastResponseStringified);
  225. haSipDialog = HASipDialogFactory.createHASipDialog(clusteredSipStack.getReplicationStrategy(), (SipProviderImpl)clusteredSipStack.getSipProviders().next(), lastResponse);
  226. haSipDialog.setDialogId(dialogId);
  227. updateDialogMetaData(dialogMetaData, dialogAppData, haSipDialog, true);
  228. // setLastResponse won't be called on recreation since version will be null on recreation
  229. haSipDialog.setLastResponse(lastResponse);
  230. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  231. logger.logDebug("HA SIP Dialog " + dialogId + " localTag = " + haSipDialog.getLocalTag());
  232. logger.logDebug("HA SIP Dialog " + dialogId + " remoteTag = " + haSipDialog.getRemoteTag());
  233. logger.logDebug("HA SIP Dialog " + dialogId + " localParty = " + haSipDialog.getLocalParty());
  234. logger.logDebug("HA SIP Dialog " + dialogId + " remoteParty = " + haSipDialog.getRemoteParty());
  235. }
  236. } catch (PeerUnavailableException e) {
  237. throw new SipCacheException("A problem occured while retrieving the following dialog " + dialogId + " from the Cache", e);
  238. } catch (ParseException e) {
  239. throw new SipCacheException("A problem occured while retrieving the following dialog " + dialogId + " from the Cache", e);
  240. }
  241. }
  242. return haSipDialog;
  243. }
  244. public void updateDialog(HASipDialog haSipDialog, Map<String, Object> dialogMetaData,
  245. Object dialogAppData) throws SipCacheException {
  246. if(dialogMetaData != null) {
  247. final long currentVersion = haSipDialog.getVersion();
  248. final Long cacheVersion = ((Long)dialogMetaData.get(AbstractHASipDialog.VERSION));
  249. if(cacheVersion != null && currentVersion < cacheVersion.longValue()) {
  250. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  251. logger.logDebug("HA SIP Dialog " + haSipDialog + " with dialogId " + haSipDialog.getDialogIdToReplicate() + " is older " + currentVersion + " than the one in the cache " + cacheVersion + " updating it");
  252. }
  253. try {
  254. final String lastResponseStringified = (String) dialogMetaData.get(AbstractHASipDialog.LAST_RESPONSE);
  255. final SIPResponse lastResponse = (SIPResponse) SipFactory.getInstance().createMessageFactory().createResponse(lastResponseStringified);
  256. haSipDialog.setLastResponse(lastResponse);
  257. updateDialogMetaData(dialogMetaData, dialogAppData, haSipDialog, false);
  258. } catch (PeerUnavailableException e) {
  259. throw new SipCacheException("A problem occured while retrieving the following dialog " + haSipDialog.getDialogIdToReplicate() + " from the TreeCache", e);
  260. } catch (ParseException e) {
  261. throw new SipCacheException("A problem occured while retrieving the following dialog " + haSipDialog.getDialogIdToReplicate() + " from the TreeCache", e);
  262. }
  263. } else {
  264. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  265. logger.logDebug("HA SIP Dialog " + haSipDialog + " with dialogId " + haSipDialog.getDialogIdToReplicate() + " is not older " + currentVersion + " than the one in the cache " + cacheVersion + ", not updating it");
  266. }
  267. }
  268. }
  269. }
  270. /**
  271. * Update the haSipDialog passed in param with the dialogMetaData and app meta data
  272. * @param dialogMetaData
  273. * @param dialogAppData
  274. * @param haSipDialog
  275. * @throws ParseException
  276. * @throws PeerUnavailableException
  277. */
  278. private void updateDialogMetaData(Map<String, Object> dialogMetaData, Object dialogAppData, HASipDialog haSipDialog, boolean recreation) throws ParseException,
  279. PeerUnavailableException {
  280. haSipDialog.setMetaDataToReplicate(dialogMetaData, recreation);
  281. haSipDialog.setApplicationDataToReplicate(dialogAppData);
  282. final String contactStringified = (String) dialogMetaData.get(AbstractHASipDialog.CONTACT_HEADER);
  283. if(contactStringified != null) {
  284. Address contactAddress = SipFactory.getInstance().createAddressFactory().createAddress(contactStringified);
  285. ContactHeader contactHeader = SipFactory.getInstance().createHeaderFactory().createContactHeader(contactAddress);
  286. haSipDialog.setContactHeader(contactHeader);
  287. }
  288. }
  289. public void putSIPDialog(SIPDialog dialog) throws SipCacheException {
  290. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  291. logger.logStackTrace();
  292. }
  293. final HASipDialog haSipDialog = (HASipDialog) dialog;
  294. final String dialogId = haSipDialog.getDialogIdToReplicate();
  295. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  296. logger.logDebug("put HA SIP Dialog " + dialog + " with dialog " + dialogId);
  297. }
  298. final Cache jbossCache = getMobicentsCache().getJBossCache();
  299. TransactionManager transactionManager = jbossCache.getConfiguration().getRuntimeConfig().getTransactionManager();
  300. boolean doTx = false;
  301. try {
  302. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  303. logger.logDebug("transaction manager :" + transactionManager);
  304. }
  305. if(transactionManager != null && transactionManager.getTransaction() == null) {
  306. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  307. logger.logDebug("transaction manager begin transaction");
  308. }
  309. transactionManager.begin();
  310. doTx = true;
  311. }
  312. final Node childNode = getNode().addChild(Fqn.fromElements(dialogId));
  313. for (Entry<String, Object> metaData : haSipDialog.getMetaDataToReplicate().entrySet()) {
  314. childNode.put(metaData.getKey(), metaData.getValue());
  315. }
  316. final Object dialogAppData = haSipDialog.getApplicationDataToReplicate();
  317. if(dialogAppData != null) {
  318. childNode.put(APPDATA, dialogAppData);
  319. }
  320. } catch (Exception ex) {
  321. try {
  322. if(transactionManager != null) {
  323. // Let's set it no matter what.
  324. transactionManager.setRollbackOnly();
  325. }
  326. } catch (Exception exn) {
  327. logger.logError("Problem rolling back session mgmt transaction",
  328. exn);
  329. }
  330. } finally {
  331. if (doTx) {
  332. try {
  333. if (transactionManager.getTransaction().getStatus() != Status.STATUS_MARKED_ROLLBACK) {
  334. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  335. logger.logDebug("transaction manager committing transaction");
  336. }
  337. transactionManager.commit();
  338. } else {
  339. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  340. logger.logDebug("endBatch(): rolling back batch");
  341. }
  342. transactionManager.rollback();
  343. }
  344. } catch (RollbackException re) {
  345. // Do nothing here since cache may rollback automatically.
  346. logger.logWarning("endBatch(): rolling back transaction with exception: "
  347. + re);
  348. } catch (RuntimeException re) {
  349. throw re;
  350. } catch (Exception e) {
  351. throw new RuntimeException(
  352. "endTransaction(): Caught Exception ending batch: ",
  353. e);
  354. }
  355. }
  356. }
  357. }
  358. public boolean removeSIPDialog(String dialogId) {
  359. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  360. logger.logDebug("remove HA SIP Dialog " + dialogId);
  361. }
  362. boolean succeeded = false;
  363. final Cache jbossCache = getMobicentsCache().getJBossCache();
  364. TransactionManager transactionManager = jbossCache.getConfiguration().getRuntimeConfig().getTransactionManager();
  365. boolean doTx = false;
  366. try {
  367. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  368. logger.logDebug("transaction manager :" + transactionManager);
  369. }
  370. if(transactionManager != null && transactionManager.getTransaction() == null) {
  371. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  372. logger.logDebug("transaction manager begin transaction");
  373. }
  374. transactionManager.begin();
  375. doTx = true;
  376. }
  377. succeeded = getNode().removeChild(dialogId);
  378. } catch (Exception ex) {
  379. try {
  380. if(transactionManager != null) {
  381. // Let's set it no matter what.
  382. transactionManager.setRollbackOnly();
  383. }
  384. } catch (Exception exn) {
  385. logger.logError("Problem rolling back session mgmt transaction",
  386. exn);
  387. }
  388. } finally {
  389. if (doTx) {
  390. try {
  391. if (transactionManager.getTransaction().getStatus() != Status.STATUS_MARKED_ROLLBACK) {
  392. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  393. logger.logDebug("transaction manager committing transaction");
  394. }
  395. transactionManager.commit();
  396. } else {
  397. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  398. logger.logDebug("endBatch(): rolling back batch");
  399. }
  400. transactionManager.rollback();
  401. }
  402. } catch (RollbackException re) {
  403. // Do nothing here since cache may rollback automatically.
  404. logger.logWarning("endBatch(): rolling back transaction with exception: "
  405. + re);
  406. } catch (RuntimeException re) {
  407. throw re;
  408. } catch (Exception e) {
  409. throw new RuntimeException(
  410. "endTransaction(): Caught Exception ending batch: ",
  411. e);
  412. }
  413. }
  414. }
  415. return succeeded;
  416. }
  417. public void evictSIPDialog(String dialogId) {
  418. getMobicentsCache().getJBossCache().evict(Fqn.fromElements(getNodeFqn(), Fqn.fromString(dialogId)));
  419. if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
  420. logger.logDebug("HA SIP Dialog " + dialogId + " evicted");
  421. }
  422. }
  423. }