code: @DoesServiceRequest
      private synchronized void dispatchRead(final int readLength) throws IOException {
          try {
              final byte[] byteBuffer = new byte[readLength];
  
              this.parentFileRef.downloadRangeInternal(this.currentAbsoluteReadPosition, (long) readLength, byteBuffer,
                      0, null /* this.accessCondition */, this.options, this.opContext);
  
              // Check Etag manually for now -- use access condition once conditional headers supported.
              if (this.accessCondition != null) {
                  if (!this.accessCondition.getIfMatch().equals(this.parentFileRef.getProperties().getEtag())) {
                      throw new StorageException(StorageErrorCode.CONDITION_FAILED.toString(),
                              SR.INVALID_CONDITIONAL_HEADERS, HttpURLConnection.HTTP_PRECON_FAILED, null, null);
                  }
              }
  
              this.currentBuffer = new ByteArrayInputStream(byteBuffer);
              this.bufferSize = readLength;
              this.bufferStartOffset = this.currentAbsoluteReadPosition;
          }
          catch (final StorageException e) {
              this.streamFaulted = true;
              this.lastError = Utility.initIOException(e);
              throw this.lastError;
          }
      }
docs: Dispatches a read operation of N bytes.
  
  @param readLength
  An <code>int</code> which represents the number of bytes to read.
  
  @throws IOException
  If an I/O error occurs.