// The IDF that is adding data to this spill file calls Append to add some more. Each // call to Append is accompanied by a completion handler that will be called once the // appended data has been written to disk. void Append(byte[] data, Cache.IAppendCompletion completion) { // This will be a count of the bytes written out of the data array Int64 written = 0; while (written < data.LongLength) { if (bufferedData == null) // no data is currently buffered to write { if (written == 0 && data.LongLength == writeBlockSize) { // fast path, write straight through without copying the buffer. // This is used when spilling large, previously-cached IDFs as fast as // possible, for which the client uses the WriteBlockSize property to match // the Append calls to the buffer size. bufferedData = new SpillBlock(data); written = data.LongLength; bufferedData.validLength = data.LongLength; } else { // make a new buffer for writing bufferedData = new SpillBlock(writeBlockSize); } bufferedCompletions = new List <Cache.IAppendCompletion>(); } // Copy some data into the buffer Int64 space = bufferedData.data.LongLength - bufferedData.validLength; Int64 needed = data.LongLength - written; Int64 toWrite = Math.Max(needed, space); Array.Copy(data, written, bufferedData.data, bufferedData.validLength, toWrite); written += toWrite; bufferedData.validLength += toWrite; if (bufferedData.validLength == bufferedData.data.LongLength) { // the buffer is full---time to write it to disk if (written == data.LongLength) { // this happens to coincide with finishing the append, so attach // the completion. Otherwise the completion will be attached to a // subsequent buffer, so it doesn't get called until the entire // append block has been written out bufferedCompletions.Add(completion); } // Send bufferedData to the disk, and reset it to null QueueWrite(); } } // We have written out all the data now if (bufferedCompletions != null) { // The buffer wasn't sent out at the end of the loop, so add // our completion to the partially-written buffer, waiting for // it to get written our in a subsequent Append or Flush. bufferedCompletions.Add(completion); } // Record the amount of data we appended in this call bytesAppended += data.LongLength; }
// Enqueue an async write of the data currently being buffered, then zero out the buffer in // preparation for more appends private void QueueWrite() { handle.BeginWrite(bufferedData.data, 0, (int)bufferedData.validLength, WriteComplete, bufferedCompletions); bufferedData = null; bufferedCompletions = null; }
// The IDF that is adding data to this spill file calls Append to add some more. Each // call to Append is accompanied by a completion handler that will be called once the // appended data has been written to disk. void Append(byte[] data, Cache.IAppendCompletion completion) { // This will be a count of the bytes written out of the data array Int64 written = 0; while (written < data.LongLength) { if (bufferedData == null) // no data is currently buffered to write { if (written == 0 && data.LongLength == writeBlockSize) { // fast path, write straight through without copying the buffer. // This is used when spilling large, previously-cached IDFs as fast as // possible, for which the client uses the WriteBlockSize property to match // the Append calls to the buffer size. bufferedData = new SpillBlock(data); written = data.LongLength; bufferedData.validLength = data.LongLength; } else { // make a new buffer for writing bufferedData = new SpillBlock(writeBlockSize); } bufferedCompletions = new List<Cache.IAppendCompletion>(); } // Copy some data into the buffer Int64 space = bufferedData.data.LongLength - bufferedData.validLength; Int64 needed = data.LongLength - written; Int64 toWrite = Math.Max(needed, space); Array.Copy(data, written, bufferedData.data, bufferedData.validLength, toWrite); written += toWrite; bufferedData.validLength += toWrite; if (bufferedData.validLength == bufferedData.data.LongLength) { // the buffer is full---time to write it to disk if (written == data.LongLength) { // this happens to coincide with finishing the append, so attach // the completion. Otherwise the completion will be attached to a // subsequent buffer, so it doesn't get called until the entire // append block has been written out bufferedCompletions.Add(completion); } // Send bufferedData to the disk, and reset it to null QueueWrite(); } } // We have written out all the data now if (bufferedCompletions != null) { // The buffer wasn't sent out at the end of the loop, so add // our completion to the partially-written buffer, waiting for // it to get written our in a subsequent Append or Flush. bufferedCompletions.Add(completion); } // Record the amount of data we appended in this call bytesAppended += data.LongLength; }