/// <summary>Return a manifest of what finalized edit logs are available.</summary> /// <remarks> /// Return a manifest of what finalized edit logs are available. All available /// edit logs are returned starting from the transaction id passed. If /// 'fromTxId' falls in the middle of a log, that log is returned as well. /// </remarks> /// <param name="fromTxId">Starting transaction id to read the logs.</param> /// <returns>RemoteEditLogManifest object.</returns> public virtual RemoteEditLogManifest GetEditLogManifest(long fromTxId) { lock (this) { // Collect RemoteEditLogs available from each FileJournalManager IList <RemoteEditLog> allLogs = Lists.NewArrayList(); foreach (JournalSet.JournalAndStream j in journals) { if (j.GetManager() is FileJournalManager) { FileJournalManager fjm = (FileJournalManager)j.GetManager(); try { Sharpen.Collections.AddAll(allLogs, fjm.GetRemoteEditLogs(fromTxId, false)); } catch (Exception t) { Log.Warn("Cannot list edit logs in " + fjm, t); } } } // Group logs by their starting txid ImmutableListMultimap <long, RemoteEditLog> logsByStartTxId = Multimaps.Index(allLogs , RemoteEditLog.GetStartTxid); long curStartTxId = fromTxId; IList <RemoteEditLog> logs = Lists.NewArrayList(); while (true) { ImmutableList <RemoteEditLog> logGroup = ((ImmutableList <RemoteEditLog>)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. ICollection <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 = Sharpen.Collections.Max(logGroup); logs.AddItem(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); } }
/// <exception cref="System.IO.IOException"/> private static string GetLogsAsString(FileJournalManager fjm, long firstTxId) { return(Joiner.On(",").Join(fjm.GetRemoteEditLogs(firstTxId, false))); }