private static BlockingQueue<long[]> queueItemIDsInBatches(DataModel dataModel, int batchSize) {

    longPrimitiveIterator itemIDs = dataModel.getItemIDs();
    int numItems = dataModel.getNumItems();

    BlockingQueue<long[]> itemIDBatches = new LinkedBlockingQueue<long[]>((numItems / batchSize) + 1);

    long[] batch = new long[batchSize];
    int pos = 0;
    while (itemIDs.hasNext()) {
      if (pos == batchSize) {
        itemIDBatches.add(batch.clone());
        pos = 0;
      }
      batch[pos] = itemIDs.nextlong();
      pos++;
    }
    int nonQueuedItemIDs = batchSize - pos;
    if (nonQueuedItemIDs > 0) {
      long[] lastBatch = new long[nonQueuedItemIDs];
      Array.Copy(batch, 0, lastBatch, 0, nonQueuedItemIDs);
      itemIDBatches.add(lastBatch);
    }

    log.info("Queued {} items in {} batches", numItems, itemIDBatches.Count);

    return itemIDBatches;
  }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test(timeout = TEST_RUN_TIME_MS * 20) public void closeTransaction() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void CloseTransaction()
        {
            BlockingQueue <bool>             committerToTerminator = new LinkedBlockingQueue <bool>(1);
            BlockingQueue <TerminatorAction> terminatorToCommitter = new LinkedBlockingQueue <TerminatorAction>(1);

            RunTwoThreads(tx =>
            {
                bool?terminatorShouldAct = committerToTerminator.poll();
                if (terminatorShouldAct != null && terminatorShouldAct)
                {
                    TerminatorAction action = TerminatorAction.random();
                    action.executeOn(tx);
                    assertTrue(terminatorToCommitter.add(action));
                }
            }, tx =>
            {
                tx.initialize();
                CommitterAction committerAction = CommitterAction.random();
                committerAction.executeOn(tx);
                if (committerToTerminator.offer(true))
                {
                    TerminatorAction terminatorAction;
                    try
                    {
                        terminatorAction = terminatorToCommitter.poll(1, TimeUnit.SECONDS);
                    }
                    catch (InterruptedException)
                    {
                        Thread.CurrentThread.Interrupt();
                        return;
                    }
                    if (terminatorAction != null)
                    {
                        Close(tx, committerAction, terminatorAction);
                    }
                }
            });
        }