/// <summary> /// Pull out sorted batches from the RowSorter instance and save them using the IBatchHandler implementation. /// Also return the first batch as an output. /// </summary> /// <param name="rowSorter">RowSorter instance.</param> /// <returns>The first batch pulled from the RowSorter.</returns> private Batch SaveBatchesAndReturnFirstBatch(RowSorter rowSorter) { // Get an enumerator over the batch list. IEnumerable<RowSorter.SortedBatch> batchEnumerator = rowSorter.PullSortedBatches(); // Prepare a batch header instance. The BatchCode will be the folder name under which we will write files corresponding // to each sorted batch. Every batch will have a knowledge that contains the information in the batch. So we have to combine // the existing client knowledge with the batch knowledge before returning it back to the caller. var header = new BatchHeader { BatchCode = Guid.NewGuid(), // New batch code. BatchFileNames = new List<string>() }; var batchList = new List<Batch>(); Guid batchName = Guid.NewGuid(); Guid nextBatchName = Guid.NewGuid(); foreach (var sortedBatch in batchEnumerator) { // Create a new batch instance. var b = new Batch { BatchCode = header.BatchCode, FileName = batchName.ToString(), // Random file name LearnedKnowledge = sortedBatch.sortedDataSetKnowledge.Serialize(), Data = sortedBatch.sortedDataSet, ClientScopeName = _clientScopeName, NextBatch = nextBatchName }; header.BatchFileNames.Add(b.FileName); batchList.Add(b); // Set the batch names. batchName = nextBatchName; nextBatchName = Guid.NewGuid(); } // If there are no batches, just return. if (0 == batchList.Count) { return null; } // Set properties for the last batch. batchList[batchList.Count - 1].IsLastBatch = true; batchList[batchList.Count - 1].NextBatch = null; // Only save if we have more than 1 batch. if (batchList.Count > 1) { // Save all but the first batch, since we are sending that to the client as a response to the current request. _batchHandler.SaveBatches(batchList.Skip(1).ToList(), header); } // Return the first batch. return batchList[0]; }
/// <summary> /// Gets the next batch in a sequence. /// </summary> /// <param name="batchCode">Batch code value</param> /// <param name="nextBatchSequenceNumber">Sequence number of the next batch</param> /// <returns>Batch information</returns> public Batch GetNextBatch(Guid batchCode, Guid nextBatchSequenceNumber) { // Create the batch directory. var path = Path.Combine(_batchSpoolDirectory, batchCode.ToString()); if (!Directory.Exists(path)) { // no batch found. return(null); } string headerFilePath = Path.Combine(path, BATCH_HEADER_FILENAME); BatchHeader header = null; if (File.Exists(headerFilePath)) { var headerFormatter = new BinaryFormatter(); using (var fileStream = new FileStream(headerFilePath, FileMode.Open, FileAccess.Read)) { header = headerFormatter.Deserialize(fileStream) as BatchHeader; } } if (null == header) { // no header return(null); } // Get the batch file name from the header. string batchFile = header.BatchFileNames.Where(b => new Guid(b) == nextBatchSequenceNumber).FirstOrDefault(); if (String.IsNullOrEmpty(batchFile)) { // missing batch file. return(null); } string batchFilePath = Path.Combine(path, batchFile); Batch batch = null; if (File.Exists(batchFilePath)) { var formatter = new BinaryFormatter(); using (var fileStream = new FileStream(batchFilePath, FileMode.Open, FileAccess.Read)) { batch = formatter.Deserialize(fileStream) as Batch; } } if (null != batch) { string filePath = Path.Combine(path, batch.FileName); if (File.Exists(filePath)) { File.Delete(filePath); } if (batch.IsLastBatch) { // If this is the last batch then try to cleanup the directory. CleanupBatchDirectory(path, headerFilePath, header); } } return(batch); }