private RemoveRandomReturn removeRandomExhaustive( RandomGrabArrayItemExclusionList excluding, ClientContext context, long now) { synchronized (root) { long wakeupTime = Long.MAX_VALUE; if (grabArrays.length == 0) return null; int x = context.fastWeakRandom.nextInt(grabArrays.length); for (int i = 0; i < grabArrays.length; i++) { x++; if (x >= grabArrays.length) x = 0; RemoveRandomWithObject<T> rga = grabArrays[x]; long excludeTime = rga.getWakeupTime(context, now); if (excludeTime > 0) { if (wakeupTime > excludeTime) wakeupTime = excludeTime; continue; } if (logMINOR) Logger.minor( this, "Picked " + x + " of " + grabArrays.length + " : " + rga + " on " + this); RandomGrabArrayItem item = null; RemoveRandomReturn val = rga.removeRandom(excluding, context, now); if (val != null) { if (val.item != null) item = val.item; else { if (wakeupTime > val.wakeupTime) wakeupTime = val.wakeupTime; } } if (logMINOR) Logger.minor( this, "RGA has picked " + x + "/" + grabArrays.length + ": " + item + " rga.isEmpty=" + rga.isEmpty()); if (item != null) { return new RemoveRandomReturn(item); } else if (rga.isEmpty()) { if (logMINOR) Logger.minor(this, "Removing grab array " + x + " : " + rga + " (is empty)"); removeElement(x); } } reduceWakeupTime(wakeupTime, context); return new RemoveRandomReturn(wakeupTime); } }
private RemoveRandomReturn removeRandomOneOnly( RandomGrabArrayItemExclusionList excluding, ClientContext context, long now) { synchronized (root) { long wakeupTime = Long.MAX_VALUE; // Optimise the common case RemoveRandomWithObject<T> rga = grabArrays[0]; if (logMINOR) Logger.minor(this, "Only one RGA: " + rga); long excludeTime = rga.getWakeupTime(context, now); if (excludeTime > 0) return new RemoveRandomReturn(excludeTime); if (rga == null) { Logger.error(this, "Only one entry and that is null"); // We are sure grabArrays = (C[]) new RemoveRandomWithObject[0]; grabClients = (T[]) new Object[0]; return null; } RemoveRandomReturn val = rga.removeRandom(excluding, context, now); RandomGrabArrayItem item = null; if (val != null) { // val == null => remove it if (val.item != null) item = val.item; else { wakeupTime = val.wakeupTime; } } if (rga.isEmpty()) { if (logMINOR) Logger.minor(this, "Removing only grab array (0) : " + rga); grabArrays = (C[]) new RemoveRandomWithObject[0]; grabClients = (T[]) new Object[0]; } if (logMINOR) Logger.minor(this, "Returning (one item only) " + item + " for " + rga); if (item == null) { if (grabArrays.length == 0) { if (logMINOR) Logger.minor(this, "Arrays are empty on " + this); return null; // Remove this as well } reduceWakeupTime(wakeupTime, context); return new RemoveRandomReturn(wakeupTime); } else return new RemoveRandomReturn(item); } }
private RemoveRandomReturn removeRandomTwoOnly( RandomGrabArrayItemExclusionList excluding, ClientContext context, long now) { synchronized (root) { long wakeupTime = Long.MAX_VALUE; // Another simple common case int x = context.fastWeakRandom.nextBoolean() ? 1 : 0; RemoveRandomWithObject<T> rga = grabArrays[x]; RemoveRandomWithObject<T> firstRGA = rga; if (rga == null) { Logger.error(this, "rga = null on " + this); if (grabArrays[1 - x] == null) { Logger.error(this, "other rga is also null on " + this); grabArrays = (C[]) new RemoveRandomWithObject[0]; grabClients = (T[]) new Object[0]; return null; } else { Logger.error( this, "grabArrays[" + (1 - x) + "] is valid but [" + x + "] is null, correcting..."); grabArrays = (C[]) new RemoveRandomWithObject[] {grabArrays[1 - x]}; grabClients = (T[]) new Object[] {grabClients[1 - x]}; return null; } } RandomGrabArrayItem item = null; RemoveRandomReturn val = null; if (logMINOR) Logger.minor(this, "Only 2, trying " + rga); long excludeTime = rga.getWakeupTime(context, now); if (excludeTime > 0) { wakeupTime = excludeTime; rga = null; firstRGA = null; } else { val = rga.removeRandom(excluding, context, now); if (val != null) { if (val.item != null) item = val.item; else { if (wakeupTime > val.wakeupTime) wakeupTime = val.wakeupTime; } } } if (item != null) { if (logMINOR) Logger.minor(this, "Returning (two items only) " + item + " for " + rga); return new RemoveRandomReturn(item); } else { x = 1 - x; rga = grabArrays[x]; if (rga == null) { Logger.error(this, "Other RGA is null later on on " + this); grabArrays = (C[]) new RemoveRandomWithObject[] {grabArrays[1 - x]}; grabClients = (T[]) new Object[] {grabClients[1 - x]}; reduceWakeupTime(wakeupTime, context); return new RemoveRandomReturn(wakeupTime); } excludeTime = rga.getWakeupTime(context, now); if (excludeTime > 0) { if (wakeupTime > excludeTime) wakeupTime = excludeTime; rga = null; } else { val = rga.removeRandom(excluding, context, now); if (val != null) { if (val.item != null) item = val.item; else { if (wakeupTime > val.wakeupTime) wakeupTime = val.wakeupTime; } } } if (firstRGA != null && firstRGA.isEmpty() && rga != null && rga.isEmpty()) { if (logMINOR) Logger.minor( this, "Removing both on " + this + " : " + firstRGA + " and " + rga + " are empty"); grabArrays = (C[]) new RemoveRandomWithObject[0]; grabClients = (T[]) new Object[0]; } else if (firstRGA != null && firstRGA.isEmpty()) { if (logMINOR) Logger.minor(this, "Removing first: " + firstRGA + " is empty on " + this); grabArrays = (C[]) new RemoveRandomWithObject[] { grabArrays[x] }; // don't use RGA, it may be nulled out grabClients = (T[]) new Object[] {grabClients[x]}; } if (logMINOR) Logger.minor(this, "Returning (two items only) " + item + " for " + rga); if (item == null) { if (grabArrays.length == 0) return null; // Remove this as well reduceWakeupTime(wakeupTime, context); return new RemoveRandomReturn(wakeupTime); } else return new RemoveRandomReturn(item); } } }
private RandomGrabArrayItem removeRandomLimited( RandomGrabArrayItemExclusionList excluding, ClientContext context, long now) { synchronized (root) { /** Count of arrays that have items but didn't return anything because of exclusions */ final int MAX_EXCLUDED = 10; int excluded = 0; while (true) { if (grabArrays.length == 0) return null; int x = context.fastWeakRandom.nextInt(grabArrays.length); RemoveRandomWithObject<T> rga = grabArrays[x]; if (rga == null) { // We handle this in the other cases so we should handle it here. Logger.error(this, "Slot " + x + " is null for client " + grabClients[x]); excluded++; if (excluded > MAX_EXCLUDED) { Logger.normal( this, "Too many sub-arrays are entirely excluded on " + this + " length = " + grabArrays.length, new Exception("error")); return null; } continue; } long excludeTime = rga.getWakeupTime(context, now); if (excludeTime > 0) { excluded++; if (excluded > MAX_EXCLUDED) { Logger.normal( this, "Too many sub-arrays are entirely excluded on " + this + " length = " + grabArrays.length, new Exception("error")); return null; } continue; } if (logMINOR) Logger.minor( this, "Picked " + x + " of " + grabArrays.length + " : " + rga + " on " + this); RandomGrabArrayItem item = null; RemoveRandomReturn val = rga.removeRandom(excluding, context, now); if (val != null && val.item != null) item = val.item; if (logMINOR) Logger.minor( this, "RGA has picked " + x + "/" + grabArrays.length + ": " + item + " rga.isEmpty=" + rga.isEmpty()); // If it is not empty but returns null we exclude it, and count the exclusion. // If it is empty we remove it, and don't count the exclusion. if (item != null) { return item; } else { if (rga.isEmpty()) { if (logMINOR) Logger.minor(this, "Removing grab array " + x + " : " + rga + " (is empty)"); removeElement(x); } else { excluded++; if (excluded > MAX_EXCLUDED) { Logger.normal( this, "Too many sub-arrays are entirely excluded on " + this + " length = " + grabArrays.length, new Exception("error")); return null; } } continue; } } } }