public void executeNoDupes(Runnable job, int prio, String jobName) {
    synchronized (jobs) {
      if (jobs[prio].contains(job)) {
        if (logMINOR) Logger.minor(this, "Not queueing job: Job already queued: " + job);
        return;
      }

      if (logMINOR)
        Logger.minor(
            this,
            "Queueing "
                + jobName
                + " : "
                + job
                + " priority "
                + prio
                + ", executor state: running="
                + running
                + " waiting="
                + waiting);

      jobs[prio].addLast(job);
      jobs.notifyAll();
      if (!running && realExecutor != null) {
        reallyStart();
      }
    }
  }
    public void run() {
      long lastDumped = System.currentTimeMillis();
      synchronized (jobs) {
        if (current != null) {
          if (current.isAlive()) {
            Logger.error(
                this, "Already running a thread for " + this + " !!", new Exception("error"));
            return;
          }
        }
        current = Thread.currentThread();
      }
      try {
        while (true) {
          Runnable job = null;
          synchronized (jobs) {
            job = checkQueue();
            if (job == null) {
              waiting = true;
              try {
                // NB: notify only on adding work or this quits early.
                jobs.wait(jobTimeout);
              } catch (InterruptedException e) {
                // Ignore
              }
              waiting = false;
              job = checkQueue();
              if (job == null) {
                running = false;
                return;
              }
            }
          }
          try {
            if (logMINOR) Logger.minor(this, "Running job " + job);
            long start = System.currentTimeMillis();
            job.run();
            long end = System.currentTimeMillis();
            if (logMINOR) {
              Logger.minor(this, "Job " + job + " took " + (end - start) + "ms");
            }

            if (statistics != null) {
              statistics.reportDatabaseJob(job.toString(), end - start);
            }
          } catch (Throwable t) {
            Logger.error(this, "Caught " + t, t);
            Logger.error(this, "While running " + job + " on " + this);
          }
        }
      } finally {
        synchronized (jobs) {
          current = null;
          running = false;
        }
      }
    }
  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);
    }
  }
예제 #4
0
 private void reallyStart() {
   synchronized (syncLock) {
     threadStarted = true;
   }
   if (logMINOR) Logger.minor(this, "Starting thread... " + name + " : " + runner);
   realExecutor.execute(runner, name);
 }
 @Override
 public void maybeRemove(RemoveRandom r, ClientContext context) {
   int count = 0;
   int finalSize;
   synchronized (root) {
     while (true) {
       int found = -1;
       for (int i = 0; i < grabArrays.length; i++) {
         if (grabArrays[i] == r) {
           found = i;
           break;
         }
       }
       if (found != -1) {
         count++;
         if (count > 1)
           Logger.error(this, "Found " + r + " many times in " + this, new Exception("error"));
         removeElement(found);
       } else {
         break;
       }
     }
     finalSize = grabArrays.length;
   }
   if (count == 0) {
     // This is not unusual, it was e.g. removed because of being empty.
     // And it has already been removeFrom()'ed.
     if (logMINOR)
       Logger.minor(this, "Not in parent: " + r + " for " + this, new Exception("error"));
   }
   if (finalSize == 0 && parent != null) {
     parent.maybeRemove(this, context);
   }
 }
 @Override
 public void clearWakeupTime(ClientContext context) {
   if (logMINOR) Logger.minor(this, "clearCooldownTime() on " + this);
   synchronized (root) {
     wakeupTime = 0;
     if (parent != null) parent.clearWakeupTime(context);
   }
 }
 private Runnable checkQueue() {
   if (!invertOrder) {
     for (int i = 0; i < jobs.length; i++) {
       if (!jobs[i].isEmpty()) {
         if (logMINOR) Logger.minor(this, "Chosen job at priority " + i);
         return jobs[i].removeFirst();
       }
     }
   } else {
     for (int i = jobs.length - 1; i >= 0; i--) {
       if (!jobs[i].isEmpty()) {
         if (logMINOR) Logger.minor(this, "Chosen job at priority " + i);
         return jobs[i].removeFirst();
       }
     }
   }
   return null;
 }
 private void reallyStart() {
   synchronized (jobs) {
     if (running) {
       Logger.error(this, "Not reallyStart()ing: ALREADY RUNNING", new Exception("error"));
       return;
     }
     running = true;
     if (logMINOR)
       Logger.minor(this, "Starting thread... " + name + " : " + runner, new Exception("debug"));
     realExecutor.execute(runner, name);
   }
 }
 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);
   }
 }
 @Override
 public boolean reduceWakeupTime(long wakeupTime, ClientContext context) {
   if (logMINOR)
     Logger.minor(
         this, "reduceCooldownTime(" + (wakeupTime - System.currentTimeMillis()) + ") on " + this);
   boolean reachedRoot = false;
   synchronized (root) {
     if (this.wakeupTime > wakeupTime) {
       this.wakeupTime = wakeupTime;
       if (parent != null) parent.reduceWakeupTime(wakeupTime, context);
       else reachedRoot = true; // Even if it reduces it we need to wake it up.
     } else return false;
   }
   if (reachedRoot) root.wakeUp(context);
   return true;
 }
