OutputBufferChunkSource.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /* Copyright 2013-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. namespace MongoDB.Bson.IO
  17. {
  18. /// <summary>
  19. /// Represents a source of chunks optimized for output buffers.
  20. /// </summary>
  21. public sealed class OutputBufferChunkSource : IBsonChunkSource
  22. {
  23. // constants
  24. const int DefaultInitialUnpooledChunkSize = 1024;
  25. const int DefaultMaxChunkSize = 1 * 1024 * 1024;
  26. const int DefaultMinChunkSize = 16 * 1024;
  27. // fields
  28. private readonly IBsonChunkSource _baseSource;
  29. private bool _disposed;
  30. private int _initialUnpooledChunkSize;
  31. private readonly int _maxChunkSize;
  32. private readonly int _minChunkSize;
  33. private int _previousChunkSize;
  34. // constructors
  35. /// <summary>
  36. /// Initializes a new instance of the <see cref="OutputBufferChunkSource"/> class.
  37. /// </summary>
  38. /// <param name="baseSource">The chunk source.</param>
  39. /// <param name="initialUnpooledChunkSize">The size of the initial unpooled chunk.</param>
  40. /// <param name="minChunkSize">The minimum size of a chunk.</param>
  41. /// <param name="maxChunkSize">The maximum size of a chunk.</param>
  42. public OutputBufferChunkSource(
  43. IBsonChunkSource baseSource,
  44. int initialUnpooledChunkSize = DefaultInitialUnpooledChunkSize,
  45. int minChunkSize = DefaultMinChunkSize,
  46. int maxChunkSize = DefaultMaxChunkSize)
  47. {
  48. if (baseSource == null)
  49. {
  50. throw new ArgumentNullException("baseSource");
  51. }
  52. if (initialUnpooledChunkSize < 0)
  53. {
  54. throw new ArgumentOutOfRangeException("initialUnpooledChunkSize");
  55. }
  56. if (minChunkSize <= 0)
  57. {
  58. throw new ArgumentOutOfRangeException("minChunkSize");
  59. }
  60. if (maxChunkSize <= 0)
  61. {
  62. throw new ArgumentOutOfRangeException("maxChunkSize");
  63. }
  64. if (!PowerOf2.IsPowerOf2(minChunkSize))
  65. {
  66. throw new ArgumentException("minChunkSize is not a power of 2.", "minChunkSize");
  67. }
  68. if (!PowerOf2.IsPowerOf2(maxChunkSize))
  69. {
  70. throw new ArgumentException("maxChunkSize is not a power of 2.", "maxChunkSize");
  71. }
  72. if (maxChunkSize < minChunkSize)
  73. {
  74. throw new ArgumentException("maxChunkSize is less than minChunkSize", "maxChunkSize");
  75. }
  76. _baseSource = baseSource;
  77. _initialUnpooledChunkSize = initialUnpooledChunkSize;
  78. _minChunkSize = minChunkSize;
  79. _maxChunkSize = maxChunkSize;
  80. }
  81. // properties
  82. /// <summary>
  83. /// Gets the base source.
  84. /// </summary>
  85. /// <value>
  86. /// The base source.
  87. /// </value>
  88. public IBsonChunkSource BaseSource
  89. {
  90. get
  91. {
  92. ThrowIfDisposed();
  93. return _baseSource;
  94. }
  95. }
  96. /// <summary>
  97. /// Gets the initial unpooled chunk size.
  98. /// </summary>
  99. /// <value>
  100. /// The initial unpooled chunk size.
  101. /// </value>
  102. public int InitialUnpooledChunkSize
  103. {
  104. get { return _initialUnpooledChunkSize; }
  105. }
  106. /// <summary>
  107. /// Gets the maximum size of a chunk.
  108. /// </summary>
  109. /// <value>
  110. /// The maximum size of a chunk.
  111. /// </value>
  112. public int MaxChunkSize
  113. {
  114. get { return _maxChunkSize; }
  115. }
  116. /// <summary>
  117. /// Gets the minimum size of a chunk.
  118. /// </summary>
  119. /// <value>
  120. /// The minimum size of a chunk.
  121. /// </value>
  122. public int MinChunkSize
  123. {
  124. get { return _minChunkSize; }
  125. }
  126. // methods
  127. /// <inheritdoc/>
  128. public void Dispose()
  129. {
  130. _disposed = true;
  131. }
  132. /// <inheritdoc/>
  133. public IBsonChunk GetChunk(int requestedSize)
  134. {
  135. if (requestedSize <= 0)
  136. {
  137. throw new ArgumentOutOfRangeException("requestedSize");
  138. }
  139. ThrowIfDisposed();
  140. IBsonChunk chunk;
  141. if (_previousChunkSize == 0 && _initialUnpooledChunkSize != 0)
  142. {
  143. chunk = new ByteArrayChunk(_initialUnpooledChunkSize);
  144. }
  145. else
  146. {
  147. var powerOf2Size = PowerOf2.RoundUpToPowerOf2(_previousChunkSize + 1);
  148. var chunkSize = Math.Max(Math.Min(powerOf2Size, _maxChunkSize), _minChunkSize);
  149. chunk = _baseSource.GetChunk(chunkSize);
  150. }
  151. _previousChunkSize = chunk.Bytes.Count;
  152. return chunk;
  153. }
  154. private void ThrowIfDisposed()
  155. {
  156. if (_disposed)
  157. {
  158. throw new ObjectDisposedException(GetType().Name);
  159. }
  160. }
  161. }
  162. }