code: func OpenBlock(logger log.Logger, dir string, pool chunkenc.Pool) (pb *Block, err error) {
  	if logger == nil {
  		logger = log.NewNopLogger()
  	}
  	var closers []io.Closer
  	defer func() {
  		if err != nil {
  			var merr tsdb_errors.MultiError
  			merr.Add(err)
  			merr.Add(closeAll(closers))
  			err = merr.Err()
  		}
  	}()
  	meta, err := readMetaFile(dir)
  	if err != nil {
  		return nil, err
  	}
  
  	cr, err := chunks.NewDirReader(chunkDir(dir), pool)
  	if err != nil {
  		return nil, err
  	}
  	closers = append(closers, cr)
  
  	ir, err := index.NewFileReader(filepath.Join(dir, indexFilename))
  	if err != nil {
  		return nil, err
  	}
  	closers = append(closers, ir)
  
  	tr, tsr, err := readTombstones(dir)
  	if err != nil {
  		return nil, err
  	}
  	closers = append(closers, tr)
  
  	// TODO refactor to set this at block creation time as
  	// that would be the logical place for a block size to be calculated.
  	bs := blockSize(cr, ir, tsr)
  	meta.Stats.NumBytes = bs
  	err = writeMetaFile(logger, dir, meta)
  	if err != nil {
  		level.Warn(logger).Log("msg", "couldn't write the meta file for the block size", "block", dir, "err", err)
  	}
  
  	pb = &Block{
  		dir:             dir,
  		meta:            *meta,
  		chunkr:          cr,
  		indexr:          ir,
  		tombstones:      tr,
  		symbolTableSize: ir.SymbolTableSize(),
  		logger:          logger,
  	}
  	return pb, nil
  }
docs: // OpenBlock opens the block in the directory. It can be passed a chunk pool, which is used
  // to instantiate chunk structs.