public void Recover(MessageQueue recoveryQueue, string correlationId) { var conversations = LargeMessage.GetConversationsOfCorrelation(recoveryQueue, correlationId); var dtctoPo = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.PO_DTC_RECOVERY)); var sqltoPo = Kiss.GetTimeout(KissTimeout.PO_SQL_RECOVERY); using (var scope = new TransactionScope(TransactionScopeOption.Required, dtctoPo)) using (var kiss = new SqlConnection(Kiss.GetConnection(_sql))) using (var poRemoval = new SqlCommand(PROCEDURE_PO_REMOVAL_ALL, kiss) { CommandTimeout = sqltoPo, CommandType = CommandType.StoredProcedure }) { kiss.Open(); poRemoval.ExecuteNonQuery(); kiss.Close(); foreach (var conversation in conversations) { OnProcessMessage(KissTransactionMode.DTC, recoveryQueue, conversation); } scope.Complete(); } }
protected override void OnProcessMessage(KissTransactionMode mode, MessageQueue queue, Guid conversation) { long id, maxId = ID_NO_VALUE; string clientId, recoveryClient; Message bundleControl; MessageQueueTransaction transaction = null; var convMessages = LargeMessage.GetMessagesOfConversation(queue, conversation); var allBundleIds = Bundle.RetrieveAll(_sql); var ttrqBundle = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.BUNDLE_TTRQ)); var ttbrBundle = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.BUNDLE_TTBR)); var timeout = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.BUNDLE_CONTROL_RECEIVE_TIMEOUT)); if (mode == KissTransactionMode.DTC) { throw new NotSupportedException("DTC"); } try { transaction = new MessageQueueTransaction(); transaction.Begin(); bundleControl = queue.ReceiveById(convMessages[0], timeout, transaction); recoveryClient = (string)bundleControl.Body; foreach (var bundleId in allBundleIds) { id = long.Parse(bundleId.Split(SEPARATOR_BUNDLE_IDS)[0]); clientId = bundleId.Split(SEPARATOR_BUNDLE_IDS)[1]; if (clientId == recoveryClient && id > maxId) { maxId = id; } } using (var msg = new Message(maxId) { CorrelationId = bundleControl.Id, Formatter = bundleControl.Formatter, TimeToReachQueue = ttrqBundle, TimeToBeReceived = ttbrBundle, Extension = LargeMessage.ToMessageExtension(Guid.NewGuid()) }) { bundleControl.ResponseQueue.Send(msg, transaction); } transaction.Commit(); } finally { if (transaction != null) { transaction.Dispose(); } } }
protected override void DistributeMSMQ(KissTransactionMode mode, bool remove, string[] filter, LargeMessage largeMessage) { List <MessageQueue> allQueues = null; MessageQueueTransaction msmqTransaction = null; var ttrqPo = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.PO_TTRQ)); var ttbrPo = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.PO_TTBR)); try { largeMessage.EncodeExtension(new[] { _id, DateTime.Now.ToBinary().ToString(), remove.ToString() }); allQueues = new Neighborhood(_sql, FORMAT_PO_POSTFIX).GetAllQueues(filter); if (allQueues.Count > 0) { if (mode == KissTransactionMode.MSMQ) { msmqTransaction = new MessageQueueTransaction(); msmqTransaction.Begin(); } foreach (var queue in allQueues) { largeMessage.Send(queue, msmqTransaction, ttrqPo, ttbrPo); } if (mode == KissTransactionMode.MSMQ) { msmqTransaction.Commit(); } } } catch { if (msmqTransaction != null && mode == KissTransactionMode.MSMQ) { msmqTransaction.Abort(); } throw; } finally { if (msmqTransaction != null) { msmqTransaction.Dispose(); } if (allQueues != null) { foreach (var queue in allQueues) { queue.Dispose(); } } } }
public void Respond(MessageQueue responseQueue, MessageQueueTransaction transaction, string correlationId) { var largeMessage = new LargeMessage(DataBuffer, null, _msmqCapacity, correlationId, null); var ttrqPo = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.PO_TTRQ)); var ttbrPo = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.PO_TTBR)); largeMessage.EncodeExtension(new[] { _id, DateTime.Now.ToBinary().ToString(), false.ToString() }); largeMessage.Send(responseQueue, transaction, ttrqPo, ttbrPo); }
private void PeekCompleted(object source, PeekCompletedEventArgs eventArgs) { var abortQueue = false; try { using (var peek = _localQueue.EndPeek(eventArgs.AsyncResult)) { if (peek.AppSpecific != APP_SPECIFIC_STOP) { foreach (var conversation in LargeMessage.GetAvailableConversations(_localQueue)) { OnProcessMessage(_mode, _localQueue, conversation); } } else { _localQueue.ReceiveById(peek.Id, MessageQueueTransactionType.Single).Dispose(); DisposeLocalQueue(); } } } catch (MessageQueueException me) { if (me.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout && me.MessageQueueErrorCode != MessageQueueErrorCode.TransactionEnlist) { abortQueue = true; } } catch (SqlException) { abortQueue = true; } catch (TransactionAbortedException) { abortQueue = true; } catch { abortQueue = true; } if (abortQueue) { DisposeLocalQueue(); } else if (_started) { Thread.Sleep(SLEEP_PEEK_NEXT_MESSAGE); _localQueue.BeginPeek(); } }
protected bool Retrieve(string retrieveProcedure, SqlParameter[] retrieveParameters, string dataName) { byte[] dataBuffer = (byte[])Retrieve(_sql, retrieveProcedure, retrieveParameters, dataName); var retrieved = dataBuffer != null; if (retrieved) { _bufferIndex = Math.Min(_bufferIndex, dataBuffer.Length); _largeMessage = new LargeMessage(dataBuffer, null, _msmqCapacity, null, _outputHeader); } return(retrieved); }
protected DistributionBase(string sql, byte[] dataBuffer, int bufferIndex, int msmqCapacity, string outputHeader) { byte[] dataBufferCopy; _sql = sql; _msmqCapacity = msmqCapacity; _outputHeader = outputHeader; _bufferIndex = Math.Abs(bufferIndex); if (dataBuffer != null) { dataBufferCopy = new byte[_bufferIndex + dataBuffer.Length]; Array.Copy(dataBuffer, 0, dataBufferCopy, _bufferIndex, dataBuffer.Length); } else { dataBufferCopy = new byte[_bufferIndex]; } _largeMessage = new LargeMessage(dataBufferCopy, null, msmqCapacity, null, outputHeader); }
protected override void OnProcessMessage(KissTransactionMode mode, MessageQueue queue, Guid conversation) { Message poControl; PersistentObject po; MessageQueueTransaction transaction = null; var convMessages = LargeMessage.GetMessagesOfConversation(queue, conversation); var allPoIds = PersistentObject.RetrieveAll(_sql); var timeout = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.PO_CONTROL_RECEIVE_TIMEOUT)); if (mode == KissTransactionMode.DTC) { throw new NotSupportedException("DTC"); } try { transaction = new MessageQueueTransaction(); transaction.Begin(); poControl = queue.ReceiveById(convMessages[0], timeout, transaction); foreach (var poId in allPoIds) { po = new PersistentObject(_sql, poId, _msmqCapacity); po.Retrieve(); po.Respond(poControl.ResponseQueue, transaction, poControl.Id); } transaction.Commit(); } finally { if (transaction != null) { transaction.Dispose(); } } }
public string[] DecodeExtension() { return(LargeMessage.DecodeMessageExtension(_messageExtension)); }
public void EncodeExtension(string[] values) { _messageExtension = LargeMessage.EncodeMessageExtension(values); }
protected abstract void DistributeMSMQ(KissTransactionMode mode, bool remove, string[] filter, LargeMessage largeMessage);
public void RecoverBundles() { long id, maxId = ID_NOT_RECEIVED_AT_BACKEND; bool responseAvailable, localRecoveryDone, remoteRecoveryDone; DateTime?selfLastUpdate; MessageQueue[] controlQueuesOpen, controlQueues = null; MessageQueue recoveryQueue = null; var ttrqBundleControl = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.BUNDLE_CONTROL_TTRQ)); var ttbrBundleControl = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.BUNDLE_CONTROL_TTBR)); try { controlQueues = new Neighborhood(_sql, FORMAT_BUNDLE_CONTROL_POSTFIX).GetOthersQueues().ToArray(); controlQueuesOpen = new MessageQueue[controlQueues.Length]; controlQueues.CopyTo(controlQueuesOpen, 0); recoveryQueue = new Neighborhood(_sql, FORMAT_BUNDLE_RECOVERY_POSTFIX).GetLocalQueue(); localRecoveryDone = !(controlQueues.Length > 0); while (!localRecoveryDone) { for (var i = 0; i < controlQueues.Length; i++) { if (controlQueuesOpen[i] == null) { continue; } using (var msg = new Message(_clientId) { ResponseQueue = recoveryQueue, Formatter = controlQueues[i].Formatter, TimeToReachQueue = ttrqBundleControl, TimeToBeReceived = ttbrBundleControl, Extension = LargeMessage.ToMessageExtension(Guid.NewGuid()) }) { responseAvailable = false; controlQueues[i].Send(msg, MessageQueueTransactionType.Single); for (var j = 0; j < MAX_RETRY_BUNDLE_RECOVERY && !responseAvailable; j++) { Thread.Sleep(SLEEP_BUNDLE_RECOVERY); responseAvailable = LargeMessage.IsCorrelationAvailable(recoveryQueue, msg.Id); } if (responseAvailable) { using (var response = recoveryQueue. ReceiveByCorrelationId(msg.Id, MessageQueueTransactionType.Single)) { id = (long)response.Body; if (id > maxId) { maxId = id; } } controlQueuesOpen[i] = null; } } } localRecoveryDone = Array.TrueForAll(controlQueuesOpen, q => q == null); } RemoveAllBundlesAndStages(); do { QueryStageList(true); WaitForSelfStage(true, null, out id, out selfLastUpdate); remoteRecoveryDone = id != ID_NO_ANSWER_FROM_BACKEND; if (!remoteRecoveryDone) { Thread.Sleep(SLEEP_BUNDLE_RECOVERY); } } while (!remoteRecoveryDone); if (id > maxId) { maxId = id; } if (maxId != ID_NOT_RECEIVED_AT_BACKEND) { new Bundle(_sql, maxId, _clientId, _msmqCapacity).Recover(); } } finally { if (recoveryQueue != null) { recoveryQueue.Dispose(); } if (controlQueues != null) { foreach (var queue in controlQueues) { queue.Dispose(); } } } }
public void RecoverPersistentObjects() { bool localRecoveryDone; List <MessageQueue> controlQueues = null; MessageQueue recoveryQueue = null; var poListener = new PersistentObjectListener(_sql, _msmqCapacity); var ttrqPoControl = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.PO_CONTROL_TTRQ)); var ttbrPoControl = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.PO_CONTROL_TTBR)); try { controlQueues = new Neighborhood(_sql, FORMAT_PO_CONTROL_POSTFIX).GetOthersQueues(); recoveryQueue = new Neighborhood(_sql, FORMAT_PO_RECOVERY_POSTFIX).GetLocalQueue(); localRecoveryDone = !(controlQueues.Count > 0); if (localRecoveryDone) { poListener.Recover(recoveryQueue, string.Empty); } while (!localRecoveryDone) { foreach (var controlQueue in controlQueues) { using (var msg = new Message { ResponseQueue = recoveryQueue, Formatter = controlQueue.Formatter, TimeToReachQueue = ttrqPoControl, TimeToBeReceived = ttbrPoControl, Extension = LargeMessage.ToMessageExtension(Guid.NewGuid()) }) { controlQueue.Send(msg, MessageQueueTransactionType.Single); for (var i = 0; i < MAX_RETRY_PO_RECOVERY && !localRecoveryDone; i++) { Thread.Sleep(SLEEP_PO_RECOVERY); localRecoveryDone = LargeMessage.IsCorrelationAvailable(recoveryQueue, msg.Id); } if (localRecoveryDone) { poListener.Recover(recoveryQueue, msg.Id); break; } } } } } finally { if (recoveryQueue != null) { recoveryQueue.Dispose(); } if (controlQueues != null) { foreach (var queue in controlQueues) { queue.Dispose(); } } } }
protected override void OnProcessMessage(KissTransactionMode mode, MessageQueue queue, Guid conversation) { string[] extension; MessageQueueTransaction msmqTransaction = null; var convMessages = LargeMessage.GetMessagesOfConversation(queue, conversation); var largeMessage = new LargeMessage(_msmqCapacity, null); var dtctoPo = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.PO_DTC_STORAGE)); var sqltoPo = Kiss.GetTimeout(KissTimeout.PO_SQL_STORAGE); try { using (var scope = new TransactionScope(TransactionScopeOption.Required, dtctoPo)) using (var kiss = new SqlConnection(Kiss.GetConnection(_sql))) using (var poStorage = new SqlCommand(PROCEDURE_PO_STORAGE, kiss) { CommandTimeout = sqltoPo, CommandType = CommandType.StoredProcedure }) using (var poRemoval = new SqlCommand(PROCEDURE_PO_REMOVAL, kiss) { CommandTimeout = sqltoPo, CommandType = CommandType.StoredProcedure }) { if (mode == KissTransactionMode.DTC) { largeMessage.Receive(queue, null, convMessages, Kiss.GetTimeout(KissTimeout.PO_RECEIVE_TIMEOUT)); } else { using (var suppress = new TransactionScope(TransactionScopeOption.Suppress)) { msmqTransaction = new MessageQueueTransaction(); msmqTransaction.Begin(); largeMessage.Receive(queue, msmqTransaction, convMessages, Kiss.GetTimeout(KissTimeout.PO_RECEIVE_TIMEOUT)); suppress.Complete(); } } extension = largeMessage.DecodeExtension(); kiss.Open(); if (bool.Parse(extension[2])) { poRemoval.Parameters.AddWithValue("@po_id", extension[0]); poRemoval.ExecuteNonQuery(); } else { poStorage.Parameters.AddWithValue("@po_id", extension[0]); poStorage.Parameters.AddWithValue("@po_sent", DateTime.FromBinary(long.Parse(extension[1]))); poStorage.Parameters.AddWithValue("@po_received", DateTime.Now); poStorage.Parameters.AddWithValue("@po", largeMessage.DataBuffer); poStorage.ExecuteNonQuery(); } kiss.Close(); scope.Complete(); } if (mode != KissTransactionMode.DTC) { msmqTransaction.Commit(); } } catch { if (msmqTransaction != null && mode == KissTransactionMode.MSMQ) { msmqTransaction.Abort(); } throw; } finally { if (msmqTransaction != null) { msmqTransaction.Dispose(); } } }
protected override void DistributeMSMQ(KissTransactionMode mode, bool remove, string[] filter, LargeMessage largeMessage) { object sequenceNumber; string bundleSentChar; DateTime bundleSent; MessageQueueTransaction msmqTransaction = null; List <MessageQueue> othersQueues = null; var ttrqBundle = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.BUNDLE_TTRQ)); var ttbrBundle = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.BUNDLE_TTBR)); var dialogLifetime = Kiss.GetTimeout(KissTimeout.BUNDLE_SSSB); var dtctoBundle = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.BUNDLE_DTC_DISTRIBUTION)); if (remove) { throw new NotSupportedException("remove"); } try { othersQueues = new Neighborhood(_sql, FORMAT_BUNDLE_POSTFIX).GetOthersQueues(filter); using (var scope = new TransactionScope(TransactionScopeOption.Required, dtctoBundle)) { bundleSent = DateTime.Now; bundleSentChar = bundleSent.ToString(FORMAT_BUNDLE_SENT, DateTimeFormatInfo.InvariantInfo); Process(PROCEDURE_BUNDLE_PROCESSING, new[] { new SqlParameter("@client_id", _clientId), new SqlParameter("@bundle_sent", bundleSent), new SqlParameter("@bundle_sent_char", bundleSentChar), new SqlParameter("@dialog_lifetime", dialogLifetime) }, "@bundle", out sequenceNumber); largeMessage.EncodeExtension(new[] { sequenceNumber.ToString(), _clientId, bundleSent.ToBinary().ToString() }); if (mode == KissTransactionMode.DTC) { foreach (var queue in othersQueues) { largeMessage.Send(queue, null, ttrqBundle, ttbrBundle); } } else { using (var suppress = new TransactionScope(TransactionScopeOption.Suppress)) { msmqTransaction = new MessageQueueTransaction(); msmqTransaction.Begin(); foreach (var queue in othersQueues) { largeMessage.Send(queue, msmqTransaction, ttrqBundle, ttbrBundle); } suppress.Complete(); } } scope.Complete(); } _id = (long)sequenceNumber; SetOutputHeader(string.Format(FORMAT_TO_STRING, _id, _clientId)); if (mode != KissTransactionMode.DTC) { msmqTransaction.Commit(); } } catch { if (msmqTransaction != null && mode == KissTransactionMode.MSMQ) { msmqTransaction.Abort(); } throw; } finally { if (msmqTransaction != null) { msmqTransaction.Dispose(); } if (othersQueues != null) { foreach (var queue in othersQueues) { queue.Dispose(); } } } }
protected override void OnProcessMessage(KissTransactionMode mode, MessageQueue queue, Guid conversation) { string[] extension; string bundleSentChar; DateTime bundleSent; MessageQueueTransaction msmqTransaction = null; var convMessages = LargeMessage.GetMessagesOfConversation(queue, conversation); var largeMessage = new LargeMessage(_msmqCapacity, null); var dtctoBundle = TimeSpan.FromSeconds(Kiss.GetTimeout(KissTimeout.BUNDLE_DTC_STORAGE)); var sqltoBundle = Kiss.GetTimeout(KissTimeout.BUNDLE_SQL_STORAGE); try { using (var scope = new TransactionScope(TransactionScopeOption.Required, dtctoBundle)) using (var kiss = new SqlConnection(Kiss.GetConnection(_sql))) using (var bundleStorage = new SqlCommand(PROCEDURE_BUNDLE_STORAGE, kiss) { CommandTimeout = sqltoBundle, CommandType = CommandType.StoredProcedure }) { if (mode == KissTransactionMode.DTC) { largeMessage.Receive(queue, null, convMessages, Kiss.GetTimeout(KissTimeout.BUNDLE_RECEIVE_TIMEOUT)); } else { using (var suppress = new TransactionScope(TransactionScopeOption.Suppress)) { msmqTransaction = new MessageQueueTransaction(); msmqTransaction.Begin(); largeMessage.Receive(queue, msmqTransaction, convMessages, Kiss.GetTimeout(KissTimeout.BUNDLE_RECEIVE_TIMEOUT)); suppress.Complete(); } } extension = largeMessage.DecodeExtension(); bundleSent = DateTime.FromBinary(long.Parse(extension[2])); bundleSentChar = bundleSent.ToString(FORMAT_BUNDLE_SENT, DateTimeFormatInfo.InvariantInfo); bundleStorage.Parameters.AddWithValue("@bundle_id", long.Parse(extension[0])); bundleStorage.Parameters.AddWithValue("@client_id", extension[1]); bundleStorage.Parameters.AddWithValue("@bundle_sent", bundleSent); bundleStorage.Parameters.AddWithValue("@bundle_received", DateTime.Now); bundleStorage.Parameters.AddWithValue("@bundle_sent_char", bundleSentChar); bundleStorage.Parameters.AddWithValue("@bundle", largeMessage.DataBuffer); kiss.Open(); bundleStorage.ExecuteNonQuery(); kiss.Close(); scope.Complete(); } if (mode != KissTransactionMode.DTC) { msmqTransaction.Commit(); } } catch { if (msmqTransaction != null && mode == KissTransactionMode.MSMQ) { msmqTransaction.Abort(); } throw; } finally { if (msmqTransaction != null) { msmqTransaction.Dispose(); } } }