grib/src/main/java/ucar/nc2/grib/grib2/Grib2Index.java
public boolean makeIndex(String filename, RandomAccessFile dataRaf) throws IOException {
    String idxPath = filename;
    if (!idxPath.endsWith(GBX9_IDX)) idxPath += GBX9_IDX;
    File idxFile = GribIndexCache.getFileOrCache(idxPath);
    File idxFileTmp = GribIndexCache.getFileOrCache(idxPath + ".tmp");

    boolean ok = false;
    RandomAccessFile raf = null;

    try (FileOutputStream fout = new FileOutputStream(idxFileTmp)) {
      //// header message
      fout.write(MAGIC_START.getBytes(CDM.utf8Charset));
      NcStream.writeVInt(fout, version);

      Map<Long, Integer> gdsMap = new HashMap<>();
      gdsList = new ArrayList<>();
      records = new ArrayList<>(200);

      Grib2IndexProto.Grib2Index.Builder rootBuilder = Grib2IndexProto.Grib2Index.newBuilder();
      rootBuilder.setFilename(filename);

      if (dataRaf == null)  {
        raf = RandomAccessFile.acquire(filename);
        dataRaf = raf;
      }

      Grib2RecordScanner scan = new Grib2RecordScanner(dataRaf);
      while (scan.hasNext()) {
        Grib2Record r = scan.next();
        if (r == null) break; // done
        records.add(r);

        Grib2SectionGridDefinition gdss = r.getGDSsection();
        Integer index = gdsMap.get(gdss.calcCRC());
        if (index == null) {
          gdsList.add(gdss);
          index = gdsList.size()-1;
          gdsMap.put(gdss.calcCRC(), index);
          rootBuilder.addGdsList(makeGdsProto(gdss));
        }
        rootBuilder.addRecords(makeRecordProto(r, index, r.getGDS().scanMode));
      }

      if (records.isEmpty())
        throw new RuntimeException("No GRIB2 records found in "+dataRaf.getLocation());

      Grib2IndexProto.Grib2Index index = rootBuilder.build();
      byte[] b = index.toByteArray();
      NcStream.writeVInt(fout, b.length); // message size
      fout.write(b);  // message  - all in one gulp
      logger.debug("  made gbx9 index for {} size={}", filename, b.length);

      ok = true;
      return true;

    } finally {
      if (raf != null) raf.close(); // only close if we opened it

      // now switch; fout has been closed
      if (ok) {
        RandomAccessFile.eject(idxFile.getPath());
        boolean deleteOk = !idxFile.exists() || idxFile.delete();
        boolean renameOk = idxFileTmp.renameTo(idxFile);
        if (!deleteOk)
          logger.error("  could not delete Grib2Index= {}", idxFile.getPath());
        if (!renameOk)
          logger.error("  could not rename Grib2Index= {}", idxFile.getPath());
      }
    }
  }
public boolean makeIndex(String filename, RandomAccessFile dataRaf) throws IOException {
    String idxPath = filename;
    if (!idxPath.endsWith(GBX9_IDX)) idxPath += GBX9_IDX;
    File idxFile = GribIndexCache.getFileOrCache(idxPath);
    File idxFileTmp = GribIndexCache.getFileOrCache(idxPath + ".tmp");

    boolean ok = false;
    RandomAccessFile raf = null;

    try (FileOutputStream fout = new FileOutputStream(idxFileTmp)) {
      //// header message
      fout.write(MAGIC_START.getBytes(CDM.utf8Charset));
      NcStream.writeVInt(fout, version);

      Map<Long, Integer> gdsMap = new HashMap<>();
      gdsList = new ArrayList<>();
      records = new ArrayList<>(200);

      Grib2IndexProto.Grib2Index.Builder rootBuilder = Grib2IndexProto.Grib2Index.newBuilder();
      rootBuilder.setFilename(filename);

      if (dataRaf == null)  {
        raf = RandomAccessFile.acquire(filename);
        dataRaf = raf;
      }

      Grib2RecordScanner scan = new Grib2RecordScanner(dataRaf);
      while (scan.hasNext()) {
        Grib2Record r = scan.next();
        if (r == null) break; // done
        records.add(r);

        Grib2SectionGridDefinition gdss = r.getGDSsection();
        Integer index = gdsMap.get(gdss.calcCRC());
        if (index == null) {
          gdsList.add(gdss);
          index = gdsList.size()-1;
          gdsMap.put(gdss.calcCRC(), index);
          rootBuilder.addGdsList(makeGdsProto(gdss));
        }
        rootBuilder.addRecords(makeRecordProto(r, index, r.getGDS().scanMode));
      }

      if (records.isEmpty())
        throw new RuntimeException("No GRIB2 records found in "+dataRaf.getLocation());

      Grib2IndexProto.Grib2Index index = rootBuilder.build();
      byte[] b = index.toByteArray();
      NcStream.writeVInt(fout, b.length); // message size
      fout.write(b);  // message  - all in one gulp
      logger.debug("  made gbx9 index for {} size={}", filename, b.length);

      ok = true;
      return true;

    } finally {
      if (raf != null) raf.close(); // only close if we opened it

      // now switch; fout has been closed
      if (ok) {
        RandomAccessFile.eject(idxFile.getPath());
        boolean deleteOk = !idxFile.exists() || idxFile.delete();
        boolean renameOk = idxFileTmp.renameTo(idxFile);
        if (!deleteOk)
          logger.error("  could not delete Grib2Index= {}", idxFile.getPath());
        if (!renameOk)
          logger.error("  could not rename Grib2Index= {}", idxFile.getPath());
      }
    }
  }
