/**
  * Return a random GlobalAttributeValueId
  *
  * @return
  */
 public GlobalAttributeValueId getRandomGlobalAttributeValue() {
   int offset = rng.nextInt(this.gag_ids.size());
   GlobalAttributeGroupId gag_id = this.gag_ids.get(offset);
   assert (gag_id != null);
   int count = rng.nextInt(gag_id.getCount());
   GlobalAttributeValueId gav_id = new GlobalAttributeValueId(gag_id, count);
   return gav_id;
 }
 public ItemInfo getRandomItem() {
   assert (this.getAllItemsCount() > 0);
   int idx = -1;
   while (idx == -1 || allItemSets[idx].isEmpty()) {
     idx = rng.nextInt(allItemSets.length);
   } // WHILE
   return (this.getRandomItem(allItemSets[idx], false, false));
 }
  /**
   * 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);
  }