Exemple #1
0
  /**
   * Find the best editlog input stream to read from txid. If a journal throws an
   * CorruptionException while reading from a txn id, it means that it has more transactions, but
   * can't find any from fromTxId. If this is the case and no other journal has transactions, we
   * should throw an exception as it means more transactions exist, we just can't load them.
   *
   * @param fromTxnId Transaction id to start from.
   * @return A edit log input stream with tranactions fromTxId or null if no more exist
   */
  @Override
  public EditLogInputStream getInputStream(long fromTxnId) throws IOException {
    JournalManager bestjm = null;
    long bestjmNumTxns = 0;
    CorruptionException corruption = null;

    for (JournalAndStream jas : journals) {
      JournalManager candidate = jas.getManager();
      long candidateNumTxns = 0;
      try {
        candidateNumTxns = candidate.getNumberOfTransactions(fromTxnId);
      } catch (CorruptionException ce) {
        corruption = ce;
      } catch (IOException ioe) {
        continue; // error reading disk, just skip
      }

      if (candidateNumTxns > bestjmNumTxns) {
        bestjm = candidate;
        bestjmNumTxns = candidateNumTxns;
      }
    }

    if (bestjm == null) {
      if (corruption != null) {
        throw new IOException("No non-corrupt logs for txid " + fromTxnId, corruption);
      } else {
        return null;
      }
    }
    return bestjm.getInputStream(fromTxnId);
  }
Exemple #2
0
 List<JournalManager> getJournalManagers() {
   List<JournalManager> jList = new ArrayList<JournalManager>();
   for (JournalAndStream j : journals) {
     jList.add(j.getManager());
   }
   return jList;
 }
Exemple #3
0
 /**
  * Returns true if there are no journals or all are disabled.
  *
  * @return True if no journals or all are disabled.
  */
 public boolean isEmpty() {
   for (JournalAndStream jas : journals) {
     if (!jas.isDisabled()) {
       return false;
     }
   }
   return true;
 }
Exemple #4
0
  /**
   * Return a manifest of what finalized edit logs are available. All available edit logs are
   * returned starting from the transaction id passed.
   *
   * @param fromTxId Starting transaction id to read the logs.
   * @return RemoteEditLogManifest object.
   */
  public synchronized RemoteEditLogManifest getEditLogManifest(long fromTxId) {
    // Collect RemoteEditLogs available from each FileJournalManager
    List<RemoteEditLog> allLogs = Lists.newArrayList();
    for (JournalAndStream j : journals) {
      if (j.getManager() instanceof FileJournalManager) {
        FileJournalManager fjm = (FileJournalManager) j.getManager();
        try {
          allLogs.addAll(fjm.getRemoteEditLogs(fromTxId));
        } catch (Throwable t) {
          LOG.warn("Cannot list edit logs in " + fjm, t);
        }
      }
    }

    // Group logs by their starting txid
    ImmutableListMultimap<Long, RemoteEditLog> logsByStartTxId =
        Multimaps.index(allLogs, RemoteEditLog.GET_START_TXID);
    long curStartTxId = fromTxId;

    List<RemoteEditLog> logs = Lists.newArrayList();
    while (true) {
      ImmutableList<RemoteEditLog> logGroup = logsByStartTxId.get(curStartTxId);
      if (logGroup.isEmpty()) {
        // we have a gap in logs - for example because we recovered some old
        // storage directory with ancient logs. Clear out any logs we've
        // accumulated so far, and then skip to the next segment of logs
        // after the gap.
        SortedSet<Long> startTxIds = Sets.newTreeSet(logsByStartTxId.keySet());
        startTxIds = startTxIds.tailSet(curStartTxId);
        if (startTxIds.isEmpty()) {
          break;
        } else {
          if (LOG.isDebugEnabled()) {
            LOG.debug(
                "Found gap in logs at "
                    + curStartTxId
                    + ": "
                    + "not returning previous logs in manifest.");
          }
          logs.clear();
          curStartTxId = startTxIds.first();
          continue;
        }
      }

      // Find the one that extends the farthest forward
      RemoteEditLog bestLog = Collections.max(logGroup);
      logs.add(bestLog);
      // And then start looking from after that point
      curStartTxId = bestLog.getEndTxId() + 1;
    }
    RemoteEditLogManifest ret = new RemoteEditLogManifest(logs);

    if (LOG.isDebugEnabled()) {
      LOG.debug("Generated manifest for logs since " + fromTxId + ":" + ret);
    }
    return ret;
  }
Exemple #5
0
 @Override
 protected long getNumSync() {
   for (JournalAndStream jas : journals) {
     if (jas.isActive()) {
       return jas.getCurrentStream().getNumSync();
     }
   }
   return 0;
 }
Exemple #6
0
 @Override
 public boolean shouldForceSync() {
   for (JournalAndStream js : journals) {
     if (js.isActive() && js.getCurrentStream().shouldForceSync()) {
       return true;
     }
   }
   return false;
 }
Exemple #7
0
 /** Add sync times to the buffer. */
 String getSyncTimes() {
   StringBuilder buf = new StringBuilder();
   for (JournalAndStream jas : journals) {
     if (jas.isActive()) {
       buf.append(jas.getCurrentStream().getTotalSyncTime());
       buf.append(" ");
     }
   }
   return buf.toString();
 }
Exemple #8
0
  /** Called when some journals experience an error in some operation. */
  private void disableAndReportErrorOnJournals(List<JournalAndStream> badJournals) {
    if (badJournals == null || badJournals.isEmpty()) {
      return; // nothing to do
    }

    for (JournalAndStream j : badJournals) {
      LOG.error("Disabling journal " + j);
      j.abort();
      j.setDisabled(true);
    }
  }
Exemple #9
0
 void remove(JournalManager j) {
   JournalAndStream jasToRemove = null;
   for (JournalAndStream jas : journals) {
     if (jas.getManager().equals(j)) {
       jasToRemove = jas;
       break;
     }
   }
   if (jasToRemove != null) {
     jasToRemove.abort();
     journals.remove(jasToRemove);
   }
 }
Exemple #10
0
 @Override
 public long getNumberOfTransactions(long fromTxnId) throws IOException {
   long num = 0;
   for (JournalAndStream jas : journals) {
     if (jas.isActive()) {
       long newNum = jas.getManager().getNumberOfTransactions(fromTxnId);
       if (newNum > num) {
         num = newNum;
       }
     }
   }
   return num;
 }