@Override
    public void run() {
      while (true) {
        int blinkIdx = blinkBuffer.getCount();
        if (blinkIdx == -1) break;

        BlinkEntry be = blinkBuffer.bs.get(blinkIdx);
        GBlink b = new GBlink(new MapWord(be.get_mapCode()));
        b.setColor((int) be.get_colors());
        QI qi = b.optimizedQuantumInvariant(3, 8);
        blinkBuffer.qis[blinkIdx] = qi;
      }
    }
  public static void main(String[] args)
      throws FileNotFoundException, IOException, SQLException, ClassNotFoundException {
    // Args: Limit / numThreads / numedges / qiIDPrefix
    int numThreads = 16;
    if (args.length >= 2) {
      numThreads = Integer.parseInt(args[1]);
    }
    BlinkBuffer blinkBuffer = new BlinkBuffer();
    QICalculator[] threads = new QICalculator[numThreads];

    int numedges = 0;
    if (args.length >= 3) {
      numedges = Integer.parseInt(args[2]);
    }

    long qiIDPrefix = 0;
    if (args.length >= 4) {
      qiIDPrefix = Integer.parseInt(args[3]);
    }

    BlinkDB db = (BlinkDB) App.getRepositorio();
    long t0 = System.currentTimeMillis();

    QIRepository R = new QIRepository();

    // fill in QIRepository
    ArrayList<QI> qis = App.getRepositorio().getQIs();
    for (QI q : qis) R.add(q);

    HashMap<BlinkEntry, QI> _map = new HashMap<BlinkEntry, QI>();
    int limit = Integer.parseInt(args[0]);
    long blinkIDs[] = db.getBlinkIDsWithoutQI(limit, numedges);
    System.out.println("Found " + blinkIDs.length + " blinks without QI");
    int delta = 100;
    int count = 1;
    int acum = 0;
    for (int k = 0; k < blinkIDs.length; k += delta) {

      long t = System.currentTimeMillis();
      long[] curIDs = Arrays.copyOfRange(blinkIDs, k, Math.min(k + delta, blinkIDs.length));
      System.out.print("Calc for ");
      for (long x : curIDs) {
        System.out.print(" " + x);
      }
      System.out.println("");
      ArrayList<BlinkEntry> bs = db.getBlinksByIDsArray(curIDs);

      t = System.currentTimeMillis();

      blinkBuffer.reset(bs);
      for (int i = 0; i < numThreads; ++i) {
        threads[i] = new QICalculator(blinkBuffer);
        threads[i].start();
      }
      try {
        for (int i = 0; i < numThreads; ++i) {
          threads[i].join();
        }
      } catch (InterruptedException e) {
        System.out.println("Problem!");
      }

      System.out.println(String.format(" %.2f sec.", (System.currentTimeMillis() - t) / 1000.0));
      for (int i = 0; i < bs.size(); ++i) {
        BlinkEntry be = bs.get(i);

        QI qi = blinkBuffer.qis[i];

        // add to repository
        QI qiRep = R.add(qi);
        if (qiRep == null) qiRep = qi;

        //
        _map.put(be, qiRep);
      }

      //
      ArrayList<QI> list = R.getList(); // get list of not persistent QIs
      // t = System.currentTimeMillis();

      db.insertQIs(list, qiIDPrefix);
      acum = acum + list.size();
      System.out.println(
          String.format(
              "Inserted %6d new QIs total QIs %6d in %.2f sec.",
              list.size(), acum, (System.currentTimeMillis() - t0) / 1000.0));

      // updating biEntry
      for (BlinkEntry be : bs) {
        QI qi = _map.get(be);
        be.set_qi(qi.get_id());
      }

      // update qis
      t = System.currentTimeMillis();
      db.updateBlinksQI(bs);
      // System.out.println(String.format("Updated QIs %d blinks in %.2f sec.", bs.size(),
      // (System.currentTimeMillis() - t) / 1000.0));

      // update index
      System.out.println(
          "Calculated " + (k + curIDs.length) + " of " + blinkIDs.length + " blinks QI");
    }

    System.out.println(
        String.format(
            "Total Time to calculate QIs %.2f sec.", (System.currentTimeMillis() - t0) / 1000.0));
    System.exit(0);
  }