@@ -3,9 +3,9 @@ using System; | |||
using System.Collections.Concurrent; | |||
using System.Collections.Generic; | |||
namespace Discord.Data | |||
namespace Discord | |||
{ | |||
public class DefaultDataStore : DataStore | |||
public class DataStore | |||
{ | |||
private const int CollectionConcurrencyLevel = 1; //WebSocket updater/event handler. //TODO: Needs profiling, increase to 2? | |||
private const double AverageChannelsPerGuild = 10.22; //Source: Googie2149 | |||
@@ -17,12 +17,12 @@ namespace Discord.Data | |||
private readonly ConcurrentDictionary<ulong, CachedGuild> _guilds; | |||
private readonly ConcurrentDictionary<ulong, CachedGlobalUser> _users; | |||
internal override IReadOnlyCollection<ICachedChannel> Channels => _channels.ToReadOnlyCollection(); | |||
internal override IReadOnlyCollection<CachedDMChannel> DMChannels => _dmChannels.ToReadOnlyCollection(); | |||
internal override IReadOnlyCollection<CachedGuild> Guilds => _guilds.ToReadOnlyCollection(); | |||
internal override IReadOnlyCollection<CachedGlobalUser> Users => _users.ToReadOnlyCollection(); | |||
internal IReadOnlyCollection<ICachedChannel> Channels => _channels.ToReadOnlyCollection(); | |||
internal IReadOnlyCollection<CachedDMChannel> DMChannels => _dmChannels.ToReadOnlyCollection(); | |||
internal IReadOnlyCollection<CachedGuild> Guilds => _guilds.ToReadOnlyCollection(); | |||
internal IReadOnlyCollection<CachedGlobalUser> Users => _users.ToReadOnlyCollection(); | |||
public DefaultDataStore(int guildCount, int dmChannelCount) | |||
public DataStore(int guildCount, int dmChannelCount) | |||
{ | |||
double estimatedChannelCount = guildCount * AverageChannelsPerGuild + dmChannelCount; | |||
double estimatedUsersCount = guildCount * AverageUsersPerGuild; | |||
@@ -32,18 +32,18 @@ namespace Discord.Data | |||
_users = new ConcurrentDictionary<ulong, CachedGlobalUser>(CollectionConcurrencyLevel, (int)(estimatedUsersCount * CollectionMultiplier)); | |||
} | |||
internal override ICachedChannel GetChannel(ulong id) | |||
internal ICachedChannel GetChannel(ulong id) | |||
{ | |||
ICachedChannel channel; | |||
if (_channels.TryGetValue(id, out channel)) | |||
return channel; | |||
return null; | |||
} | |||
internal override void AddChannel(ICachedChannel channel) | |||
internal void AddChannel(ICachedChannel channel) | |||
{ | |||
_channels[channel.Id] = channel; | |||
} | |||
internal override ICachedChannel RemoveChannel(ulong id) | |||
internal ICachedChannel RemoveChannel(ulong id) | |||
{ | |||
ICachedChannel channel; | |||
if (_channels.TryRemove(id, out channel)) | |||
@@ -51,19 +51,19 @@ namespace Discord.Data | |||
return null; | |||
} | |||
internal override CachedDMChannel GetDMChannel(ulong userId) | |||
internal CachedDMChannel GetDMChannel(ulong userId) | |||
{ | |||
CachedDMChannel channel; | |||
if (_dmChannels.TryGetValue(userId, out channel)) | |||
return channel; | |||
return null; | |||
} | |||
internal override void AddDMChannel(CachedDMChannel channel) | |||
internal void AddDMChannel(CachedDMChannel channel) | |||
{ | |||
_channels[channel.Id] = channel; | |||
_dmChannels[channel.Recipient.Id] = channel; | |||
} | |||
internal override CachedDMChannel RemoveDMChannel(ulong userId) | |||
internal CachedDMChannel RemoveDMChannel(ulong userId) | |||
{ | |||
CachedDMChannel channel; | |||
ICachedChannel ignored; | |||
@@ -75,18 +75,18 @@ namespace Discord.Data | |||
return null; | |||
} | |||
internal override CachedGuild GetGuild(ulong id) | |||
internal CachedGuild GetGuild(ulong id) | |||
{ | |||
CachedGuild guild; | |||
if (_guilds.TryGetValue(id, out guild)) | |||
return guild; | |||
return null; | |||
} | |||
internal override void AddGuild(CachedGuild guild) | |||
internal void AddGuild(CachedGuild guild) | |||
{ | |||
_guilds[guild.Id] = guild; | |||
} | |||
internal override CachedGuild RemoveGuild(ulong id) | |||
internal CachedGuild RemoveGuild(ulong id) | |||
{ | |||
CachedGuild guild; | |||
if (_guilds.TryRemove(id, out guild)) | |||
@@ -94,18 +94,18 @@ namespace Discord.Data | |||
return null; | |||
} | |||
internal override CachedGlobalUser GetUser(ulong id) | |||
internal CachedGlobalUser GetUser(ulong id) | |||
{ | |||
CachedGlobalUser user; | |||
if (_users.TryGetValue(id, out user)) | |||
return user; | |||
return null; | |||
} | |||
internal override CachedGlobalUser GetOrAddUser(ulong id, Func<ulong, CachedGlobalUser> userFactory) | |||
internal CachedGlobalUser GetOrAddUser(ulong id, Func<ulong, CachedGlobalUser> userFactory) | |||
{ | |||
return _users.GetOrAdd(id, userFactory); | |||
} | |||
internal override CachedGlobalUser RemoveUser(ulong id) | |||
internal CachedGlobalUser RemoveUser(ulong id) | |||
{ | |||
CachedGlobalUser user; | |||
if (_users.TryRemove(id, out user)) |
@@ -1,4 +0,0 @@ | |||
namespace Discord.Data | |||
{ | |||
public delegate DataStore DataStoreProvider(int shardId, int totalShards, int guildCount, int dmCount); | |||
} |
@@ -1,29 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
namespace Discord.Data | |||
{ | |||
public abstract class DataStore | |||
{ | |||
internal abstract IReadOnlyCollection<ICachedChannel> Channels { get; } | |||
internal abstract IReadOnlyCollection<CachedDMChannel> DMChannels { get; } | |||
internal abstract IReadOnlyCollection<CachedGuild> Guilds { get; } | |||
internal abstract IReadOnlyCollection<CachedGlobalUser> Users { get; } | |||
internal abstract ICachedChannel GetChannel(ulong id); | |||
internal abstract void AddChannel(ICachedChannel channel); | |||
internal abstract ICachedChannel RemoveChannel(ulong id); | |||
internal abstract CachedDMChannel GetDMChannel(ulong userId); | |||
internal abstract void AddDMChannel(CachedDMChannel channel); | |||
internal abstract CachedDMChannel RemoveDMChannel(ulong userId); | |||
internal abstract CachedGuild GetGuild(ulong id); | |||
internal abstract void AddGuild(CachedGuild guild); | |||
internal abstract CachedGuild RemoveGuild(ulong id); | |||
internal abstract CachedGlobalUser GetUser(ulong id); | |||
internal abstract CachedGlobalUser GetOrAddUser(ulong userId, Func<ulong, CachedGlobalUser> userFactory); | |||
internal abstract CachedGlobalUser RemoveUser(ulong id); | |||
} | |||
} |
@@ -1,11 +0,0 @@ | |||
namespace Discord.Data | |||
{ | |||
//TODO: Implement | |||
//TODO: CachedPublicUser's GuildCount system is not at all multi-writer threadsafe! | |||
//TODO: CachedPublicUser's Update method is not multi-writer threadsafe! | |||
//TODO: Are there other multiwriters across shards? | |||
/*public class SharedDataStore | |||
{ | |||
}*/ | |||
} |
@@ -1,5 +1,4 @@ | |||
using Discord.API.Gateway; | |||
using Discord.Data; | |||
using Discord.Extensions; | |||
using Discord.Logging; | |||
using Discord.Net.Converters; | |||
@@ -26,7 +25,6 @@ namespace Discord | |||
#if BENCHMARK | |||
private readonly Logger _benchmarkLogger; | |||
#endif | |||
private readonly DataStoreProvider _dataStoreProvider; | |||
private readonly JsonSerializer _serializer; | |||
private readonly int _connectionTimeout, _reconnectDelay, _failedReconnectDelay; | |||
private readonly int _largeThreshold; | |||
@@ -71,7 +69,6 @@ namespace Discord | |||
_connectionTimeout = config.ConnectionTimeout; | |||
_reconnectDelay = config.ReconnectDelay; | |||
_failedReconnectDelay = config.FailedReconnectDelay; | |||
_dataStoreProvider = config.DataStoreProvider; | |||
MessageCacheSize = config.MessageCacheSize; | |||
_largeThreshold = config.LargeThreshold; | |||
@@ -481,7 +478,7 @@ namespace Discord | |||
await _gatewayLogger.DebugAsync("Received Dispatch (READY)").ConfigureAwait(false); | |||
var data = (payload as JToken).ToObject<ReadyEvent>(_serializer); | |||
var dataStore = _dataStoreProvider(ShardId, _totalShards, data.Guilds.Length, data.PrivateChannels.Length); | |||
var dataStore = new DataStore( data.Guilds.Length, data.PrivateChannels.Length); | |||
var currentUser = new CachedSelfUser(this, data.User); | |||
int unavailableGuilds = 0; | |||
@@ -1,5 +1,4 @@ | |||
using Discord.Data; | |||
using Discord.Net.WebSockets; | |||
using Discord.Net.WebSockets; | |||
namespace Discord | |||
{ | |||
@@ -29,11 +28,7 @@ namespace Discord | |||
/// Decreasing this may reduce CPU usage while increasing login time and network usage. | |||
/// </summary> | |||
public int LargeThreshold { get; set; } = 250; | |||
//Engines | |||
/// <summary> Gets or sets the provider used to generate datastores. </summary> | |||
public DataStoreProvider DataStoreProvider { get; set; } = (shardId, totalShards, guildCount, dmCount) => new DefaultDataStore(guildCount, dmCount); | |||
/// <summary> Gets or sets the provider used to generate new websocket connections. </summary> | |||
public WebSocketProvider WebSocketProvider { get; set; } = () => new DefaultWebSocketClient(); | |||
} | |||
@@ -1,4 +1,5 @@ | |||
using System; | |||
using Discord.API; | |||
using Model = Discord.API.User; | |||
namespace Discord | |||
@@ -33,6 +34,12 @@ namespace Discord | |||
} | |||
} | |||
public override void Update(Model model, UpdateSource source) | |||
{ | |||
lock (this) | |||
base.Update(model, source); | |||
} | |||
public CachedGlobalUser Clone() => MemberwiseClone() as CachedGlobalUser; | |||
ICachedUser ICachedUser.Clone() => Clone(); | |||
} | |||
@@ -1,5 +1,4 @@ | |||
using Discord.Data; | |||
using Discord.Extensions; | |||
using Discord.Extensions; | |||
using System; | |||
using System.Collections.Concurrent; | |||
using System.Collections.Generic; | |||