package org.freertr.addr; import java.math.BigInteger; import org.freertr.util.bits; import org.freertr.util.logger; /** * address pool * * @param type of address * @author matecsaba */ public class addrPool { /** * name of this pool */ public String poolName; private T first; private BigInteger frst; private BigInteger incr; private boolean[] used; /** * setup address pool * * @param adr first address * @param nxt increment of next address * @param num number of addresses in pool */ @SuppressWarnings("unchecked") public addrPool(T adr, T nxt, int num) { first = (T) adr.copyBytes(); used = new boolean[num]; for (int i = 0; i < num; i++) { used[i] = false; } frst = addr2bn(first); incr = addr2bn(nxt); } public String toString() { return poolName; } private BigInteger addr2bn(T adr) { byte[] buf1 = adr.getBytes(); byte[] buf2 = new byte[buf1.length + 1]; bits.byteCopy(buf1, 0, buf2, 1, buf1.length); buf2[0] = 0; return new BigInteger(buf2); } @SuppressWarnings("unchecked") private T bn2addr(BigInteger n) { T a = (T) first.copyBytes(); final int as = a.getSize(); byte[] buf1 = n.toByteArray(); if (buf1.length > as) { a.fromBuf(buf1, buf1.length - as); return a; } byte[] buf2 = new byte[as]; for (int i = 0; i < as; i++) { buf2[i] = 0; } bits.byteCopy(buf1, 0, buf2, as - buf1.length, buf1.length); a.fromBuf(buf2, 0); return a; } /** * return total number of addresses * * @return total number of addresses */ public int addrTotal() { return used.length; } /** * return free number of addresses * * @return free number of addresses */ public int addrFree() { int o = 0; for (int i = 0; i < used.length; i++) { if (used[i] == false) { o++; } } return o; } /** * allocate one address * * @return address allocated, null if none */ public synchronized T addrAlloc() { for (int retry = 0; retry < 64; retry++) { int i = bits.random(0, used.length); if (used[i]) { continue; } used[i] = true; BigInteger b = new BigInteger("" + i).multiply(incr).add(frst); return bn2addr(b); } logger.warn("failed to allocate new address"); return null; } /** * release one address * * @param adr address to release */ public void addrRelease(T adr) { BigInteger i = addr2bn(adr); i = i.subtract(frst).divide(incr); int o = i.intValue(); if ((o < 0) || (o >= used.length)) { return; } used[o] = false; } }