Browse Source

Moved the file information into a parameter to IConfigProvider's methods

pull/46/head
Anairkoen Schno 4 years ago
parent
commit
656d9f27a1
6 changed files with 62 additions and 50 deletions
  1. +5
    -3
      IPA.Loader/Config/Config.cs
  2. +9
    -15
      IPA.Loader/Config/ConfigRuntime.cs
  3. +28
    -13
      IPA.Loader/Config/IConfigProvider.cs
  4. +2
    -2
      IPA.Loader/Config/IConfigStore.cs
  5. +14
    -13
      IPA.Loader/Config/Providers/JsonConfigProvider.cs
  6. +4
    -4
      IPA.Loader/Config/Stores/GeneratedStore.cs

+ 5
- 3
IPA.Loader/Config/Config.cs View File

@ -131,14 +131,15 @@ namespace IPA.Config
/// <summary> /// <summary>
/// Gets the name associated with this <see cref="Config"/> object. /// Gets the name associated with this <see cref="Config"/> object.
/// </summary> /// </summary>
public string Name { get; private set; }
public string Name { get; }
/// <summary> /// <summary>
/// Gets the <see cref="IConfigProvider"/> associated with this <see cref="Config"/> object. /// Gets the <see cref="IConfigProvider"/> associated with this <see cref="Config"/> object.
/// </summary> /// </summary>
public IConfigProvider Provider { get; private set; }
public IConfigProvider Provider { get; }
internal IConfigStore Store = null; internal IConfigStore Store = null;
internal readonly FileInfo File; internal readonly FileInfo File;
internal readonly ConfigProvider configProvider;
internal int Writes = 0; internal int Writes = 0;
/// <summary> /// <summary>
@ -166,7 +167,8 @@ namespace IPA.Config
private Config(string name, IConfigProvider provider, FileInfo file) private Config(string name, IConfigProvider provider, FileInfo file)
{ {
Name = name; Provider = provider; File = file;
Name = name; Provider = provider; File = file;
configProvider = new ConfigProvider(file, provider);
} }
} }
} }

+ 9
- 15
IPA.Loader/Config/ConfigRuntime.cs View File

