in AdlsDotNetSDK/FileTransfer/Jobs/CopyFileJob.cs [183:261]
private void TransferChunks(Stream readStream, Stream writeStream)
{
readStream.Seek(_offset, SeekOrigin.Begin);
var readBytes = new byte[BuffSize];
// Index till which there is data already in the buffer
var residualDataSize = 0;
// Only for upload, non-binary and chunked uploads
// Each thread respnsible for a chunk will look for the first newline in it's chunk and it will start uploading after that
// And after it's chunk is uploaded then read forward into the next chunk till it gets a new line.
if (Metadata.IsUpload && !Metadata.IsBinary && ChunkIndex > 0)
{
int indexAfterNewLine = ReadForwardTillNewLine(readStream, readBytes, 0);
int finalReadData = (int)(readStream.Position - _offset); // Bytes of data read for getting a new line
// If no new line found and the remaining data in stream was less than 4 MB then indexAfterNewLine is 0
residualDataSize = finalReadData - indexAfterNewLine;
if (residualDataSize > 0)
{
Buffer.BlockCopy(readBytes, indexAfterNewLine , readBytes, 0, residualDataSize);
}
}
if (!Metadata.IsUpload)
{
writeStream.Seek(_offset, SeekOrigin.Begin);
}
// if we have done readForwardTilNewLine then less data needs to be read now so update the lengthToRead
long lengthToRead = _lengthToRead - (readStream.Position - _offset);
while (lengthToRead > 0)
{
// Since we have data till residualDataSize in buffer we have to read remaining data in buffer
int bufferDataSize = residualDataSize + ReadDataIntoBuffer(readStream, readBytes, residualDataSize, (int)Math.Min(BuffSize - residualDataSize, lengthToRead));
if (bufferDataSize == residualDataSize)
{ // This will never be the case unless the file is being edited because if there was no data it would have been caught by lengthToRead>0
break;
}
int indexAfterlastNewLine = bufferDataSize;
if (Metadata.IsUpload && !Metadata.IsBinary)
{
indexAfterlastNewLine = GetNewLine(readBytes, 0, bufferDataSize, Metadata.EncodeType, true) + 1;
}
// For non binary uploads: indexAfterNewLine will be either the index after new line or 0 if no new line is found and data in the buffer is less than 4 MB
// Rest scenarios: indexAfterNewLine will be buffer data length
if (indexAfterlastNewLine != 0)
{
writeStream.Write(readBytes, 0, indexAfterlastNewLine);
}
else if (bufferDataSize == AdlsOutputStream.BufferMaxCapacity) // No newlines were found in 4MB
{
throw new AdlsException($"No new lines obtained in {AdlsOutputStream.BufferMaxCapacity} of data at offset {readStream.Position - AdlsOutputStream.BufferMaxCapacity} for file {Metadata.SrcFile}. File should be uploaded as binary.");
}
// Length read this turn would be total buffer size minus the residual Data size, update the lengthToRead for next turn
lengthToRead -= bufferDataSize - residualDataSize;
// Compute new residualDataSize: data starting from indexAfterNewLine till total buffer size
residualDataSize = bufferDataSize - indexAfterlastNewLine;
// Move residual data to the start of the array.
if (residualDataSize > 0)
{
Buffer.BlockCopy(readBytes, indexAfterlastNewLine, readBytes, 0, residualDataSize);
}
}
// Only for upload, non-binary and chunked uploads
// Read forward into next chunk till it gets a new line
if (Metadata.IsUpload && !Metadata.IsBinary && ChunkIndex >= 0 && ChunkIndex < Metadata.TotalChunks)
{
int indexAfterNewLine = ReadForwardTillNewLine(readStream, readBytes, residualDataSize);
if (indexAfterNewLine != 0)
{
residualDataSize = indexAfterNewLine;
}
}
// For non binary uploads there can be residual data
if (residualDataSize > 0)
{
writeStream.Write(readBytes, 0, residualDataSize);
}
}