From a8409a9c86eb37dae636b6cc13714d4234a1f1d7 Mon Sep 17 00:00:00 2001 From: adelikat Date: Tue, 15 Sep 2015 20:03:50 -0400 Subject: [PATCH] TasStateManager - some cleanup --- .../BizHawk.Client.Common.csproj | 1 + .../movie/tasproj/StateManagerState.cs | 97 +++++++++++ .../movie/tasproj/TasStateManager.cs | 155 ++++++------------ 3 files changed, 147 insertions(+), 106 deletions(-) create mode 100644 BizHawk.Client.Common/movie/tasproj/StateManagerState.cs diff --git a/BizHawk.Client.Common/BizHawk.Client.Common.csproj b/BizHawk.Client.Common/BizHawk.Client.Common.csproj index 4043a9589a..9817297aa8 100644 --- a/BizHawk.Client.Common/BizHawk.Client.Common.csproj +++ b/BizHawk.Client.Common/BizHawk.Client.Common.csproj @@ -158,6 +158,7 @@ Bk2Movie.cs + diff --git a/BizHawk.Client.Common/movie/tasproj/StateManagerState.cs b/BizHawk.Client.Common/movie/tasproj/StateManagerState.cs new file mode 100644 index 0000000000..c4012ac9d7 --- /dev/null +++ b/BizHawk.Client.Common/movie/tasproj/StateManagerState.cs @@ -0,0 +1,97 @@ +using System; + +namespace BizHawk.Client.Common +{ + /// + /// Represents a savestate in the TasStateManager + /// + internal class StateManagerState : IDisposable + { + private static long _stateId = 0; + private TasStateManager _manager; + + private byte[] _state; + private long _id; + + public int Frame { get; set; } + + public byte[] State + { + get + { + if (_state != null) + { + return _state; + } + + return _manager.ndbdatabase.FetchAll(_id.ToString()); + } + set + { + if (_state != null) + { + _state = value; + } + else + { + throw new Exception("Attempted to set a state to null."); + } + } + } + + public int Length + { + get { return State.Length; } + } + + public bool IsOnDisk + { + get { return _state == null; } + } + + public StateManagerState(TasStateManager manager, byte[] state, int frame) + { + _manager = manager; + _state = state; + Frame = frame; + + if (_stateId > long.MaxValue - 100) + { + throw new InvalidOperationException(); + } + + _id = System.Threading.Interlocked.Increment(ref _stateId); + } + + public void MoveToDisk() + { + if (IsOnDisk) + { + return; + } + + _manager.ndbdatabase.Store(_id.ToString(), _state, 0, _state.Length); + _state = null; + } + + public void MoveToRAM() + { + if (!IsOnDisk) + { + return; + } + + string key = _id.ToString(); + _state = _manager.ndbdatabase.FetchAll(key); + _manager.ndbdatabase.Release(key); + } + + public void Dispose() + { + if (!IsOnDisk) + return; + + _manager.ndbdatabase.Release(_id.ToString()); + } + } +} diff --git a/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs b/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs index 81ce1929e9..aa402e23e7 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs @@ -1,85 +1,15 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.IO; using System.Linq; -using System.Text; using System.Drawing; using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Common.IEmulatorExtensions; -using stateKVP = System.Collections.Generic.KeyValuePair; - namespace BizHawk.Client.Common { - class tsmState : IDisposable - { - static long state_id = 0; - TasStateManager _manager; - - byte[] _state; - long ID; - public int Frame; - - public tsmState(TasStateManager manager, byte[] state, int frame) - { - _manager = manager; - _state = state; - Frame = frame; - - if (state_id > long.MaxValue - 100) - throw new InvalidOperationException(); - ID = System.Threading.Interlocked.Increment(ref state_id); - } - - public byte[] State - { - get - { - if (_state != null) - return _state; - - return _manager.ndbdatabase.FetchAll(ID.ToString()); - } - set - { - if (_state != null) - _state = value; - else - throw new Exception("Attempted to set a state to null."); - } - } - public int Length { get { return State.Length; } } - - public bool IsOnDisk { get { return _state == null; } } - public void MoveToDisk() - { - if (IsOnDisk) - return; - - _manager.ndbdatabase.Store(ID.ToString(), _state, 0, _state.Length); - _state = null; - } - public void MoveToRAM() - { - if (!IsOnDisk) - return; - - string key = ID.ToString(); - _state = _manager.ndbdatabase.FetchAll(key); - _manager.ndbdatabase.Release(key); - } - public void Dispose() - { - if (!IsOnDisk) - return; - - _manager.ndbdatabase.Release(ID.ToString()); - } - } - /// /// Captures savestates and manages the logic of adding, retrieving, /// invalidating/clearing of states. Also does memory management and limiting of states @@ -105,9 +35,10 @@ namespace BizHawk.Client.Common } } + private List lowPriorityStates = new List(); internal NDBDatabase ndbdatabase; private Guid guid = Guid.NewGuid(); - private SortedList States = new SortedList(); + private SortedList States = new SortedList(); private string statePath { @@ -124,6 +55,7 @@ namespace BizHawk.Client.Common private int _minFrequency = VersionInfo.DeveloperBuild ? 2 : 1; private const int _maxFrequency = 16; + private int StateFrequency { get @@ -145,7 +77,9 @@ namespace BizHawk.Client.Common } private int maxStates - { get { return (int)(Settings.Cap / _expectedStateSize) + (int)((ulong)Settings.DiskCapacitymb * 1024 * 1024 / _expectedStateSize); } } + { + get { return (int)(Settings.Cap / _expectedStateSize) + (int)((ulong)Settings.DiskCapacitymb * 1024 * 1024 / _expectedStateSize); } + } public TasStateManager(TasMovie movie) { @@ -153,7 +87,7 @@ namespace BizHawk.Client.Common Settings = new TasStateManagerSettings(Global.Config.DefaultTasProjSettings); - accessed = new List(); + accessed = new List(); if (_movie.StartsFromSavestate) SetState(0, _movie.BinarySavestate); @@ -186,7 +120,7 @@ namespace BizHawk.Client.Common limit = maxStates; } - States = new SortedList(limit); + States = new SortedList(limit); if (_expectedStateSize > int.MaxValue) throw new InvalidOperationException(); @@ -213,7 +147,8 @@ namespace BizHawk.Client.Common return new KeyValuePair(-1, new byte[0]); } } - private List accessed; + + private List accessed; public byte[] InitialState { @@ -264,7 +199,6 @@ namespace BizHawk.Client.Common } } - private List lowPriorityStates = new List(); private void MaybeRemoveStates() { // Loop, because removing a state that has a duplicate won't save any space @@ -281,6 +215,7 @@ namespace BizHawk.Client.Common MoveStateToDisk(accessed[lastMemState].Frame); } } + /// /// X is the frame of the state, Y is the branch (-1 for current). /// @@ -336,7 +271,7 @@ namespace BizHawk.Client.Common } else { - tsmState s = States.Values[1]; + StateManagerState s = States.Values[1]; shouldRemove.X = s.Frame; shouldRemove.Y = -1; } @@ -344,6 +279,7 @@ namespace BizHawk.Client.Common return shouldRemove; } + private bool StateIsMarker(int frame, int branch) { if (frame == -1) @@ -359,6 +295,7 @@ namespace BizHawk.Client.Common return _movie.GetBranch(branch).Markers.Any(m => m.Frame + 1 == frame); } } + private bool AllLag(int from, int upTo) { if (upTo >= Global.Emulator.Frame) @@ -382,6 +319,7 @@ namespace BizHawk.Client.Common Used -= (ulong)States[index].Length; States[index].MoveToDisk(); } + private void MoveStateToMemory(int index) { States[index].MoveToRAM(); @@ -402,7 +340,7 @@ namespace BizHawk.Client.Common else { Used += (ulong)state.Length; - States.Add(frame, new tsmState(this, state, frame)); + States.Add(frame, new StateManagerState(this, state, frame)); } StateAccessed(frame); @@ -413,6 +351,7 @@ namespace BizHawk.Client.Common lowPriorityStates.Add(States[frame]); } } + private void RemoveState(int frame, int branch = -1) { if (branch == -1) @@ -420,7 +359,7 @@ namespace BizHawk.Client.Common else accessed.Remove(BranchStates[frame][branch]); - tsmState state; + StateManagerState state; bool hasDuplicate = stateHasDuplicate(frame, branch) != -2; if (branch == -1) { @@ -444,12 +383,13 @@ namespace BizHawk.Client.Common if (!hasDuplicate) lowPriorityStates.Remove(state); } + private void StateAccessed(int frame) { if (frame == 0 && _movie.StartsFromSavestate) return; - tsmState state = States[frame]; + StateManagerState state = States[frame]; bool removed = accessed.Remove(state); accessed.Add(state); @@ -488,12 +428,12 @@ namespace BizHawk.Client.Common frame = 1; } - List> statesToRemove = + List> statesToRemove = States.Where(x => x.Key >= frame).ToList(); anyInvalidated = statesToRemove.Any(); - foreach (KeyValuePair state in statesToRemove) + foreach (KeyValuePair state in statesToRemove) RemoveState(state.Key); CallInvalidateCallback(frame); @@ -513,11 +453,12 @@ namespace BizHawk.Client.Common Used = 0; clearDiskStates(); } + public void ClearStateHistory() { if (States.Any()) { - tsmState power = States.Values.FirstOrDefault(s => s.Frame == 0); + StateManagerState power = States.Values.FirstOrDefault(s => s.Frame == 0); StateAccessed(power.Frame); States.Clear(); @@ -529,6 +470,7 @@ namespace BizHawk.Client.Common clearDiskStates(); } } + private void clearDiskStates() { if (ndbdatabase != null) @@ -570,12 +512,13 @@ namespace BizHawk.Client.Common continue; StateAccessed(States.ElementAt(i).Key); - KeyValuePair kvp = States.ElementAt(i); + KeyValuePair kvp = States.ElementAt(i); bw.Write(kvp.Key); bw.Write(kvp.Value.Length); bw.Write(kvp.Value.State); } } + private List ExcludeStates() { List ret = new List(); @@ -642,11 +585,8 @@ namespace BizHawk.Client.Common // 4 bytes - length of savestate // 0 - n savestate - private ulong Used - { - get; - set; - } + private ulong Used { get; set; } + private ulong DiskUsed { get @@ -702,7 +642,7 @@ namespace BizHawk.Client.Common #region "Branches" - private SortedList> BranchStates = new SortedList>(); + private SortedList> BranchStates = new SortedList>(); //private int branches = 0; private int currentBranch = -1; @@ -712,7 +652,7 @@ namespace BizHawk.Client.Common /// Returns the ID of the branch (-1 for current) of the first match. If no match, returns -2. private int stateHasDuplicate(int frame, int branch) { - tsmState stateToMatch; + StateManagerState stateToMatch; if (branch == -1) stateToMatch = States[frame]; else @@ -732,14 +672,15 @@ namespace BizHawk.Client.Common if (i == branch) continue; - SortedList stateList = BranchStates[frame]; + SortedList stateList = BranchStates[frame]; if (stateList != null && stateList.ContainsKey(i) && stateList[i] == stateToMatch) return i; } return -2; } - private Point findState(tsmState s) + + private Point findState(StateManagerState s) { Point ret = new Point(0, -1); ret.X = s.Frame; @@ -761,14 +702,14 @@ namespace BizHawk.Client.Common // might as well just add another field to branch, like counter of added branches, and check by that int identifier = (int)_movie.GetBranch(_movie.BranchCount-1).TimeStamp.TimeOfDay.TotalSeconds; - foreach (KeyValuePair kvp in States) + foreach (KeyValuePair kvp in States) { if (!BranchStates.ContainsKey(kvp.Key)) - BranchStates.Add(kvp.Key, new SortedList()); - SortedList stateList = BranchStates[kvp.Key]; + BranchStates.Add(kvp.Key, new SortedList()); + SortedList stateList = BranchStates[kvp.Key]; if (stateList == null) // when does this happen? { - stateList = new SortedList(); + stateList = new SortedList(); BranchStates[kvp.Key] = stateList; } stateList.Add(identifier, kvp.Value); @@ -781,9 +722,9 @@ namespace BizHawk.Client.Common { int identifier = (int)_movie.GetBranch(index).TimeStamp.TimeOfDay.TotalSeconds; - foreach (KeyValuePair> kvp in BranchStates.ToList()) + foreach (KeyValuePair> kvp in BranchStates.ToList()) { - SortedList stateList = kvp.Value; + SortedList stateList = kvp.Value; if (stateList == null) continue; @@ -816,9 +757,9 @@ namespace BizHawk.Client.Common int identifier = (int)_movie.GetBranch(index).TimeStamp.TimeOfDay.TotalSeconds; // RemoveBranch - foreach (KeyValuePair> kvp in BranchStates.ToList()) + foreach (KeyValuePair> kvp in BranchStates.ToList()) { - SortedList stateList = kvp.Value; + SortedList stateList = kvp.Value; if (stateList == null) continue; @@ -835,18 +776,20 @@ namespace BizHawk.Client.Common stateList.Remove(identifier); if (stateList.Count == 0) + { BranchStates[kvp.Key] = null; + } } // AddBranch - foreach (KeyValuePair kvp in States) + foreach (KeyValuePair kvp in States) { if (!BranchStates.ContainsKey(kvp.Key)) - BranchStates.Add(kvp.Key, new SortedList()); - SortedList stateList = BranchStates[kvp.Key]; + BranchStates.Add(kvp.Key, new SortedList()); + SortedList stateList = BranchStates[kvp.Key]; if (stateList == null) { - stateList = new SortedList(); + stateList = new SortedList(); BranchStates[kvp.Key] = stateList; } stateList.Add(identifier, kvp.Value); @@ -859,7 +802,7 @@ namespace BizHawk.Client.Common { int identifier = (int)_movie.GetBranch(index).TimeStamp.TimeOfDay.TotalSeconds; Invalidate(0); // Not a good way of doing it? - foreach (KeyValuePair> kvp in BranchStates) + foreach (KeyValuePair> kvp in BranchStates) { if (kvp.Key == 0 && States.ContainsKey(0)) continue; // TODO: It might be a better idea to just not put state 0 in BranchStates.