public boolean makeIndex ( String filename , RandomAccessFile dataRaf ) throws IOException { String idxPath = filename ; if ( ! idxPath . endsWith ( GBX9_IDX ) ) idxPath += GBX9_IDX ; File idxFile = GribIndexCache . getFileOrCache ( idxPath ) ; File idxFileTmp = GribIndexCache . getFileOrCache ( idxPath + ".tmp" ) ; boolean ok = false ; RandomAccessFile raf = null ; try ( FileOutputStream fout = new FileOutputStream ( idxFileTmp ) ) { //// header message
 fout . write ( MAGIC_START . getBytes ( CDM . utf8Charset ) ) ; NcStream . writeVInt ( fout , version ) ; Map < Long , Integer > gdsMap = new HashMap <> ( ) ; gdsList = new ArrayList <> ( ) ; records = new ArrayList <> ( 200 ) ; Grib2IndexProto . Grib2Index . Builder rootBuilder = Grib2IndexProto . Grib2Index . newBuilder ( ) ; rootBuilder . setFilename ( filename ) ; if ( dataRaf == null ) { raf = RandomAccessFile . acquire ( filename ) ; dataRaf = raf ; } Grib2RecordScanner scan = new Grib2RecordScanner ( dataRaf ) ; while ( scan . hasNext ( ) ) { Grib2Record r = scan . next ( ) ; if ( r == null ) break ; // done
 records . add ( r ) ; Grib2SectionGridDefinition gdss = r . getGDSsection ( ) ; Integer index = gdsMap . get ( gdss . calcCRC ( ) ) ; if ( index == null ) { gdsList . add ( gdss ) ; index = gdsList . size ( ) - 1 ; gdsMap . put ( gdss . calcCRC ( ) , index ) ; rootBuilder . addGdsList ( makeGdsProto ( gdss ) ) ; } rootBuilder . addRecords ( makeRecordProto ( r , index , r . getGDS ( ) . scanMode ) ) ; } if ( records . isEmpty ( ) ) throw new RuntimeException ( "No GRIB2 records found in " + dataRaf . getLocation ( ) ) ; Grib2IndexProto . Grib2Index index = rootBuilder . build ( ) ; byte [ ] b = index . toByteArray ( ) ; NcStream . writeVInt ( fout , b . length ) ; // message size
 fout . write ( b ) ; // message  - all in one gulp
 logger . debug ( "  made gbx9 index for {} size={}" , filename , b . length ) ; ok = true ; return true ; } finally { if ( raf != null ) raf . close ( ) ; // only close if we opened it
 // now switch; fout has been closed
 if ( ok ) { RandomAccessFile . eject ( idxFile . getPath ( ) ) ; boolean deleteOk = ! idxFile . exists ( ) || idxFile . delete ( ) ; boolean renameOk = idxFileTmp . renameTo ( idxFile ) ; if ( ! deleteOk ) logger . error ( "  could not delete Grib2Index= {}" , idxFile . getPath ( ) ) ; if ( ! renameOk ) logger . error ( "  could not rename Grib2Index= {}" , idxFile . getPath ( ) ) ; } } }
LOOK what about extending an index ??
LOOK what about extending an index ??