@ -151,10 +151,11 @@ namespace IPA.Config
} }
} }
public static Task TriggerFileLoad(Config config) => loadFactory.StartNew(() => LoadTask(config));
public static Task TriggerFileLoad(Config config)
=> loadFactory.StartNew(() => LoadTask(config));
public static Task TriggerLoadAll() =>
TaskEx.WhenAll(configs.Select(TriggerFileLoad));
public static Task TriggerLoadAll()
=> TaskEx.WhenAll(configs.Select(TriggerFileLoad));
/// <summary> /// <summary>
/// this is synchronous, unlike <see cref="TriggerFileLoad(Config)"/> /// this is synchronous, unlike <see cref="TriggerFileLoad(Config)"/>
@ -167,13 +168,10 @@ namespace IPA.Config
try try
{ {
using var readLock = Synchronization.LockRead(store.WriteSyncObject); using var readLock = Synchronization.LockRead(store.WriteSyncObject);
lock (config.Provider)
{
config.Provider.File = config.File;
EnsureWritesSane(config);
Interlocked.Increment(ref config.Writes);
store.WriteTo(config.Provider);
}
EnsureWritesSane(config);
Interlocked.Increment(ref config.Writes);
store.WriteTo(config.configProvider);
} }
catch (ThreadAbortException) catch (ThreadAbortException)
{ {
@ -201,11 +199,7 @@ namespace IPA.Config
{ {
var store = config.Store; var store = config.Store;
using var writeLock = Synchronization.LockWrite(store.WriteSyncObject); using var writeLock = Synchronization.LockWrite(store.WriteSyncObject);
lock (config.Provider)
{
config.Provider.File = config.File;
store.ReadFrom(config.Provider);
}
store.ReadFrom(config.configProvider);
} }
catch (Exception e) catch (Exception e)
{ {


+ 28
- 13
IPA.Loader/Config/IConfigProvider.cs View File

@ -1,5 +1,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading.Tasks;
using IPA.Config.Data; using IPA.Config.Data;
namespace IPA.Config namespace IPA.Config
@ -32,30 +33,44 @@ namespace IPA.Config
string Extension { get; } string Extension { get; }
/// <summary> /// <summary>
/// Sets the file that this provider will read and write to.
/// Stores the <see cref="Value"/> given to disk in the format specified.
/// </summary> /// </summary>
/// <remarks>
/// The provider is expected to gracefully handle this changing at any point,
/// and is expected to close any old file handles when this is reassigned.
/// This may be set to the same file multiple times in this object's lifetime.
/// This will always have been set at least once before any calls to <see cref="Load"/>
/// or <see cref="Store"/> are made.
/// </remarks>
FileInfo File { set; }
/// <param name="value">the <see cref="Value"/> to store</param>
/// <param name="file">the file to write to</param>
void Store(Value value, FileInfo file);
/// <summary>
/// Loads a <see cref="Value"/> from disk in whatever format this provider provides
/// and returns it.
/// </summary>
/// <param name="file">the file to read from</param>
/// <returns>the <see cref="Value"/> loaded</returns>
Value Load(FileInfo file);
}
/// <summary>
/// A wrapper for an <see cref="IConfigProvider"/> and the <see cref="FileInfo"/> to use with it.
/// </summary>
public class ConfigProvider // this *should* be a struct imo, but mono doesn't seem to like that
{
private readonly FileInfo file;
private readonly IConfigProvider provider;
// TODO: consider moving to asynchronous Store and Load with a FileInfo parameter
internal ConfigProvider(FileInfo file, IConfigProvider provider)
{
this.file = file; this.provider = provider;
}
/// <summary> /// <summary>
/// Stores the <see cref="Value"/> given to disk in the format specified. /// Stores the <see cref="Value"/> given to disk in the format specified.
/// </summary> /// </summary>
/// <param name="value">the <see cref="Value"/> to store</param> /// <param name="value">the <see cref="Value"/> to store</param>
void Store(Value value);
public void Store(Value value) => provider.Store(value, file);
/// <summary> /// <summary>
/// Loads a <see cref="Value"/> from disk in whatever format this provider provides /// Loads a <see cref="Value"/> from disk in whatever format this provider provides
/// and returns it. /// and returns it.
/// </summary> /// </summary>
/// <returns>the <see cref="Value"/> loaded</returns> /// <returns>the <see cref="Value"/> loaded</returns>
Value Load();
public Value Load() => provider.Load(file);
} }
} }

+ 2
- 2
IPA.Loader/Config/IConfigStore.cs View File

@ -40,7 +40,7 @@ namespace IPA.Config
/// this is called. /// this is called.
/// </remarks> /// </remarks>
/// <param name="provider">the provider to write to</param> /// <param name="provider">the provider to write to</param>
void WriteTo(IConfigProvider provider);
void WriteTo(ConfigProvider provider);
/// <summary> /// <summary>
/// Reads the config structure from the given <see cref="IConfigProvider"/> into the current /// Reads the config structure from the given <see cref="IConfigProvider"/> into the current
@ -51,7 +51,7 @@ namespace IPA.Config
/// this is called. /// this is called.
/// </remarks> /// </remarks>
/// <param name="provider">the provider to read from</param> /// <param name="provider">the provider to read from</param>
void ReadFrom(IConfigProvider provider);
void ReadFrom(ConfigProvider provider);
} }
} }

+ 14
- 13
IPA.Loader/Config/Providers/JsonConfigProvider.cs View File

