/**
   * Note that this synchronization block only matters for the loader
   *
   * @param min_item_count
   * @param clientId - Will use null if less than zero
   * @param exclude
   * @return
   */
  private synchronized UserId getRandomUserId(int min_item_count, int clientId, UserId... exclude) {
    // We use the UserIdGenerator to ensure that we always select the next UserId for
    // a given client from the same set of UserIds
    if (this.randomItemCount == null) {
      this.randomItemCount = new FlatHistogram<Long>(this.rng, this.users_per_itemCount);
    }
    if (this.userIdGenerator == null) this.initializeUserIdGenerator(clientId);

    UserId user_id = null;
    int tries = 1000;
    final long num_users = this.userIdGenerator.getTotalUsers() - 1;
    while (user_id == null && tries-- > 0) {
      // We first need to figure out how many items our seller needs to have
      long itemCount = -1;
      // assert(min_item_count < this.users_per_item_count.getMaxValue());
      while (itemCount < min_item_count) {
        itemCount = this.randomItemCount.nextValue();
      } // WHILE

      // Set the current item count and then choose a random position
      // between where the generator is currently at and where it ends
      this.userIdGenerator.setCurrentItemCount((int) itemCount);
      long cur_position = this.userIdGenerator.getCurrentPosition();
      long new_position = rng.number(cur_position, num_users);
      user_id = this.userIdGenerator.seekToPosition((int) new_position);
      if (user_id == null) continue;

      // Make sure that we didn't select the same UserId as the one we were
      // told to exclude.
      if (exclude != null && exclude.length > 0) {
        for (UserId ex : exclude) {
          if (ex != null && ex.equals(user_id)) {
            if (LOG.isTraceEnabled()) LOG.trace("Excluding " + user_id);
            user_id = null;
            break;
          }
        } // FOR
        if (user_id == null) continue;
      }

      // If we don't care about skew, then we're done right here
      if (LOG.isTraceEnabled()) LOG.trace("Selected " + user_id);
      break;
    } // WHILE
    if (user_id == null && LOG.isDebugEnabled()) {
      LOG.warn(
          String.format(
              "Failed to select a random UserId "
                  + "[minItemCount=%d, clientId=%d, exclude=%s, totalPossible=%d, currentPosition=%d]",
              min_item_count,
              clientId,
              Arrays.toString(exclude),
              this.userIdGenerator.getTotalUsers(),
              this.userIdGenerator.getCurrentPosition()));
    }
    return (user_id);
  }
 public ItemId getNextItemId(UserId seller_id) {
   Integer cnt = this.seller_item_cnt.get(seller_id);
   if (cnt == null || cnt == 0) {
     cnt = seller_id.getItemCount();
     this.seller_item_cnt.put(seller_id, cnt);
   }
   this.seller_item_cnt.put(seller_id);
   return (new ItemId(seller_id, cnt.intValue()));
 }
  private AuctionMarkProfile copyProfile(AuctionMarkWorker worker, AuctionMarkProfile other) {
    this.client_id = worker.getId();
    this.scale_factor = other.scale_factor;
    this.loaderStartTime = other.loaderStartTime;
    this.loaderStopTime = other.loaderStopTime;
    this.users_per_itemCount = other.users_per_itemCount;
    this.items_per_category = other.items_per_category;
    this.gag_ids = other.gag_ids;

    // Initialize the UserIdGenerator so we can figure out whether our
    // client should even have these ids
    this.initializeUserIdGenerator(this.client_id);
    assert (this.userIdGenerator != null);

    for (int i = 0; i < this.allItemSets.length; i++) {
      LinkedList<ItemInfo> list = this.allItemSets[i];
      assert (list != null);
      LinkedList<ItemInfo> origList = other.allItemSets[i];
      assert (origList != null);

      for (ItemInfo itemInfo : origList) {
        UserId sellerId = itemInfo.getSellerId();
        if (this.userIdGenerator.checkClient(sellerId)) {
          this.seller_item_cnt.set(sellerId, sellerId.getItemCount());
          list.add(itemInfo);
        }
      } // FOR
      Collections.shuffle(list);
    } // FOR

    for (ItemCommentResponse cr : other.pending_commentResponses) {
      UserId sellerId = new UserId(cr.sellerId);
      if (this.userIdGenerator.checkClient(sellerId)) {
        this.pending_commentResponses.add(cr);
      }
    } // FOR

    if (LOG.isTraceEnabled()) LOG.trace("SellerItemCounts:\n" + this.seller_item_cnt);

    return (this);
  }