Ejemplo n.º 1
0
 /** Called by RequestStarter to find a request to run. */
 @Override
 public ChosenBlock grabRequest() {
   boolean needsRefill = true;
   while (true) {
     PersistentChosenRequest reqGroup = null;
     synchronized (starterQueue) {
       short bestPriority = Short.MAX_VALUE;
       for (PersistentChosenRequest req : starterQueue) {
         if (req.prio == RequestStarter.MINIMUM_PRIORITY_CLASS) {
           if (logDEBUG)
             Logger.debug(
                 this, "Ignoring paused persistent request: " + req + " prio: " + req.prio);
           continue; // Ignore paused requests
         }
         if (req.prio < bestPriority) {
           bestPriority = req.prio;
           reqGroup = req;
         }
       }
     }
     if (reqGroup != null) {
       // Try to find a better non-persistent request
       if (logMINOR)
         Logger.minor(this, "Persistent request: " + reqGroup + " prio " + reqGroup.prio);
       ChosenBlock better = getBetterNonPersistentRequest(reqGroup.prio);
       if (better != null) {
         if (better.getPriority() > reqGroup.prio) {
           Logger.error(
               this, "Selected " + better + " as better than " + reqGroup + " but isn't better!");
         }
         if (logMINOR) Logger.minor(this, "Returning better: " + better);
         return better;
       }
     }
     if (reqGroup == null) {
       queueFillRequestStarterQueue();
       return getBetterNonPersistentRequest(Short.MAX_VALUE);
     }
     ChosenBlock block;
     synchronized (starterQueue) {
       block = reqGroup.grabNotStarted(clientContext.fastWeakRandom, this);
       if (block == null) {
         if (logMINOR) Logger.minor(this, "No block found on " + reqGroup);
         int finalLength = 0;
         for (int i = 0; i < starterQueue.size(); i++) {
           if (starterQueue.get(i) == reqGroup) {
             starterQueue.remove(i);
             if (logMINOR)
               Logger.minor(this, "Removed " + reqGroup + " from starter queue because is empty");
             i--;
           } else {
             finalLength += starterQueue.get(i).sizeNotStarted();
           }
         }
         needsRefill = finalLength < MAX_STARTER_QUEUE_SIZE;
         continue;
       } else {
         // Prevent this request being selected, even though we may remove the PCR from the starter
         // queue
         // in the very near future. When the PCR finishes, the requests will be un-blocked.
         if (!runningPersistentRequests.contains(reqGroup.request))
           runningPersistentRequests.add(reqGroup.request);
       }
     }
     if (needsRefill) queueFillRequestStarterQueue();
     if (logMINOR) Logger.minor(this, "grabRequest() returning " + block + " for " + reqGroup);
     return block;
   }
 }
Ejemplo n.º 2
0
    public boolean send(
        NodeClientCore core, RequestScheduler sched, final ClientContext context, ChosenBlock req) {
      // Ignore keyNum, key, since we're only sending one block.
      ClientKeyBlock b;
      ClientKey key = null;
      if (SingleBlockInserter.logMINOR)
        Logger.minor(this, "Starting request: " + SingleBlockInserter.this);
      BlockItem block = (BlockItem) req.token;
      try {
        try {
          b =
              innerEncode(
                  context.random,
                  block.uri,
                  block.copyBucket,
                  block.isMetadata,
                  block.compressionCodec,
                  block.sourceLength,
                  compressorDescriptor);
        } catch (CHKEncodeException e) {
          throw new LowLevelPutException(
              LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e);
        } catch (SSKEncodeException e) {
          throw new LowLevelPutException(
              LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e);
        } catch (MalformedURLException e) {
          throw new LowLevelPutException(
              LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e);
        } catch (InsertException e) {
          throw new LowLevelPutException(
              LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e);
        } catch (IOException e) {
          throw new LowLevelPutException(
              LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e);
        } catch (InvalidCompressionCodecException e) {
          throw new LowLevelPutException(
              LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e);
        }
        if (b == null) {
          Logger.error(
              this,
              "Asked to send empty block on " + SingleBlockInserter.this,
              new Exception("error"));
          return false;
        }
        key = b.getClientKey();
        final ClientKey k = key;
        if (block.persistent) {
          context.jobRunner.queue(
              new DBJob() {

                public boolean run(ObjectContainer container, ClientContext context) {
                  if (!container.ext().isStored(SingleBlockInserter.this)) return false;
                  container.activate(SingleBlockInserter.this, 1);
                  onEncode(k, container, context);
                  container.deactivate(SingleBlockInserter.this, 1);
                  return false;
                }
              },
              NativeThread.NORM_PRIORITY + 1,
              false);
        } else {
          context.mainExecutor.execute(
              new Runnable() {

                public void run() {
                  onEncode(k, null, context);
                }
              },
              "Got URI");
        }
        if (req.localRequestOnly)
          try {
            core.node.store(b, false, req.canWriteClientCache, true, false);
          } catch (KeyCollisionException e) {
            throw new LowLevelPutException(LowLevelPutException.COLLISION);
          }
        else core.realPut(b, req.canWriteClientCache, req.forkOnCacheable);
      } catch (LowLevelPutException e) {
        if (e.code == LowLevelPutException.COLLISION) {
          // Collision
          try {
            ClientSSKBlock collided =
                (ClientSSKBlock)
                    core.node.fetch((ClientSSK) key, true, true, req.canWriteClientCache);
            byte[] data = collided.memoryDecode(true);
            byte[] inserting = BucketTools.toByteArray(block.copyBucket);
            if (collided.isMetadata() == block.isMetadata
                && collided.getCompressionCodec() == block.compressionCodec
                && Arrays.equals(data, inserting)) {
              if (SingleBlockInserter.logMINOR)
                Logger.minor(this, "Collided with identical data: " + SingleBlockInserter.this);
              req.onInsertSuccess(context);
              return true;
            }
          } catch (KeyVerifyException e1) {
            Logger.error(this, "Caught " + e1 + " when checking collision!", e1);
          } catch (KeyDecodeException e1) {
            Logger.error(this, "Caught " + e1 + " when checking collision!", e1);
          } catch (IOException e1) {
            Logger.error(this, "Caught " + e1 + " when checking collision!", e1);
          }
        }
        req.onFailure(e, context);
        if (SingleBlockInserter.logMINOR)
          Logger.minor(this, "Request failed: " + SingleBlockInserter.this + " for " + e);
        return true;
      } catch (DatabaseDisabledException e) {
        // Impossible, and nothing to do.
        Logger.error(this, "Running persistent insert but database is disabled!");
      } finally {
        block.copyBucket.free();
      }
      if (SingleBlockInserter.logMINOR)
        Logger.minor(this, "Request succeeded: " + SingleBlockInserter.this);
      req.onInsertSuccess(context);
      return true;
    }