@SuppressWarnings("rawtypes")
 @Override
 public void start(SenseiCore senseiCore) {
   persistentCaches = new HashMap<Integer, PersistentCache>(senseiCore.getPartitions().length);
   for (int partition : senseiCore.getPartitions()) {
     Zoie zoie = (Zoie) senseiCore.getIndexReaderFactory(partition);
     PersistentCache persistentCache =
         new PersistentCache(getPath(indexDirectory, nodeId, partition), versionComparator);
     PersistentCache.registerAsListener(persistentCache, zoie);
     persistentCaches.put(partition, persistentCache);
   }
 }
  public final Res execute(final Req senseiReq) {
    SearchCounter.mark();
    Set<Integer> partitions = senseiReq == null ? null : senseiReq.getPartitions();
    if (partitions == null) {
      partitions = new HashSet<Integer>();
      int[] containsPart = _core.getPartitions();
      if (containsPart != null) {
        for (int part : containsPart) {
          partitions.add(part);
        }
      }
    }
    Res finalResult;
    if (partitions != null && partitions.size() > 0) {
      if (logger.isDebugEnabled()) {
        logger.debug("serving partitions: " + partitions.toString());
      }
      final ArrayList<Res> resultList = new ArrayList<Res>(partitions.size());
      Future<Res>[] futures = new Future[partitions.size() - 1];
      int i = 0;
      for (final int partition : partitions) {
        final long start = System.currentTimeMillis();
        final IndexReaderFactory<ZoieIndexReader<BoboIndexReader>> readerFactory =
            _core.getIndexReaderFactory(partition);

        if (i < partitions.size() - 1) // Search simultaneously.
        {
          try {
            futures[i] =
                (Future<Res>)
                    _executorService.submit(
                        new Callable<Res>() {
                          public Res call() throws Exception {
                            Timer timer = getTimer(partition);

                            Res res =
                                timer.time(
                                    new Callable<Res>() {

                                      @Override
                                      public Res call() throws Exception {
                                        return handleRequest(
                                            senseiReq,
                                            readerFactory,
                                            _core.getQueryBuilderFactory());
                                      }
                                    });

                            long end = System.currentTimeMillis();
                            res.setTime(end - start);
                            logger.info(
                                "searching partition: "
                                    + partition
                                    + " browse took: "
                                    + res.getTime());

                            return res;
                          }
                        });
          } catch (Exception e) {
            senseiReq.addError(new SenseiError(e.getMessage(), ErrorType.BoboExecutionError));
            logger.error(e.getMessage(), e);
          }
        } else // Reuse current thread.
        {
          try {
            Timer timer = getTimer(partition);
            Res res =
                timer.time(
                    new Callable<Res>() {

                      @Override
                      public Res call() throws Exception {
                        return handleRequest(
                            senseiReq, readerFactory, _core.getQueryBuilderFactory());
                      }
                    });

            resultList.add(res);
            long end = System.currentTimeMillis();
            res.setTime(end - start);
            logger.info("searching partition: " + partition + " browse took: " + res.getTime());
          } catch (Exception e) {
            logger.error(e.getMessage(), e);
            senseiReq.addError(new SenseiError(e.getMessage(), ErrorType.BoboExecutionError));

            resultList.add(getEmptyResultInstance(e));
          }
        }
        ++i;
      }

      for (i = 0; i < futures.length; ++i) {
        try {
          Res res = futures[i].get(_timeout, TimeUnit.MILLISECONDS);
          resultList.add(res);
        } catch (Exception e) {

          logger.error(e.getMessage(), e);
          if (e instanceof TimeoutException) {
            senseiReq.addError(new SenseiError(e.getMessage(), ErrorType.ExecutionTimeout));
          } else {
            senseiReq.addError(new SenseiError(e.getMessage(), ErrorType.BoboExecutionError));
          }
          resultList.add(getEmptyResultInstance(e));
        }
      }

      try {
        finalResult =
            MergeTimer.time(
                new Callable<Res>() {
                  public Res call() throws Exception {
                    return mergePartitionedResults(senseiReq, resultList);
                  }
                });
      } catch (Exception e) {
        logger.error(e.getMessage(), e);
        finalResult = getEmptyResultInstance(null);
        finalResult.addError(new SenseiError(e.getMessage(), ErrorType.MergePartitionError));
      }
    } else {
      if (logger.isInfoEnabled()) {
        logger.info("no partitions specified");
      }
      finalResult = getEmptyResultInstance(null);
      finalResult.addError(
          new SenseiError("no partitions specified", ErrorType.PartitionCallError));
    }
    if (logger.isInfoEnabled()) {
      logger.info(
          "searching partitions  "
              + String.valueOf(partitions)
              + " took: "
              + finalResult.getTime());
    }
    return finalResult;
  }