Skip to content

Commit 73be375

Browse files
IDataHolder: Rewrote to support sandboxing. Cleaned up and added handy dictionary-like functions.
NodeDataStorage: New storage location per node for custom data, resolver types, and, eventually, object types. Transport: More progress
1 parent e444864 commit 73be375

File tree

5 files changed

+231
-144
lines changed

5 files changed

+231
-144
lines changed

Source/Data/IDataHolder.cs

Lines changed: 27 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
/// Author: Maverick Liberty
55
///////////////////////////////////////////////////////
66

7-
using System;
8-
using System.Collections.Generic;
97
using System.Diagnostics.CodeAnalysis;
10-
using System.Runtime.CompilerServices;
8+
using EppNet.Node;
119

1210
namespace EppNet.Data
1311
{
@@ -17,161 +15,51 @@ namespace EppNet.Data
1715
/// specific instance
1816
/// </summary>
1917

20-
public interface IDataHolder : IDisposable
18+
public interface IDataHolder : INodeDescendant
2119
{
22-
/// <summary>
23-
/// Global data dictionary. I considered using something with weak references but those
24-
/// just hide poor memory management.
25-
/// <br></br>Just make sure you call dispose!
26-
/// </summary>
27-
internal static readonly ConditionalWeakTable<IDataHolder, Dictionary<string, object>> _globalDataDict = new();
28-
29-
/// <summary>
30-
/// Tries to get all data associated with a particular <see cref="IDataHolder"/><br></br>
31-
/// </summary>
32-
/// <param name="dataHolder"></param>
33-
/// <returns>Whether or not an internal dictionary was cleared<br>
34-
/// </br><b>NOTE:</b> Returns false if no custom data was set.</returns>
35-
36-
public static bool DeleteAllData([NotNull] IDataHolder dataHolder)
37-
{
38-
if (dataHolder == null)
39-
return false;
4020

41-
return _globalDataDict.Remove(dataHolder);
42-
}
21+
public bool Set<T>([NotNull] string key, T value) =>
22+
Node.DataStorage.AddOrUpdateCustomDataEntry(this, key, value);
4323

44-
/// <summary>
45-
/// Tries to associate a value with a key<br/>
46-
/// Key mustn't be null or empty.<br></br>
47-
/// <b>NOTE:</b> Uses <see cref="GetOrCreateData"/>, so will only fail for invalid keys
48-
/// </summary>
49-
/// <param name="key"></param>
50-
/// <param name="value"></param>
51-
/// <returns>Whether or not the key was set to the value</returns>
52-
/// <exception cref="ArgumentException">Key cannot be empty or null</exception>
53-
54-
public bool Set(string key, object value)
24+
public bool SetIfAbsent<T>([NotNull] string key, T value)
5525
{
56-
var data = GetOrCreateData();
57-
58-
if (string.IsNullOrEmpty(key))
59-
throw new ArgumentException("Key cannot be empty or null!");
26+
if (!Has(key))
27+
return Set(key, value);
6028

61-
if (TryGetValue(key, out object existing) && existing == value)
62-
// Data is already set
63-
return false;
64-
65-
data[key] = value;
66-
return true;
29+
return false;
6730
}
6831

69-
/// <summary>
70-
/// Fetches a value by the key without any checks<br/>
71-
/// Can result in an error if the key doesn't exist.
72-
/// </summary>
73-
/// <param name="key"></param>
74-
/// <exception cref="KeyNotFoundException">The specified key could not be found</exception>
75-
/// <returns></returns>
76-
77-
public object Get(string key) => GetOrCreateData()[key];
78-
79-
/// <summary>
80-
/// Tries to remove the specified key from the internal data dictionary
81-
/// </summary>
82-
/// <param name="key"></param>
83-
/// <returns>Whether or not it was deleted</returns>
84-
85-
public bool Remove(string key) => GetOrCreateData().Remove(key);
86-
87-
/// <summary>
88-
/// Tries to get an object by key
89-
/// </summary>
90-
/// <param name="key"></param>
91-
/// <param name="value"></param>
92-
/// <returns>Whether or not the key was valid</returns>
93-
94-
public bool TryGetValue(string key, out object value)
95-
{
96-
value = null;
97-
98-
var data = GetOrCreateData();
32+
public T Get<T>([NotNull] string key) =>
33+
(T)Node.DataStorage.GetCustomDataEntry(this, key);
9934

100-
if (data == null)
101-
return false;
35+
public object Get([NotNull] string key) =>
36+
Node.DataStorage.GetCustomDataEntry(this, key);
10237

103-
return data.TryGetValue(key, out value);
104-
}
38+
public T GetOrDefault<T>([NotNull] string key, T fallback) =>
39+
TryGet(key, out T result) ? result : fallback;
10540

106-
/// <summary>
107-
/// Gets or creates an internal dictionary for data holding
108-
/// </summary>
109-
/// <returns>A dictionary</returns>
110-
111-
public Dictionary<string, object> GetOrCreateData()
41+
public bool TryGet<T>([NotNull] string key, out T value)
11242
{
43+
bool fetched = Node.DataStorage.TryGetCustomDataEntry(this, key, out object obj);
44+
value = default;
11345

114-
Dictionary<string, object> data;
115-
116-
if (!_globalDataDict.TryGetValue(this, out data))
46+
if (fetched && obj is T casted)
11747
{
118-
data = new(StringComparer.Ordinal);
119-
_globalDataDict.Add(this, data);
48+
value = casted;
49+
return true;
12050
}
12151

122-
return data;
52+
return false;
12353
}
12454

125-
}
126-
127-
public static class IDataHolderExtensions
128-
{
55+
public bool TryGet([NotNull] string key, out object value) =>
56+
Node.DataStorage.TryGetCustomDataEntry(this, key, out value);
12957

130-
/// <summary>
131-
/// Tries to associate a value with a key<br/>
132-
/// Key mustn't be null or empty.<br></br>
133-
/// <b>NOTE:</b> Uses <see cref="GetOrCreateData"/>, so will only fail for invalid keys
134-
/// </summary>
135-
/// <param name="key"></param>
136-
/// <param name="value"></param>
137-
/// <returns>Whether or not the key was set to the value</returns>
138-
/// <exception cref="ArgumentException">Key cannot be empty or null</exception>
139-
public static bool Set<T>(this T holder, string key, object value) where T : IDataHolder => holder.Set(key, value);
140-
141-
/// <summary>
142-
/// Fetches a value by the key without any checks<br/>
143-
/// Can result in an error if the key doesn't exist.
144-
/// </summary>
145-
/// <param name="key"></param>
146-
/// <exception cref="KeyNotFoundException">The specified key could not be found</exception>
147-
/// <returns></returns>
148-
public static object Get<T>(this T holder, string key) where T : IDataHolder => holder.Get(key);
149-
150-
/// <summary>
151-
/// Tries to remove the specified key from the internal data dictionary
152-
/// </summary>
153-
/// <param name="key"></param>
154-
/// <returns>Whether or not it was deleted</returns>
155-
156-
public static bool Remove<T>(this T holder, string key) where T : IDataHolder => holder.Remove(key);
157-
158-
/// <summary>
159-
/// Tries to get an object by key
160-
/// </summary>
161-
/// <param name="key"></param>
162-
/// <param name="value"></param>
163-
/// <returns>Whether or not the key was valid</returns>
164-
165-
public static bool TryGetValue<T>(this T holder, string key, out object value) where T : IDataHolder => holder.TryGetValue(key, out value);
166-
167-
/// <summary>
168-
/// Gets or creates an internal dictionary for data holding
169-
/// </summary>
170-
/// <returns>A dictionary</returns>
171-
172-
public static Dictionary<string, object> GetOrCreateData<T>(this T holder) where T : IDataHolder => holder.GetOrCreateData();
58+
public bool Remove([NotNull] string key, out object value) =>
59+
Node.DataStorage.RemoveCustomDataEntry(this, key, out value);
17360

61+
public bool Has([NotNull] string key) =>
62+
Node.DataStorage.TryGetCustomDataEntry(this, key, out _);
17463

17564
}
176-
17765
}

Source/Node/NetworkNode.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ public Timestamp Timestamp
111111

112112
public Configuration Configuration { get; }
113113

114+
public NodeDataStorage DataStorage { get; }
115+
114116
internal ServiceManager _serviceMgr;
115117
internal BaseSocket _socket;
116118

0 commit comments

Comments
 (0)