Program: 6451
Project: 6451
Buggy source:
/** 
 * This forces an immediate update of the config cache. It should only be called from the refresh thread or from tests, to avoid having to add a sleep for the duration of the refresh interval. This method is synchronized to protect from race conditions if called directly from a test. Otherwise this is only called from the refresh thread, and there will not be concurrent invocations.
 * @throws IOException if failed to update config cache
 */
@VisibleForTesting public synchronized void updateCache() throws IOException {
  Map<byte[],QueueConsumerConfig> newCache=Maps.newTreeMap(Bytes.BYTES_COMPARATOR);
  long now=System.currentTimeMillis();
  TransactionSnapshot txSnapshot=transactionSnapshotSupplier.get();
  if (txSnapshot == null) {
    LOG.debug("String_Node_Str");
    return;
  }
  HTableInterface table=hTableSupplier.getInput();
  try {
    Scan scan=new Scan();
    scan.addFamily(QueueEntryRow.COLUMN_FAMILY);
    Transaction tx=TxUtils.createDummyTransaction(txSnapshot);
    setScanAttribute(scan,TxConstants.TX_OPERATION_ATTRIBUTE_KEY,txCodec.encode(tx));
    ResultScanner scanner=table.getScanner(scan);
    int configCnt=0;
    for (    Result result : scanner) {
      if (!result.isEmpty()) {
        NavigableMap<byte[],byte[]> familyMap=result.getFamilyMap(QueueEntryRow.COLUMN_FAMILY);
        if (familyMap != null) {
          configCnt++;
          Map<ConsumerInstance,byte[]> consumerInstances=new HashMap<>();
          int numGroups=0;
          Long groupId=null;
          for (          Map.Entry<byte[],byte[]> entry : familyMap.entrySet()) {
            if (entry.getKey().length != STATE_COLUMN_SIZE) {
              continue;
            }
            long gid=Bytes.toLong(entry.getKey());
            int instanceId=Bytes.toInt(entry.getKey(),Bytes.SIZEOF_LONG);
            consumerInstances.put(new ConsumerInstance(gid,instanceId),entry.getValue());
            if (groupId == null || groupId != gid) {
              numGroups++;
              groupId=gid;
            }
          }
          byte[] queueName=result.getRow();
          newCache.put(queueName,new QueueConsumerConfig(consumerInstances,numGroups));
        }
      }
    }
    long elapsed=System.currentTimeMillis() - now;
    this.configCache=newCache;
    this.lastUpdated=now;
    if (LOG.isDebugEnabled()) {
      LOG.debug("String_Node_Str",configCnt,elapsed);
    }
  }
  finally {
    try {
      table.close();
    }
 catch (    IOException ioe) {
      LOG.error("String_Node_Str",queueConfigTableName,ioe);
    }
  }
}

Fixed version (ground truth):
/** 
 * This forces an immediate update of the config cache. It should only be called from the refresh thread or from tests, to avoid having to add a sleep for the duration of the refresh interval. This method is synchronized to protect from race conditions if called directly from a test. Otherwise this is only called from the refresh thread, and there will not be concurrent invocations.
 * @throws IOException if failed to update config cache
 */
@VisibleForTesting public synchronized void updateCache() throws IOException {
  Map<byte[],QueueConsumerConfig> newCache=Maps.newTreeMap(Bytes.BYTES_COMPARATOR);
  long now=System.currentTimeMillis();
  TransactionVisibilityState txSnapshot=transactionSnapshotSupplier.get();
  if (txSnapshot == null) {
    LOG.debug("String_Node_Str");
    return;
  }
  HTableInterface table=hTableSupplier.getInput();
  try {
    Scan scan=new Scan();
    scan.addFamily(QueueEntryRow.COLUMN_FAMILY);
    Transaction tx=TxUtils.createDummyTransaction(txSnapshot);
    setScanAttribute(scan,TxConstants.TX_OPERATION_ATTRIBUTE_KEY,txCodec.encode(tx));
    ResultScanner scanner=table.getScanner(scan);
    int configCnt=0;
    for (    Result result : scanner) {
      if (!result.isEmpty()) {
        NavigableMap<byte[],byte[]> familyMap=result.getFamilyMap(QueueEntryRow.COLUMN_FAMILY);
        if (familyMap != null) {
          configCnt++;
          Map<ConsumerInstance,byte[]> consumerInstances=new HashMap<>();
          int numGroups=0;
          Long groupId=null;
          for (          Map.Entry<byte[],byte[]> entry : familyMap.entrySet()) {
            if (entry.getKey().length != STATE_COLUMN_SIZE) {
              continue;
            }
            long gid=Bytes.toLong(entry.getKey());
            int instanceId=Bytes.toInt(entry.getKey(),Bytes.SIZEOF_LONG);
            consumerInstances.put(new ConsumerInstance(gid,instanceId),entry.getValue());
            if (groupId == null || groupId != gid) {
              numGroups++;
              groupId=gid;
            }
          }
          byte[] queueName=result.getRow();
          newCache.put(queueName,new QueueConsumerConfig(consumerInstances,numGroups));
        }
      }
    }
    long elapsed=System.currentTimeMillis() - now;
    this.configCache=newCache;
    this.lastUpdated=now;
    if (LOG.isDebugEnabled()) {
      LOG.debug("String_Node_Str",configCnt,elapsed);
    }
  }
  finally {
    try {
      table.close();
    }
 catch (    IOException ioe) {
      LOG.error("String_Node_Str",queueConfigTableName,ioe);
    }
  }
}