예제 #11
0
  @Override
  public void execute(Runnable job, String jobName) {
    if (logMINOR)
      Logger.minor(
          this,
          "Running "
              + jobName
              + " : "
              + job
              + " started="
              + threadStarted
              + " waiting="
              + threadWaiting);
    jobs.add(job);

    synchronized (syncLock) {
      if (!threadStarted && realExecutor != null) reallyStart();
    }
  }
 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;
        }
      }
    }
  }
 public void run() {
   long lastDumped = System.currentTimeMillis();
   synchronized (jobs) {
     if (current != null) {
       if (current.isAlive()) {
         Logger.error(
             this, "Already running a thread for " + this + " !!", new Exception("error"));
         return;
       }
     }
     current = Thread.currentThread();
   }
   try {
     while (true) {
       Runnable job = null;
       synchronized (jobs) {
         job = checkQueue();
         if (job == null) {
           waiting = true;
           try {
             // NB: notify only on adding work or this quits early.
             jobs.wait(jobTimeout);
           } catch (InterruptedException e) {
             // Ignore
           }
           waiting = false;
           job = checkQueue();
           if (job == null) {
             running = false;
             return;
           }
         }
       }
       try {
         if (logMINOR) Logger.minor(this, "Running job " + job);
         long start = System.currentTimeMillis();
         job.run();
         long end = System.currentTimeMillis();
         if (logMINOR) {
           Logger.minor(this, "Job " + job + " took " + (end - start) + "ms");
           synchronized (timeByJobClasses) {
             String name = job.toString();
             if (name.indexOf('@') > 0) name = name.substring(0, name.indexOf('@'));
             Long l = timeByJobClasses.get(name);
             if (l != null) {
               l = Long.valueOf(l.longValue() + (end - start));
             } else {
               l = Long.valueOf(end - start);
             }
             timeByJobClasses.put(name, l);
             if (logMINOR) {
               Logger.minor(this, "Total for class " + name + " : " + l);
               if (System.currentTimeMillis() > (lastDumped + 60 * 1000)) {
                 Iterator i = timeByJobClasses.entrySet().iterator();
                 while (i.hasNext()) {
                   Map.Entry e = (Map.Entry) i.next();
                   Logger.minor(this, "Class " + e.getKey() + " : total time " + e.getValue());
                 }
                 lastDumped = System.currentTimeMillis();
               }
             }
           }
         }
       } catch (Throwable t) {
         Logger.error(this, "Caught " + t, t);
         Logger.error(this, "While running " + job + " on " + this);
       }
     }
   } finally {
     synchronized (jobs) {
       current = null;
       running = false;
     }
   }
 }