@Override public synchronized void succeeded(final BaseSendableGet succeeded, boolean persistent) { if (persistent) { try { jobRunner.queue( new DBJob() { @Override public boolean run(ObjectContainer container, ClientContext context) { if (container.ext().isActive(succeeded)) Logger.error(this, "ALREADY ACTIVE in succeeded(): " + succeeded); container.activate(succeeded, 1); schedCore.succeeded(succeeded, container); container.deactivate(succeeded, 1); return false; } @Override public String toString() { return "BaseSendableGet succeeded"; } }, TRIP_PENDING_PRIORITY, false); } catch (DatabaseDisabledException e) { Logger.error( this, "succeeded() on a persistent request but database disabled", new Exception("error")); } // Boost the priority so the PersistentChosenRequest gets deleted reasonably quickly. } else schedTransient.succeeded(succeeded, null); }
/** * Register a group of requests (not inserts): a GotKeyListener and/or one or more SendableGet's. * * @param listener Listens for specific keys. Can be null if the listener is already registered * i.e. on retrying. * @param getters The actual requests to register to the request sender queue. * @param persistent True if the request is persistent. * @param onDatabaseThread True if we are running on the database thread. NOTE: * delayedStoreCheck/probablyNotInStore is unnecessary because we only register the listener * once. * @throws FetchException */ public void register( final HasKeyListener hasListener, final SendableGet[] getters, final boolean persistent, ObjectContainer container, final BlockSet blocks, final boolean noCheckStore) throws KeyListenerConstructionException { if (logMINOR) Logger.minor(this, "register(" + persistent + "," + hasListener + "," + getters); if (isInsertScheduler) { IllegalStateException e = new IllegalStateException("finishRegister on an insert scheduler"); throw e; } if (persistent) { innerRegister(hasListener, getters, blocks, noCheckStore, container); } else { final KeyListener listener; if (hasListener != null) { listener = hasListener.makeKeyListener(container, clientContext, false); if (listener != null) schedTransient.addPendingKeys(listener); else Logger.normal(this, "No KeyListener for " + hasListener); } else listener = null; if (getters != null && !noCheckStore) { for (SendableGet getter : getters) datastoreChecker.queueTransientRequest(getter, blocks); } else { boolean anyValid = false; for (int i = 0; i < getters.length; i++) { if (!(getters[i].isCancelled(null) || getters[i].getCooldownTime(container, clientContext, System.currentTimeMillis()) != 0)) anyValid = true; } finishRegister(getters, false, container, anyValid, null); } } }
public void reregisterAll( final ClientRequester request, ObjectContainer container, short oldPrio) { schedTransient.reregisterAll(request, random, this, null, clientContext, oldPrio); if (schedCore != null) schedCore.reregisterAll(request, random, this, container, clientContext, oldPrio); starter.wakeUp(); }
public void registerInsert( final SendableRequest req, boolean persistent, boolean regmeOnly, ObjectContainer container) { if (!isInsertScheduler) throw new IllegalArgumentException("Adding a SendableInsert to a request scheduler!!"); if (persistent) { if (regmeOnly) { long bootID = 0; boolean queueFull = jobRunner.getQueueSize(NativeThread.NORM_PRIORITY) >= QUEUE_THRESHOLD; if (!queueFull) bootID = this.node.bootID; final RegisterMe regme = new RegisterMe(req, req.getPriorityClass(container), schedCore, null, bootID); container.store(regme); if (logMINOR) Logger.minor(this, "Added insert RegisterMe: " + regme); if (!queueFull) { try { jobRunner.queue( new DBJob() { @Override public boolean run(ObjectContainer container, ClientContext context) { container.delete(regme); if (req.isCancelled(container)) { if (logMINOR) Logger.minor(this, "Request already cancelled"); return false; } if (container.ext().isActive(req)) Logger.error(this, "ALREADY ACTIVE: " + req + " in delayed insert register"); container.activate(req, 1); registerInsert(req, true, false, container); container.deactivate(req, 1); return true; } @Override public String toString() { return "registerInsert"; } }, NativeThread.NORM_PRIORITY, false); } catch (DatabaseDisabledException e) { // Impossible, we are already on the database thread. } } else { schedCore.rerunRegisterMeRunner(jobRunner); } container.deactivate(req, 1); return; } schedCore.innerRegister(req, random, container, clientContext, null); starter.wakeUp(); } else { schedTransient.innerRegister(req, random, null, clientContext, null); starter.wakeUp(); } }
public void removeFromAllRequestsByClientRequest( ClientRequester clientRequest, SendableRequest get, boolean dontComplain, ObjectContainer container) { if (get.persistent()) schedCore.removeFromAllRequestsByClientRequest(get, clientRequest, dontComplain, container); else schedTransient.removeFromAllRequestsByClientRequest(get, clientRequest, dontComplain, null); }
public void tripPendingKey(final KeyBlock block) { if (logMINOR) Logger.minor(this, "tripPendingKey(" + block.getKey() + ")"); if (offeredKeys != null) { offeredKeys.remove(block.getKey()); } final Key key = block.getKey(); if (schedTransient.anyProbablyWantKey(key, clientContext)) { this.clientContext.mainExecutor.execute( new PrioRunnable() { @Override public void run() { schedTransient.tripPendingKey(key, block, null, clientContext); } @Override public int getPriority() { return TRIP_PENDING_PRIORITY; } }, "Trip pending key (transient)"); } if (schedCore == null) return; if (schedCore.anyProbablyWantKey(key, clientContext)) { try { jobRunner.queue( new DBJob() { @Override public boolean run(ObjectContainer container, ClientContext context) { if (logMINOR) Logger.minor(this, "tripPendingKey for " + key); if (schedCore.tripPendingKey(key, block, container, clientContext)) context.jobRunner.setCommitSoon(); return false; } @Override public String toString() { return "tripPendingKey"; } }, TRIP_PENDING_PRIORITY, false); } catch (DatabaseDisabledException e) { // Nothing to do } } else schedCore.countNegative(); }
private void restoreKey(Key key, ObjectContainer container, long now) { SendableGet[] reqs = container == null ? null : (schedCore == null ? null : schedCore.requestsForKey(key, container, clientContext)); SendableGet[] transientReqs = schedTransient.requestsForKey(key, container, clientContext); if (reqs == null && transientReqs == null) { // Not an error as this can happen due to race conditions etc. if (logMINOR) Logger.minor(this, "Restoring key but no keys queued?? for " + key); } if (reqs != null) { for (int i = 0; i < reqs.length; i++) { // Requests may or may not be returned activated from requestsForKey(), so don't check // But do deactivate them once we're done with them. container.activate(reqs[i], 1); reqs[i].requeueAfterCooldown(key, now, container, clientContext); container.deactivate(reqs[i], 1); } } if (transientReqs != null) { for (int i = 0; i < transientReqs.length; i++) transientReqs[i].requeueAfterCooldown(key, now, container, clientContext); } }
/** * Remove a KeyListener from the list of KeyListeners. * * @param getter * @param complain */ public void removePendingKeys(HasKeyListener getter, boolean complain) { boolean found = schedTransient.removePendingKeys(getter); if (schedCore != null) found |= schedCore.removePendingKeys(getter); if (complain && !found) Logger.error(this, "Listener not found when removing: " + getter); }
void finishRegister( final SendableGet[] getters, boolean persistent, ObjectContainer container, final boolean anyValid, final DatastoreCheckerItem reg) { if (logMINOR) Logger.minor( this, "finishRegister for " + getters + " anyValid=" + anyValid + " reg=" + reg + " persistent=" + persistent); if (isInsertScheduler) { IllegalStateException e = new IllegalStateException("finishRegister on an insert scheduler"); for (int i = 0; i < getters.length; i++) { if (persistent) container.activate(getters[i], 1); getters[i].internalError(e, this, container, clientContext, persistent); if (persistent) container.deactivate(getters[i], 1); } throw e; } if (persistent) { // Add to the persistent registration queue if (!databaseExecutor.onThread()) { throw new IllegalStateException("Not on database thread!"); } if (persistent) container.activate(getters, 1); if (logMINOR) Logger.minor(this, "finishRegister() for " + getters); if (anyValid) { boolean wereAnyValid = false; for (int i = 0; i < getters.length; i++) { SendableGet getter = getters[i]; container.activate(getter, 1); // Just check isCancelled, we have already checked the cooldown. if (!(getter.isCancelled(container))) { wereAnyValid = true; if (!getter.preRegister(container, clientContext, true)) { schedCore.innerRegister(getter, random, container, clientContext, getters); } } else getter.preRegister(container, clientContext, false); } if (!wereAnyValid) { Logger.normal(this, "No requests valid: " + getters); } } else { Logger.normal(this, "No valid requests passed in: " + getters); } if (reg != null) container.delete(reg); queueFillRequestStarterQueue(true); } else { // Register immediately. for (int i = 0; i < getters.length; i++) { if ((!anyValid) || getters[i].isCancelled(null)) { getters[i].preRegister(container, clientContext, false); continue; } else { if (getters[i].preRegister(container, clientContext, true)) continue; } if (!getters[i].isCancelled(null)) schedTransient.innerRegister(getters[i], random, null, clientContext, getters); } starter.wakeUp(); } }
public byte[] saltKey(boolean persistent, Key key) { return persistent ? schedCore.saltKey(key) : schedTransient.saltKey(key); }
@Override public long countTransientQueuedRequests() { return schedTransient.countQueuedRequests(null, clientContext); }
/* FIXME SECURITY When/if introduce tunneling or similar mechanism for starting requests * at a distance this will need to be reconsidered. See the comments on the caller in * RequestHandler (onAbort() handler). */ @Override public boolean wantKey(Key key) { if (schedTransient.anyProbablyWantKey(key, clientContext)) return true; if (schedCore != null && schedCore.anyProbablyWantKey(key, clientContext)) return true; return false; }