public void AddAction(SMVAction action, SMVActionCompleteCallBack callback, object context) { try { Log.LogDebug("Reached AddAction of cloud" + action.GetFullName()); Log.LogDebug("Adding action " + action.GetFullName()); string actionGuid = Guid.NewGuid().ToString(); // Upload action directory to blob storage. string actionPath = Utility.GetActionDirectory(action); string zipPath = Path.Combine(Path.GetTempPath(), actionGuid); if (File.Exists(zipPath)) { File.Delete(zipPath); } ZipFile.CreateFromDirectory(actionPath, zipPath); Log.LogDebug("Created zip for " + actionPath); CloudBlockBlob blob = inputContainer.GetBlockBlobReference(actionGuid + ".zip"); blob.UploadFromFile(zipPath); File.Delete(zipPath); Log.LogDebug("Uploaded blob " + blob.Name); // Add entry to table storage. // TODO: Due to constraints on sizes of properties in Azure table entities, serializedAction cannot be larger // than 64kB. Fix this if this becomes an issue. byte[] serializedAction = Utility.ObjectToByteArray(action); string moduleHash = string.Empty; ActionsTableEntry entry = new ActionsTableEntry(action.name, actionGuid, schedulerInstanceGuid, serializedAction, Utility.version, null, moduleHash); tableDataSource.AddEntry(entry); Log.LogDebug("Added to table " + entry.PartitionKey + "," + entry.RowKey); CloudMessage cloudMessage = new CloudMessage(); cloudMessage.schedulerInstanceGuid = schedulerInstanceGuid; cloudMessage.actionGuid = actionGuid; cloudMessage.maxDequeueCount = maxDequeueCount; cloudMessage.useDb = Utility.useDb; cloudMessage.taskId = Utility.taskId; string messageString = JsonConvert.SerializeObject(cloudMessage); // Add message to queue. //Log.LogInfo("Executing: " + action.GetFullName() + " [cloud id:" + actionGuid + "]"); //string messageString = schedulerInstanceGuid + "," + actionGuid + "," + maxDequeueCount; var message = new CloudQueueMessage(messageString); actionsQueue.AddMessage(message); Log.LogDebug("Adding to queue " + message.Id); contextDictionary[actionGuid] = new CloudActionCompleteContext(action, callback, context); Log.LogDebug("Done adding."); } catch (Exception e) { Utility.scheduler.Dispose(); Log.LogFatalError(e.ToString()); } }
public void cloudExceptionCallback(BrokeredMessage message) { var actionGuid = (string)message.Properties["ActionGuid"]; CloudActionCompleteContext context = contextDictionary[actionGuid]; ActionsTableEntry entry = tableDataSource.GetEntry(schedulerInstanceGuid, actionGuid); var action = (SMVAction)Utility.ByteArrayToObject(entry.SerializedAction); context.action.analysisProperty = action.analysisProperty; context.action.result = action.result; context.action.variables = action.variables; var results = new SMVActionResult[] { context.action.result }; context.callback(context.action, results, context.context); }
/// <summary> /// Callback that is called when SubscriptionClient.BeginReceive() receives a message. /// </summary> /// <param name="ar"></param> private void ActionComplete(BrokeredMessage message) { var actionGuid = (string)message.Properties["ActionGuid"]; var waitTime = (TimeSpan)message.Properties["WaitTime"]; // The amount of time the rule had to wait before it started being processed. var dequeueCount = (int)message.Properties["DequeueCount"]; // The number of times the message we sent was dequeued by the workers. message.Complete(); CloudActionCompleteContext context = contextDictionary[actionGuid]; ActionsTableEntry entry = tableDataSource.GetEntry(schedulerInstanceGuid, actionGuid); var action = (SMVAction)Utility.ByteArrayToObject(entry.SerializedAction); Log.LogDebug("Reached ActionComplete of Cloud " + action.GetFullName()); if (action.result == null) { action.result = new SMVActionResult(action.name, "NO OUTPUT?", false, false, 0); Log.LogError(string.Format("Failed to complete action: {0} ({1})", actionGuid, context.action.name)); } Log.LogDebug("ActionComplete for " + action.GetFullName() + " [cloud id " + actionGuid + "]"); // Populate the original action object so that the master scheduler gets the changes to the action object. context.action.analysisProperty = action.analysisProperty; context.action.result = action.result; context.action.variables = action.variables; var results = new SMVActionResult[] { context.action.result }; if (entry.Status != (int)ActionStatus.Complete) { Log.LogError(string.Format("Failed to complete action: {0} ({1})", actionGuid, context.action.name)); context.callback(context.action, new SMVActionResult[] { context.action.result }, context.context); Utility.scheduler.errorsEncountered = true; return; } // Download and extract the results. string actionDirectory = Utility.GetActionDirectory(context.action); CloudBlockBlob resultsBlob = outputContainer.GetBlockBlobReference(actionGuid + ".zip"); string zipPath = Path.Combine(Path.GetTempPath(), actionGuid); if (File.Exists(zipPath)) { File.Delete(zipPath); } if (resultsBlob.Exists()) { resultsBlob.DownloadToFile(zipPath, FileMode.CreateNew); resultsBlob.Delete(); using (var archive = ZipFile.OpenRead(zipPath)) { foreach (var f in archive.Entries) { var toBeExtractedFilePath = Path.Combine(actionDirectory, f.FullName); if (File.Exists(toBeExtractedFilePath)) { File.Delete(toBeExtractedFilePath); } } archive.ExtractToDirectory(actionDirectory); } File.Delete(zipPath); // Write to the cloudstats.txt file. var contents = new string[] { "Wait Time: " + waitTime.ToString(), "Dequeue Count: " + dequeueCount, "Output" + Environment.NewLine + results.First().output }; File.AppendAllLines(Path.Combine(actionDirectory, "cloudstats.txt"), contents); Log.LogDebug("download results for " + action.GetFullName() + " [cloud id " + actionGuid + "]"); } else { Log.LogInfo("Results for " + action.GetFullName() + " [cloud id " + actionGuid + "] not available!"); } context.callback(context.action, results, context.context); }