GridFSDownloadStreamBase.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* Copyright 2015-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. using System.IO;
  17. using System.Threading;
  18. using System.Threading.Tasks;
  19. using MongoDB.Driver.Core.Bindings;
  20. namespace MongoDB.Driver.GridFS
  21. {
  22. internal abstract class GridFSDownloadStreamBase<TFileId> : GridFSDownloadStream<TFileId>
  23. {
  24. // private fields
  25. private readonly IReadBinding _binding;
  26. private readonly IGridFSBucket<TFileId> _bucket;
  27. private bool _closed;
  28. private bool _disposed;
  29. private readonly GridFSFileInfo<TFileId> _fileInfo;
  30. // constructors
  31. protected GridFSDownloadStreamBase(
  32. IGridFSBucket<TFileId> bucket,
  33. IReadBinding binding,
  34. GridFSFileInfo<TFileId> fileInfo)
  35. {
  36. _bucket = bucket;
  37. _binding = binding;
  38. _fileInfo = fileInfo;
  39. }
  40. // public properties
  41. public override bool CanRead
  42. {
  43. get { return true; }
  44. }
  45. public override bool CanWrite
  46. {
  47. get { return false; }
  48. }
  49. public override GridFSFileInfo<TFileId> FileInfo
  50. {
  51. get { return _fileInfo; }
  52. }
  53. public override long Length
  54. {
  55. get { return _fileInfo.Length; }
  56. }
  57. // protected properties
  58. protected IReadBinding Binding
  59. {
  60. get { return _binding; }
  61. }
  62. protected IGridFSBucket<TFileId> Bucket
  63. {
  64. get { return _bucket; }
  65. }
  66. // public methods
  67. public override void Close(CancellationToken cancellationToken)
  68. {
  69. try
  70. {
  71. CloseIfNotAlreadyClosed(cancellationToken);
  72. }
  73. finally
  74. {
  75. Dispose();
  76. }
  77. }
  78. public override async Task CloseAsync(CancellationToken cancellationToken = default(CancellationToken))
  79. {
  80. try
  81. {
  82. await CloseIfNotAlreadyClosedAsync(cancellationToken).ConfigureAwait(false);
  83. }
  84. finally
  85. {
  86. Dispose();
  87. }
  88. }
  89. public override void Flush()
  90. {
  91. throw new NotSupportedException();
  92. }
  93. public override Task FlushAsync(CancellationToken cancellationToken)
  94. {
  95. throw new NotSupportedException();
  96. }
  97. public override void SetLength(long value)
  98. {
  99. throw new NotSupportedException();
  100. }
  101. public override void Write(byte[] buffer, int offset, int count)
  102. {
  103. throw new NotSupportedException();
  104. }
  105. public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  106. {
  107. throw new NotSupportedException();
  108. }
  109. // protected methods
  110. protected void CloseIfNotAlreadyClosedFromDispose(bool disposing)
  111. {
  112. if (disposing)
  113. {
  114. try
  115. {
  116. CloseIfNotAlreadyClosed(CancellationToken.None);
  117. }
  118. catch
  119. {
  120. // ignore exceptions when calling CloseIfNotAlreadyClosed from Dispose
  121. }
  122. }
  123. }
  124. protected virtual void CloseImplementation(CancellationToken cancellationToken)
  125. {
  126. // override in subclass if there is anything to do
  127. }
  128. protected virtual Task CloseImplementationAsync(CancellationToken cancellationToken)
  129. {
  130. // override in subclass if there is anything to do
  131. CloseImplementation(cancellationToken);
  132. return Task.FromResult(true);
  133. }
  134. protected override void Dispose(bool disposing)
  135. {
  136. CloseIfNotAlreadyClosedFromDispose(disposing);
  137. if (!_disposed)
  138. {
  139. if (disposing)
  140. {
  141. _binding.Dispose();
  142. }
  143. _disposed = true;
  144. }
  145. base.Dispose(disposing);
  146. }
  147. protected virtual void ThrowIfDisposed()
  148. {
  149. if (_disposed)
  150. {
  151. throw new ObjectDisposedException(GetType().Name);
  152. }
  153. }
  154. // private methods
  155. private void CloseIfNotAlreadyClosed(CancellationToken cancellationToken)
  156. {
  157. if (!_closed)
  158. {
  159. try
  160. {
  161. CloseImplementation(cancellationToken);
  162. }
  163. finally
  164. {
  165. _closed = true;
  166. }
  167. }
  168. }
  169. private async Task CloseIfNotAlreadyClosedAsync(CancellationToken cancellationToken)
  170. {
  171. if (!_closed)
  172. {
  173. try
  174. {
  175. await CloseImplementationAsync(cancellationToken).ConfigureAwait(false);
  176. }
  177. finally
  178. {
  179. _closed = true;
  180. }
  181. }
  182. }
  183. }
  184. }