// First grab the UserIdGenerator for the client (or -1 if there is no client)
// and seek to that itemCount. We use the UserIdGenerator to ensure that we always
// select the next UserId for a given client from the same set of UserIds
Integer client_idx = (client == null ? -1 : client);
UserIdGenerator gen = this.userIdGenerators.get(client_idx);
if (gen == null) {
synchronized (this.userIdGenerators) {
gen = this.userIdGenerators.get(client);
if (gen == null) {
gen = new UserIdGenerator(this.users_per_item_count, this.num_clients, client);
this.userIdGenerators.put(client_idx, gen);
}
} // SYNCH
}
UserId user_id = null;
int tries = 1000;
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
synchronized (gen) {
gen.setCurrentItemCount(itemCount);
long position = rng.number(gen.getCurrentPosition(), gen.getTotalUsers());
user_id = gen.seekToPosition(position);
} // SYNCH
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 (trace.val) 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 (skew == false || this.window_size == null) {
if (trace.val) LOG.trace("Selected " + user_id);
break;
}
// Otherwise, check whether this seller maps to our current window
Integer partition = this.getPartition(user_id);
if (this.window_partitions.contains(partition)) {
this.window_histogram.put(partition);
break;
}
if (trace.val) LOG.trace("Skipping " + user_id);
user_id = null;
} // WHILE
assert(user_id != null) : String.format("Failed to select a random UserId " +
"[min_item_count=%d, client=%d, skew=%s, exclude=%s, totalPossible=%d, currentPosition=%d]",
min_item_count, client, skew, Arrays.toString(exclude),
gen.getTotalUsers(), gen.getCurrentPosition());
return (user_id);
}