protected void runRefill() {
    boolean completedRound = (current != null && max != null && current > max);
    boolean needGetMinMax = (min == null || completedRound);
    if (needGetMinMax) {
      // get min & max
      fetchAll = false;
      if (startWhenIteration != 0) {
        if (logs.size() > maxLogsCount) {
          logs.remove(0);
        }
        logs.add(new Object[] {startWhenIteration, System.currentTimeMillis()});
      }

      startWhenIteration = System.currentTimeMillis();

      Object[] minMaxBounds = objectFetcher.getMinMaxBounds();
      if (minMaxBounds != null && minMaxBounds.length >= 2) {
        Object minBound = minMaxBounds[0];
        Object maxBound = minMaxBounds[1];
        if (minBound == null || maxBound == null) {
          min = null;
        } else {
          min = ((Number) minBound).longValue();
          max = ((Number) maxBound).longValue();
          if (minMaxBounds.length == 3) {
            Number count = (Number) minMaxBounds[2];
            if (count != null && count.longValue() <= minSize) {
              fetchAll = true;
            }
          }
          current = min;
          if (!fetchAll) {
            // try to autoScale
            try {
              long bulks = Math.abs(max - min) / fetchSize;
              if (maxBulksCount > 1 && bulks > maxBulksCount) {
                // guaranteed to be 1 or more by condition above
                fetchSize = (int) (Math.abs(max - min) / maxBulksCount);
              }
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        }
      }
      if (completedRound && runThroughDataSize <= minSize) {
        // we are in situation, when running through all queue didn't satisfy us.
        // in this case we need some delay, before try to fill it all again.
        runThroughNotFilled = true;
      }
      runThroughDataSize = 0;
    }

    if (!runThroughNotFilled && min != null) {
      try {
        boolean needEnd = false;

        HashMap<Integer, Integer> hashCodes =
            new HashMap<Integer, Integer>((int) (ROUGH_HASH_SIZE * queue.size()));
        Iterator it = queue.iterator();
        while (it.hasNext()) {
          Object queueElement = it.next();
          hashCodes.put(queueElement.hashCode(), queueElement.hashCode());
        }

        int tries = fillTries;
        while (!needEnd && tries-- > 0) {
          Collection collection = null;
          if (fetchAll) {
            // don't forget +1 here
            collection = objectFetcher.getRecordsCollection(min, max - min + 1);
          } else {
            collection = objectFetcher.getRecordsCollection(current, fetchSize);
          }
          if (collection != null && !collection.isEmpty()) {
            for (Iterator iterator = collection.iterator(); iterator.hasNext(); ) {
              Object o = iterator.next();
              try {
                if (o != null && !hashCodes.containsKey(o.hashCode())) {
                  queue.offer(o);
                  runThroughDataSize++;
                  try {
                    hashCodes.put(o.hashCode(), o.hashCode());
                  } catch (Exception e) {
                    e.printStackTrace();
                  }
                }
              } catch (Exception e) {
                e.printStackTrace();
                queue.offer(o);
                runThroughDataSize++;
                try {
                  hashCodes.put(o.hashCode(), o.hashCode());
                } catch (Exception e1) {
                  e1.printStackTrace();
                }
              }
            }
          }
          current += fetchSize;

          needEnd = (queue.size() >= minSize) || current > max;
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
 public String getFetcherDescriptiveName() {
   return objectFetcher.getDescriptiveName();
 }