@ -9,6 +9,7 @@ using System.ComponentModel;
using System.IO; using System.IO;
using System.Collections.Generic; using System.Collections.Generic;
using Boolean = IPA.Config.Data.Boolean; using Boolean = IPA.Config.Data.Boolean;
using System.Threading.Tasks;
namespace IPA.Config.Providers namespace IPA.Config.Providers
{ {
@ -21,14 +22,12 @@ namespace IPA.Config.Providers
public string Extension => "json"; public string Extension => "json";
public FileInfo File { get; set; }
public Value Load()
public Value Load(FileInfo file)
{ {
if (!File.Exists) return Value.Null();
if (!file.Exists) return Value.Null();
JToken jtok; JToken jtok;
using (var sreader = new StreamReader(File.OpenRead()))
using (var sreader = new StreamReader(file.OpenRead()))
{ {
using var jreader = new JsonTextReader(sreader); using var jreader = new JsonTextReader(sreader);
jtok = JToken.ReadFrom(jreader); jtok = JToken.ReadFrom(jreader);
@ -40,7 +39,7 @@ namespace IPA.Config.Providers
} }
catch (Exception e) catch (Exception e)
{ {
Logger.config.Error($"Error reading JSON file {File.FullName}; ignoring");
Logger.config.Error($"Error reading JSON file {file.FullName}; ignoring");
Logger.config.Error(e); Logger.config.Error(e);
return Value.Null(); return Value.Null();
} }
@ -116,23 +115,25 @@ namespace IPA.Config.Providers
} }
} }
public void Store(Value value)
public void Store(Value value, FileInfo file)
{ {
if (File.Directory.Exists)
File.Directory.Create();
if (file.Directory.Exists)
file.Directory.Create();
try try
{ {
var tok = VisitToToken(value); var tok = VisitToToken(value);
using var swriter = new StreamWriter(File.Open(FileMode.Create, FileAccess.Write));
using var jwriter = new JsonTextWriter(swriter);
jwriter.Formatting = Formatting.Indented;
using var swriter = new StreamWriter(file.Open(FileMode.Create, FileAccess.Write));
using var jwriter = new JsonTextWriter(swriter)
{
Formatting = Formatting.Indented
};
tok.WriteTo(jwriter); tok.WriteTo(jwriter);
} }
catch (Exception e) catch (Exception e)
{ {
Logger.config.Error($"Error serializing value for {File.FullName}");
Logger.config.Error($"Error serializing value for {file.FullName}");
Logger.config.Error(e); Logger.config.Error(e);
} }
} }


+ 4
- 4
IPA.Loader/Config/Stores/GeneratedStore.cs View File

@ -155,7 +155,7 @@ namespace IPA.Config.Stores
internal static MethodInfo ReadFromMethod = typeof(Impl).GetMethod(nameof(ReadFrom)); internal static MethodInfo ReadFromMethod = typeof(Impl).GetMethod(nameof(ReadFrom));
public void ReadFrom(IConfigProvider provider)
public void ReadFrom(ConfigProvider provider)
{ {
var values = provider.Load(); var values = provider.Load();
Logger.config.Debug("Generated impl ReadFrom"); Logger.config.Debug("Generated impl ReadFrom");
@ -168,7 +168,7 @@ namespace IPA.Config.Stores
} }
internal static MethodInfo WriteToMethod = typeof(Impl).GetMethod(nameof(WriteTo)); internal static MethodInfo WriteToMethod = typeof(Impl).GetMethod(nameof(WriteTo));
public void WriteTo(IConfigProvider provider)
public void WriteTo(ConfigProvider provider)
{ {
var values = generated.Serialize(); var values = generated.Serialize();
Logger.config.Debug("Generated impl WriteTo"); Logger.config.Debug("Generated impl WriteTo");
@ -714,7 +714,7 @@ namespace IPA.Config.Stores
} }
#endregion #endregion
#region IConfigStore.WriteTo #region IConfigStore.WriteTo
var writeTo = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.WriteTo)}", virtualMemberMethod, null, new[] { typeof(IConfigProvider) });
var writeTo = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.WriteTo)}", virtualMemberMethod, null, new[] { typeof(ConfigProvider) });
typeBuilder.DefineMethodOverride(writeTo, IConfigStore_WriteTo); typeBuilder.DefineMethodOverride(writeTo, IConfigStore_WriteTo);
{ {
@ -729,7 +729,7 @@ namespace IPA.Config.Stores
} }
#endregion #endregion
#region IConfigStore.ReadFrom #region IConfigStore.ReadFrom
var readFrom = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.ReadFrom)}", virtualMemberMethod, null, new[] { typeof(IConfigProvider) });
var readFrom = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.ReadFrom)}", virtualMemberMethod, null, new[] { typeof(ConfigProvider) });
typeBuilder.DefineMethodOverride(readFrom, IConfigStore_ReadFrom); typeBuilder.DefineMethodOverride(readFrom, IConfigStore_ReadFrom);
{ {


Loading…
Cancel
Save