@Override
 public boolean hasValidKeys(
     KeysFetchingLocally keys, ObjectContainer container, ClientContext context) {
   if (persistent) {
     container.activate(this, 1);
     container.activate(blockNums, 1);
     container.activate(segment, 1);
   }
   boolean hasSet = false;
   boolean retval = false;
   synchronized (segment) {
     for (int i = 0; i < 10; i++) {
       Integer ret;
       int x;
       if (blockNums.isEmpty()) {
         break;
       }
       x = context.random.nextInt(blockNums.size());
       ret = blockNums.get(x);
       int block = ret;
       Key key = segment.getBlockNodeKey(block, container);
       if (key == null) {
         if (segment.isFinishing(container) || segment.isFinished(container)) return false;
         if (segment.haveBlock(block, container))
           Logger.error(
               this,
               "Already have block "
                   + ret
                   + " but was in blockNums on "
                   + this
                   + " in hasValidKeys");
         else
           Logger.error(
               this, "Key is null for block " + ret + " for " + this + " in hasValidKeys");
         blockNums.remove(x);
         if (persistent) {
           container.delete(ret);
           if (!hasSet) {
             hasSet = true;
             container.store(blockNums);
           }
         }
         continue;
       }
       if (keys.hasKey(key)) {
         continue;
       }
       retval = true;
       break;
     }
   }
   if (persistent) {
     container.deactivate(blockNums, 5);
     container.deactivate(segment, 1);
   }
   return retval;
 }
  public void onGotKey(Key key, KeyBlock block, ObjectContainer container, ClientContext context) {
    if (persistent) {
      container.activate(this, 1);
      container.activate(segment, 1);
      container.activate(blockNums, 1);
    }
    if (logMINOR) Logger.minor(this, "onGotKey(" + key + ")");
    // Find and remove block if it is on this subsegment. However it may have been
    // removed already.
    int blockNo;
    synchronized (segment) {
      for (int i = 0; i < blockNums.size(); i++) {
        Integer token = blockNums.get(i);
        int num = token;
        Key k = segment.getBlockNodeKey(num, container);
        if (k != null && k.equals(key)) {
          blockNums.remove(i);
          if (persistent) container.delete(token);
          break;
        }
      }
      blockNo = segment.getBlockNumber(key, container);
    }
    if (blockNo == -1) {
      Logger.minor(this, "No block found for key " + key + " on " + this);
      return;
    }
    Integer token = Integer.valueOf(blockNo);
    ClientCHK ckey = segment.getBlockKey(blockNo, container);
    ClientCHKBlock cb;
    try {
      cb = new ClientCHKBlock((CHKBlock) block, ckey);
    } catch (CHKVerifyException e) {
      onFailure(
          new FetchException(FetchException.BLOCK_DECODE_ERROR, e), token, container, context);
      return;
    }
    Bucket data = extract(cb, token, container, context);
    if (data == null) return;

    if (!cb.isMetadata()) {
      onSuccess(data, false, token, (token).intValue(), cb, container, context);
    } else {
      onFailure(
          new FetchException(FetchException.INVALID_METADATA, "Metadata where expected data"),
          token,
          container,
          context);
    }
  }
 private SendableRequestItem getRandomBlockNum(
     KeysFetchingLocally keys, ClientContext context, ObjectContainer container) {
   if (persistent) {
     container.activate(this, 1);
     container.activate(blockNums, 1);
     container.activate(segment, 1);
   }
   logMINOR = Logger.shouldLog(Logger.MINOR, this);
   synchronized (segment) {
     if (blockNums.isEmpty()) {
       if (logMINOR) Logger.minor(this, "No blocks to remove");
       return null;
     }
     for (int i = 0; i < 10; i++) {
       Integer ret;
       int x;
       if (blockNums.size() == 0) return null;
       x = context.random.nextInt(blockNums.size());
       ret = blockNums.get(x);
       int num = ret;
       Key key = segment.getBlockNodeKey(num, container);
       if (key == null) {
         if (segment.isFinishing(container) || segment.isFinished(container)) return null;
         if (segment.haveBlock(num, container))
           Logger.error(this, "Already have block " + ret + " but was in blockNums on " + this);
         else Logger.error(this, "Key is null for block " + ret + " for " + this);
         continue;
       }
       if (keys.hasKey(key)) {
         continue;
       }
       if (logMINOR)
         Logger.minor(
             this,
             "Removing block "
                 + x
                 + " of "
                 + (blockNums.size() + 1)
                 + " : "
                 + ret
                 + " on "
                 + this);
       return new MySendableRequestItem(num);
     }
     return null;
   }
 }