protected synchronized InputStream readFileDataBlockInputStream(int blockID) throws IOException {
        if(blockID < 0) {
            throw new IllegalArgumentException("blockID must be positive");
        }
        
        // read from local if available
        if(this.localFileSystem && this.localCachedBlocks != null) {
            // check the cached file block is present
            File cachedBlockFile = this.localCachedBlocks.get(UnsignedLong.asUnsigned(blockID));
            if(cachedBlockFile != null) {
                // has cache
                if(cachedBlockFile.exists()) {
                    LOG.info("read from local cache file");
                    return new FileInputStream(cachedBlockFile);
                }
            }
        }
        
        // otherwise
        SyndicateUGHttpClient client = this.filesystem.getUGRestClient();
        Future<ClientResponse> readFuture = client.read(this.status.getPath().getPath(), this.fileDescriptor, BlockUtils.getBlockStartOffset(blockID, this.blockSize), (int) this.blockSize);
        if(readFuture != null) {
            InputStream readIS;
            try {
                readIS = client.processRead(readFuture);
            } catch (Exception ex) {
                LOG.error("exception occurred", ex);
                throw new IOException(ex);
            }
            
            if(readIS == null) {
                LOG.error("failed to read file - " + this.status.getPath().getPath());
                throw new IOException("failed to read file - " + this.status.getPath().getPath());
            }
            
            return readIS;
        } else {
            throw new IOException("Can not create a REST client");
        }
    }