void REPL(UI ui) { Ui = ui; string command = string.Empty; do { ui.Write("ll > "); command = (ui.ReadLine() ?? "exit").Trim(); if (command.Equals("pause") || command.Equals("p")) { Pause(); } else if (command.Equals("resume") || command.Equals("r")) { Resume(); } else if (command.Equals("stats")) { FileStats(); } else if (command.Equals("split")) { FileSplit(); } else if (command.Equals("test")) { var activities = LivingFile.ReadActivities("C:\\Users\\scorder\\Documents\\living-log.2015-04.log"); ActivityTools.Process(activities); } } while (!command.Equals("exit")); Program.ForceExit(); }
void FileStats() { if (LivingFile.Exists(m_filename)) { var stats = LivingFile.GetStats(m_filename); Ui.WriteLine("File " + m_filename + " has " + Tools.ToHumanString(stats.Length) + " bytes"); Ui.WriteLine("File " + m_filename + " has " + Tools.ToHumanString(stats.Count) + " lines"); } }
void FileSplit() { if (Enabled) { Ui.WriteLine("Cannot split while logging. Please pause."); } else { if (LivingFile.Exists(m_filename)) { Dump(); var info = LivingFile.GetInfo(m_filename); Ui.WriteLine("Files of names " + info.BaseName + ".YYYY-MM" + info.Extension + " will be generated"); System.Diagnostics.Stopwatch w = new System.Diagnostics.Stopwatch(); long counter = 0; var logger = new System.Timers.Timer(); logger.AutoReset = true; logger.Interval = Constants.Second; logger.Elapsed += (s, e) => { Ui.SetStatus("activities: " + Tools.ToHumanString(counter).PadRight(8) + " elapsed: " + w.Elapsed.ToString()); }; logger.Start(); var backups = new Dictionary <string, string>(); try { w.Start(); var activities = LivingFile.ReadActivities(m_filename) .Do(() => ++ counter); foreach (var activityBlock in activities.PartitionBlocks(Constants.ReadingBlockSize)) { var groups = activityBlock .GroupBy((a) => { var at = a.Timestamp.ToDateTime(); return(new { Year = at.Year, Month = at.Month }); }); foreach (var group in groups) { if (group.Any()) { IEnumerable <Activity> groupActivities; var item = group.First(); if (!Categories.IsSync(item.Type)) { // When appending activities, always start with a sync activity // This will help "resorting" activities if needed groupActivities = Enumerable.Repeat(LivingLogger.GetSync(item.Timestamp), 1).Concat(group); } else { groupActivities = group; } lock (locker) { var filename = info.Child(group.Key.Year, group.Key.Month); var backup = filename + ".bak"; if (!backups.ContainsKey(filename)) { if (File.Exists(filename)) { if (File.Exists(backup)) { File.Delete(backup); } File.Copy(filename, backup); } backups.Add(filename, backup); Ui.WriteLine("Writing to " + filename); } Timestamp previous = groupActivities.First().Timestamp; using (var writer = new StreamWriter(File.Open(filename, FileMode.Append))) { foreach (var groupActivityBlock in groupActivities.PartitionBlocks(Constants.WritingBlockSize)) { WriteText(groupActivityBlock, ref previous, writer); } } } } } } Ui.SetStatus("Split task successful."); foreach (var kvp in backups) { counter = 0; w.Restart(); Ui.WriteLine("Processing " + kvp.Key); if (File.Exists(kvp.Value)) { File.Delete(kvp.Value); } if (File.Exists(kvp.Key)) { File.Copy(kvp.Key, kvp.Value); } var processed = ActivityTools.Process( LivingFile .ReadActivities(kvp.Value) .Do(() => ++ counter) ); Timestamp previous = processed.First().Timestamp; using (var writer = new StreamWriter(File.Create(kvp.Key))) { foreach (var pBlock in processed.PartitionBlocks(Constants.WritingBlockSize)) { WriteText(pBlock, ref previous, writer); } } } foreach (var kvp in backups) { if (File.Exists(kvp.Value)) { File.Delete(kvp.Value); } } using (var file = File.Create(m_filename)) { // "using" makes sura that the file is properly closed and not still in use } Ui.SetStatus("Processing task successful."); } catch (Exception e) { Ui.SetStatus("Error during split task. Removing temporary files..."); foreach (var kvp in backups) { if (File.Exists(kvp.Key)) { File.Delete(kvp.Key); } if (File.Exists(kvp.Value)) { File.Move(kvp.Value, kvp.Key); } } } finally { logger.Stop(); } } } }