package com.hwlcn.ldap.ldap.sdk; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; import com.hwlcn.core.annotation.NotMutable; import com.hwlcn.core.annotation.ThreadSafety; import com.hwlcn.ldap.util.ThreadSafetyLevel; @NotMutable() @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) final class SRVRecordPrioritySet implements Serializable { private static final Random SEED_RANDOM = new Random(); private static final ThreadLocal<Random> RANDOMS = new ThreadLocal<Random>(); private static final long serialVersionUID = -7722028520625558942L; private final long priority; private final long totalWeight; private final List<SRVRecord> allRecords; private final List<SRVRecord> nonzeroWeightRecords; private final List<SRVRecord> zeroWeightRecords; SRVRecordPrioritySet(final long priority, final List<SRVRecord> records) { this.priority = priority; long w = 0L; final ArrayList<SRVRecord> nRecords = new ArrayList<SRVRecord>(records.size()); final ArrayList<SRVRecord> zRecords = new ArrayList<SRVRecord>(records.size()); for (final SRVRecord r : records) { if (r.getWeight() == 0L) { zRecords.add(r); } else { nRecords.add(r); w += r.getWeight(); } } totalWeight = w; allRecords = Collections.unmodifiableList(records); nonzeroWeightRecords = Collections.unmodifiableList(nRecords); zeroWeightRecords = Collections.unmodifiableList(zRecords); } long getPriority() { return priority; } List<SRVRecord> getOrderedRecords() { final ArrayList<SRVRecord> records = new ArrayList<SRVRecord>(allRecords.size()); if (! nonzeroWeightRecords.isEmpty()) { if (nonzeroWeightRecords.size() == 1) { records.addAll(nonzeroWeightRecords); } else { Random r = RANDOMS.get(); if (r == null) { synchronized (SEED_RANDOM) { r = new Random(SEED_RANDOM.nextLong()); } RANDOMS.set(r); } long tw = totalWeight; final ArrayList<SRVRecord> rl = new ArrayList<SRVRecord>(nonzeroWeightRecords); while (! rl.isEmpty()) { long w = ((r.nextLong() & 0x7FFFFFFFFFFFFFFFL) % tw); final Iterator<SRVRecord> iterator = rl.iterator(); while (iterator.hasNext()) { final SRVRecord record = iterator.next(); if ((w < record.getWeight()) || (! iterator.hasNext())) { iterator.remove(); records.add(record); tw -= record.getWeight(); break; } else { w -= record.getWeight(); } } } } } records.addAll(zeroWeightRecords); return records; } @Override() public String toString() { final StringBuilder buffer = new StringBuilder(); toString(buffer); return buffer.toString(); } void toString(final StringBuilder buffer) { buffer.append("SRVRecordPrioritySet(records={"); final Iterator<SRVRecord> iterator = allRecords.iterator(); while (iterator.hasNext()) { buffer.append(iterator.next().toString()); if (iterator.hasNext()) { buffer.append(", "); } } buffer.append("})"); } }