Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
StackExchange.Redis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tsai
StackExchange.Redis
Commits
4e5bbd11
Commit
4e5bbd11
authored
Jul 01, 2018
by
Nick Craver
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Documentation cleanup
parent
5b5be771
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
117 additions
and
96 deletions
+117
-96
Attributes.cs
StackExchange.Redis.Tests/Helpers/Attributes.cs
+6
-4
ConcurrentProfileStorageCollection.cs
...StackExchange/Redis/ConcurrentProfileStorageCollection.cs
+25
-25
ConnectionMultiplexer.Profiling.cs
...is/StackExchange/Redis/ConnectionMultiplexer.Profiling.cs
+10
-11
RetransmissionReasonType.cs
...dis/StackExchange/Redis/Enums/RetransmissionReasonType.cs
+4
-1
IProfiler.cs
...xchange.Redis/StackExchange/Redis/Interfaces/IProfiler.cs
+3
-2
LuaScript.cs
StackExchange.Redis/StackExchange/Redis/LuaScript.cs
+32
-26
ProfileContextTracker.cs
...change.Redis/StackExchange/Redis/ProfileContextTracker.cs
+22
-19
RedisKey.cs
StackExchange.Redis/StackExchange/Redis/RedisKey.cs
+6
-4
RedisValue.cs
StackExchange.Redis/StackExchange/Redis/RedisValue.cs
+2
-0
ScriptParameterMapper.cs
...change.Redis/StackExchange/Redis/ScriptParameterMapper.cs
+7
-4
No files found.
StackExchange.Redis.Tests/Helpers/Attributes.cs
View file @
4e5bbd11
...
@@ -9,11 +9,12 @@
...
@@ -9,11 +9,12 @@
namespace
StackExchange.Redis.Tests
namespace
StackExchange.Redis.Tests
{
{
/// <summary>
/// <summary>
///
Override for <see cref="Xunit.FactAttribute"/> that truncates our DisplayName down.
///
<para>Override for <see cref="Xunit.FactAttribute"/> that truncates our DisplayName down.</para>
///
///
<para>
/// Attribute that is applied to a method to indicate that it is a fact that should
/// Attribute that is applied to a method to indicate that it is a fact that should
/// be run by the test runner. It can also be extended to support a customized definition
/// be run by the test runner. It can also be extended to support a customized definition
/// of a test method.
/// of a test method.
/// </para>
/// </summary>
/// </summary>
[
AttributeUsage
(
AttributeTargets
.
Method
,
AllowMultiple
=
false
)]
[
AttributeUsage
(
AttributeTargets
.
Method
,
AllowMultiple
=
false
)]
[
XunitTestCaseDiscoverer
(
"StackExchange.Redis.Tests.FactDiscoverer"
,
"StackExchange.Redis.Tests"
)]
[
XunitTestCaseDiscoverer
(
"StackExchange.Redis.Tests.FactDiscoverer"
,
"StackExchange.Redis.Tests"
)]
...
@@ -32,13 +33,14 @@ public override string Skip
...
@@ -32,13 +33,14 @@ public override string Skip
}
}
/// <summary>
/// <summary>
///
Override for <see cref="Xunit.TheoryAttribute"/> that truncates our DisplayName down.
///
<para>Override for <see cref="Xunit.TheoryAttribute"/> that truncates our DisplayName down.</para>
///
///
<para>
/// Marks a test method as being a data theory. Data theories are tests which are
/// Marks a test method as being a data theory. Data theories are tests which are
/// fed various bits of data from a data source, mapping to parameters on the test
/// fed various bits of data from a data source, mapping to parameters on the test
/// method. If the data source contains multiple rows, then the test method is executed
/// method. If the data source contains multiple rows, then the test method is executed
/// multiple times (once with each data row). Data is provided by attributes which
/// multiple times (once with each data row). Data is provided by attributes which
/// derive from Xunit.Sdk.DataAttribute (notably, Xunit.InlineDataAttribute and Xunit.MemberDataAttribute).
/// derive from Xunit.Sdk.DataAttribute (notably, Xunit.InlineDataAttribute and Xunit.MemberDataAttribute).
/// </para>
/// </summary>
/// </summary>
[
AttributeUsage
(
AttributeTargets
.
Method
,
AllowMultiple
=
false
)]
[
AttributeUsage
(
AttributeTargets
.
Method
,
AllowMultiple
=
false
)]
[
XunitTestCaseDiscoverer
(
"StackExchange.Redis.Tests.TheoryDiscoverer"
,
"StackExchange.Redis.Tests"
)]
[
XunitTestCaseDiscoverer
(
"StackExchange.Redis.Tests.TheoryDiscoverer"
,
"StackExchange.Redis.Tests"
)]
...
...
StackExchange.Redis/StackExchange/Redis/ConcurrentProfileStorageCollection.cs
View file @
4e5bbd11
...
@@ -4,23 +4,23 @@
...
@@ -4,23 +4,23 @@
namespace
StackExchange.Redis
namespace
StackExchange.Redis
{
{
/// <summary>
/// <summary>
/// A collection of IProfiledCommands.
/// <para>A collection of IProfiledCommands.</para>
///
/// <para>This is a very light weight data structure, only supporting enumeration.</para>
/// This is a very light weight data structure, only supporting enumeration.
/// <para>
///
/// While it implements IEnumerable, it there are fewer allocations if one uses
/// While it implements IEnumerable, it there are fewer allocations if one uses
/// it's explicit GetEnumerator() method. Using `foreach` does this automatically.
/// it's explicit GetEnumerator() method. Using `foreach` does this automatically.
///
///
</para>
///
This type is not threadsafe.
///
<para>This type is not threadsafe.</para>
/// </summary>
/// </summary>
public
struct
ProfiledCommandEnumerable
:
IEnumerable
<
IProfiledCommand
>
public
struct
ProfiledCommandEnumerable
:
IEnumerable
<
IProfiledCommand
>
{
{
/// <summary>
/// <summary>
/// <para>
/// Implements IEnumerator for ProfiledCommandEnumerable.
/// Implements IEnumerator for ProfiledCommandEnumerable.
/// This implementation is comparable to List.Enumerator and Dictionary.Enumerator,
/// This implementation is comparable to List.Enumerator and Dictionary.Enumerator,
/// and is provided to reduce allocations in the common (ie. foreach) case.
/// and is provided to reduce allocations in the common (ie. foreach) case.
///
///
</para>
///
This type is not threadsafe.
///
<para>This type is not threadsafe.</para>
/// </summary>
/// </summary>
public
struct
Enumerator
:
IEnumerator
<
IProfiledCommand
>
public
struct
Enumerator
:
IEnumerator
<
IProfiledCommand
>
{
{
...
@@ -89,10 +89,11 @@ internal ProfiledCommandEnumerable(ProfileStorage head)
...
@@ -89,10 +89,11 @@ internal ProfiledCommandEnumerable(ProfileStorage head)
}
}
/// <summary>
/// <summary>
/// <para>
/// Returns an implementor of IEnumerator that, provided it isn't accessed
/// Returns an implementor of IEnumerator that, provided it isn't accessed
/// though an interface, avoids allocations.
/// though an interface, avoids allocations.
///
///
</para>
///
`foreach` will automatically use this method.
///
<para>`foreach` will automatically use this method.</para>
/// </summary>
/// </summary>
public
Enumerator
GetEnumerator
()
=>
new
Enumerator
(
Head
);
public
Enumerator
GetEnumerator
()
=>
new
Enumerator
(
Head
);
...
@@ -102,10 +103,11 @@ internal ProfiledCommandEnumerable(ProfileStorage head)
...
@@ -102,10 +103,11 @@ internal ProfiledCommandEnumerable(ProfileStorage head)
}
}
/// <summary>
/// <summary>
/// <para>
/// A thread-safe collection tailored to the "always append, with high contention, then enumerate once with no contention"
/// A thread-safe collection tailored to the "always append, with high contention, then enumerate once with no contention"
/// behavior of our profiling.
/// behavior of our profiling.
///
///
</para>
///
Performs better than ConcurrentBag, which is important since profiling code shouldn't impact timings.
///
<para>Performs better than ConcurrentBag, which is important since profiling code shouldn't impact timings.</para>
/// </summary>
/// </summary>
internal
sealed
class
ConcurrentProfileStorageCollection
internal
sealed
class
ConcurrentProfileStorageCollection
{
{
...
@@ -137,13 +139,10 @@ internal static int CountInPool()
...
@@ -137,13 +139,10 @@ internal static int CountInPool()
}
}
/// <summary>
/// <summary>
/// This method is thread-safe.
/// <para>This method is thread-safe.</para>
///
/// <para>Adds an element to the bag.</para>
/// Adds an element to the bag.
/// <para>Order is not preserved.</para>
///
/// <para>The element can only be a member of *one* bag.</para>
/// Order is not preserved.
///
/// The element can only be a member of *one* bag.
/// </summary>
/// </summary>
/// <param name="command">The command to add.</param>
/// <param name="command">The command to add.</param>
public
void
Add
(
ProfileStorage
command
)
public
void
Add
(
ProfileStorage
command
)
...
@@ -163,12 +162,12 @@ public void Add(ProfileStorage command)
...
@@ -163,12 +162,12 @@ public void Add(ProfileStorage command)
}
}
/// <summary>
/// <summary>
/// <para>
/// This method returns an enumerable view of the bag, and returns it to
/// This method returns an enumerable view of the bag, and returns it to
/// an internal pool for reuse by GetOrCreate().
/// an internal pool for reuse by GetOrCreate().
///
/// </para>
/// It is not thread safe.
/// <para>It is not thread safe.</para>
///
/// <para>It should only be called once the bag is finished being mutated.</para>
/// It should only be called once the bag is finished being mutated.
/// </summary>
/// </summary>
public
ProfiledCommandEnumerable
EnumerateAndReturnForReuse
()
public
ProfiledCommandEnumerable
EnumerateAndReturnForReuse
()
{
{
...
@@ -194,10 +193,11 @@ public void ReturnForReuse()
...
@@ -194,10 +193,11 @@ public void ReturnForReuse()
}
}
/// <summary>
/// <summary>
///
Returns a ConcurrentProfileStorageCollection to use.
///
<para>Returns a ConcurrentProfileStorageCollection to use.</para>
///
///
<para>
/// It *may* have allocated a new one, or it may return one that has previously been released.
/// It *may* have allocated a new one, or it may return one that has previously been released.
/// To return the collection, call EnumerateAndReturnForReuse()
/// To return the collection, call EnumerateAndReturnForReuse()
/// </para>
/// </summary>
/// </summary>
public
static
ConcurrentProfileStorageCollection
GetOrCreate
()
public
static
ConcurrentProfileStorageCollection
GetOrCreate
()
{
{
...
...
StackExchange.Redis/StackExchange/Redis/ConnectionMultiplexer.Profiling.cs
View file @
4e5bbd11
...
@@ -10,11 +10,12 @@ public partial class ConnectionMultiplexer
...
@@ -10,11 +10,12 @@ public partial class ConnectionMultiplexer
internal
ProfileContextTracker
profiledCommands
;
internal
ProfileContextTracker
profiledCommands
;
/// <summary>
/// <summary>
///
Sets an IProfiler instance for this ConnectionMultiplexer.
///
<para>Sets an IProfiler instance for this ConnectionMultiplexer.</para>
///
///
<para>
/// An IProfiler instances is used to determine which context to associate an
/// An IProfiler instances is used to determine which context to associate an
/// IProfiledCommand with. See BeginProfiling(object) and FinishProfiling(object)
/// IProfiledCommand with. See BeginProfiling(object) and FinishProfiling(object)
/// for more details.
/// for more details.
/// </para>
/// </summary>
/// </summary>
/// <param name="profiler">The profiler to register.</param>
/// <param name="profiler">The profiler to register.</param>
public
void
RegisterProfiler
(
IProfiler
profiler
)
public
void
RegisterProfiler
(
IProfiler
profiler
)
...
@@ -26,14 +27,13 @@ public void RegisterProfiler(IProfiler profiler)
...
@@ -26,14 +27,13 @@ public void RegisterProfiler(IProfiler profiler)
}
}
/// <summary>
/// <summary>
///
Begins profiling for the given context.
///
<para>Begins profiling for the given context.</para>
///
///
<para>
/// If the same context object is returned by the registered IProfiler, the IProfiledCommands
/// If the same context object is returned by the registered IProfiler, the IProfiledCommands
/// will be associated with each other.
/// will be associated with each other.
///
/// </para>
/// Call FinishProfiling with the same context to get the assocated commands.
/// <para>Call FinishProfiling with the same context to get the assocated commands.</para>
///
/// <para>Note that forContext cannot be a WeakReference or a WeakReference<T</para>>
/// Note that forContext cannot be a WeakReference or a WeakReference<T>
/// </summary>
/// </summary>
/// <param name="forContext">The context to begin profiling.</param>
/// <param name="forContext">The context to begin profiling.</param>
public
void
BeginProfiling
(
object
forContext
)
public
void
BeginProfiling
(
object
forContext
)
...
@@ -49,9 +49,8 @@ public void BeginProfiling(object forContext)
...
@@ -49,9 +49,8 @@ public void BeginProfiling(object forContext)
}
}
/// <summary>
/// <summary>
/// Stops profiling for the given context, returns all IProfiledCommands associated.
/// <para>Stops profiling for the given context, returns all IProfiledCommands associated.</para>
///
/// <para>By default this may do a sweep for dead profiling contexts, you can disable this by passing "allowCleanupSweep: false".</para>
/// By default this may do a sweep for dead profiling contexts, you can disable this by passing "allowCleanupSweep: false".
/// </summary>
/// </summary>
/// <param name="forContext">The context to begin profiling.</param>
/// <param name="forContext">The context to begin profiling.</param>
/// <param name="allowCleanupSweep">Whether to allow cleanup of old profiling sessions.</param>
/// <param name="allowCleanupSweep">Whether to allow cleanup of old profiling sessions.</param>
...
...
StackExchange.Redis/StackExchange/Redis/Enums/RetransmissionReasonType.cs
View file @
4e5bbd11
namespace
StackExchange.Redis
namespace
StackExchange.Redis
{
{
/// <summary>
/// <summary>
/// <para>
/// If an IProfiledCommand is a retransmission of a previous command, this enum
/// If an IProfiledCommand is a retransmission of a previous command, this enum
/// is used to indicate what prompted the retransmission.
/// is used to indicate what prompted the retransmission.
///
/// </para>
/// <para>
/// This can be used to distinguish between transient causes (moving hashslots, joining nodes, etc.)
/// This can be used to distinguish between transient causes (moving hashslots, joining nodes, etc.)
/// and incorrect routing.
/// and incorrect routing.
/// </para>
/// </summary>
/// </summary>
public
enum
RetransmissionReasonType
public
enum
RetransmissionReasonType
{
{
...
...
StackExchange.Redis/StackExchange/Redis/Interfaces/IProfiler.cs
View file @
4e5bbd11
...
@@ -4,10 +4,11 @@
...
@@ -4,10 +4,11 @@
namespace
StackExchange.Redis
namespace
StackExchange.Redis
{
{
/// <summary>
/// <summary>
///
A profiled command against a redis instance.
///
<para>A profiled command against a redis instance.</para>
///
///
<para>
/// TimeSpans returned by this interface use a high precision timer if possible.
/// TimeSpans returned by this interface use a high precision timer if possible.
/// DateTimes returned by this interface are no more precise than DateTime.UtcNow.
/// DateTimes returned by this interface are no more precise than DateTime.UtcNow.
/// </para>
/// </summary>
/// </summary>
public
interface
IProfiledCommand
public
interface
IProfiledCommand
{
{
...
...
StackExchange.Redis/StackExchange/Redis/LuaScript.cs
View file @
4e5bbd11
...
@@ -6,15 +6,16 @@
...
@@ -6,15 +6,16 @@
namespace
StackExchange.Redis
namespace
StackExchange.Redis
{
{
/// <summary>
/// <summary>
///
Represents a Lua script that can be executed on Redis.
///
<para>Represents a Lua script that can be executed on Redis.</para>
///
///
<para>
/// Unlike normal Redis Lua scripts, LuaScript can have named parameters (prefixed by a @).
/// Unlike normal Redis Lua scripts, LuaScript can have named parameters (prefixed by a @).
/// Public fields and properties of the passed in object are treated as parameters.
/// Public fields and properties of the passed in object are treated as parameters.
///
/// </para>
/// <para>
/// Parameters of type RedisKey are sent to Redis as KEY (https://redis.io/commands/eval) in addition to arguments,
/// Parameters of type RedisKey are sent to Redis as KEY (https://redis.io/commands/eval) in addition to arguments,
/// so as to play nicely with Redis Cluster.
/// so as to play nicely with Redis Cluster.
///
///
</para>
///
All members of this class are thread safe.
///
<para>All members of this class are thread safe.</para>
/// </summary>
/// </summary>
public
sealed
class
LuaScript
public
sealed
class
LuaScript
{
{
...
@@ -28,9 +29,8 @@ public sealed class LuaScript
...
@@ -28,9 +29,8 @@ public sealed class LuaScript
public
string
OriginalScript
{
get
;
}
public
string
OriginalScript
{
get
;
}
/// <summary>
/// <summary>
/// The Lua script that will actually be sent to Redis for execution.
/// <para>The Lua script that will actually be sent to Redis for execution.</para>
///
/// <para>All @-prefixed parameter names have been replaced at this point.</para>
/// All @-prefixed parameter names have been replaced at this point.
/// </summary>
/// </summary>
public
string
ExecutableScript
{
get
;
}
public
string
ExecutableScript
{
get
;
}
...
@@ -163,10 +163,11 @@ public Task<RedisResult> EvaluateAsync(IDatabaseAsync db, object ps = null, Redi
...
@@ -163,10 +163,11 @@ public Task<RedisResult> EvaluateAsync(IDatabaseAsync db, object ps = null, Redi
}
}
/// <summary>
/// <summary>
/// <para>
/// Loads this LuaScript into the given IServer so it can be run with it's SHA1 hash, instead of
/// Loads this LuaScript into the given IServer so it can be run with it's SHA1 hash, instead of
/// passing the full script on each Evaluate or EvaluateAsync call.
/// passing the full script on each Evaluate or EvaluateAsync call.
///
///
</para>
///
Note: the FireAndForget command flag cannot be set
///
<para>Note: the FireAndForget command flag cannot be set</para>
/// </summary>
/// </summary>
/// <param name="server">The server to load the script on.</param>
/// <param name="server">The server to load the script on.</param>
/// <param name="flags">The command flags to use.</param>
/// <param name="flags">The command flags to use.</param>
...
@@ -182,10 +183,11 @@ public LoadedLuaScript Load(IServer server, CommandFlags flags = CommandFlags.No
...
@@ -182,10 +183,11 @@ public LoadedLuaScript Load(IServer server, CommandFlags flags = CommandFlags.No
}
}
/// <summary>
/// <summary>
/// <para>
/// Loads this LuaScript into the given IServer so it can be run with it's SHA1 hash, instead of
/// Loads this LuaScript into the given IServer so it can be run with it's SHA1 hash, instead of
/// passing the full script on each Evaluate or EvaluateAsync call.
/// passing the full script on each Evaluate or EvaluateAsync call.
///
///
</para>
///
Note: the FireAndForget command flag cannot be set
///
<para>Note: the FireAndForget command flag cannot be set</para>
/// </summary>
/// </summary>
/// <param name="server">The server to load the script on.</param>
/// <param name="server">The server to load the script on.</param>
/// <param name="flags">The command flags to use.</param>
/// <param name="flags">The command flags to use.</param>
...
@@ -202,21 +204,24 @@ public async Task<LoadedLuaScript> LoadAsync(IServer server, CommandFlags flags
...
@@ -202,21 +204,24 @@ public async Task<LoadedLuaScript> LoadAsync(IServer server, CommandFlags flags
}
}
/// <summary>
/// <summary>
///
Represents a Lua script that can be executed on Redis.
///
<para>Represents a Lua script that can be executed on Redis.</para>
///
///
<para>
/// Unlike LuaScript, LoadedLuaScript sends the hash of it's ExecutableScript to Redis rather than pass
/// Unlike LuaScript, LoadedLuaScript sends the hash of it's ExecutableScript to Redis rather than pass
/// the whole script on each call. This requires that the script be loaded into Redis before it is used.
/// the whole script on each call. This requires that the script be loaded into Redis before it is used.
///
/// </para>
/// <para>
/// To create a LoadedLuaScript first create a LuaScript via LuaScript.Prepare(string), then
/// To create a LoadedLuaScript first create a LuaScript via LuaScript.Prepare(string), then
/// call Load(IServer, CommandFlags) on the returned LuaScript.
/// call Load(IServer, CommandFlags) on the returned LuaScript.
///
/// </para>
/// <para>
/// Unlike normal Redis Lua scripts, LoadedLuaScript can have named parameters (prefixed by a @).
/// Unlike normal Redis Lua scripts, LoadedLuaScript can have named parameters (prefixed by a @).
/// Public fields and properties of the passed in object are treated as parameters.
/// Public fields and properties of the passed in object are treated as parameters.
///
/// </para>
/// <para>
/// Parameters of type RedisKey are sent to Redis as KEY (https://redis.io/commands/eval) in addition to arguments,
/// Parameters of type RedisKey are sent to Redis as KEY (https://redis.io/commands/eval) in addition to arguments,
/// so as to play nicely with Redis Cluster.
/// so as to play nicely with Redis Cluster.
///
///
</para>
///
All members of this class are thread safe.
///
<para>All members of this class are thread safe.</para>
/// </summary>
/// </summary>
public
sealed
class
LoadedLuaScript
public
sealed
class
LoadedLuaScript
{
{
...
@@ -231,9 +236,8 @@ public sealed class LoadedLuaScript
...
@@ -231,9 +236,8 @@ public sealed class LoadedLuaScript
public
string
ExecutableScript
=>
Original
.
ExecutableScript
;
public
string
ExecutableScript
=>
Original
.
ExecutableScript
;
/// <summary>
/// <summary>
/// The SHA1 hash of ExecutableScript.
/// <para>The SHA1 hash of ExecutableScript.</para>
///
/// <para>This is sent to Redis instead of ExecutableScript during Evaluate and EvaluateAsync calls.</para>
/// This is sent to Redis instead of ExecutableScript during Evaluate and EvaluateAsync calls.
/// </summary>
/// </summary>
public
byte
[]
Hash
{
get
;
}
public
byte
[]
Hash
{
get
;
}
...
@@ -247,10 +251,11 @@ internal LoadedLuaScript(LuaScript original, byte[] hash)
...
@@ -247,10 +251,11 @@ internal LoadedLuaScript(LuaScript original, byte[] hash)
}
}
/// <summary>
/// <summary>
///
Evaluates this LoadedLuaScript against the given database, extracting parameters for the passed in object if any.
///
<para>Evaluates this LoadedLuaScript against the given database, extracting parameters for the passed in object if any.</para>
///
///
<para>
/// This method sends the SHA1 hash of the ExecutableScript instead of the script itself. If the script has not
/// This method sends the SHA1 hash of the ExecutableScript instead of the script itself. If the script has not
/// been loaded into the passed Redis instance it will fail.
/// been loaded into the passed Redis instance it will fail.
/// </para>
/// </summary>
/// </summary>
/// <param name="db">The redis databse to evaluate against.</param>
/// <param name="db">The redis databse to evaluate against.</param>
/// <param name="ps">The parameter object to use.</param>
/// <param name="ps">The parameter object to use.</param>
...
@@ -263,10 +268,11 @@ public RedisResult Evaluate(IDatabase db, object ps = null, RedisKey? withKeyPre
...
@@ -263,10 +268,11 @@ public RedisResult Evaluate(IDatabase db, object ps = null, RedisKey? withKeyPre
}
}
/// <summary>
/// <summary>
///
Evaluates this LoadedLuaScript against the given database, extracting parameters for the passed in object if any.
///
<para>Evaluates this LoadedLuaScript against the given database, extracting parameters for the passed in object if any.</para>
///
///
<para>
/// This method sends the SHA1 hash of the ExecutableScript instead of the script itself. If the script has not
/// This method sends the SHA1 hash of the ExecutableScript instead of the script itself. If the script has not
/// been loaded into the passed Redis instance it will fail.
/// been loaded into the passed Redis instance it will fail.
/// </para>
/// </summary>
/// </summary>
/// <param name="db">The redis databse to evaluate against.</param>
/// <param name="db">The redis databse to evaluate against.</param>
/// <param name="ps">The parameter object to use.</param>
/// <param name="ps">The parameter object to use.</param>
...
...
StackExchange.Redis/StackExchange/Redis/ProfileContextTracker.cs
View file @
4e5bbd11
...
@@ -11,14 +11,13 @@ namespace StackExchange.Redis
...
@@ -11,14 +11,13 @@ namespace StackExchange.Redis
internal
sealed
class
ProfileContextTracker
internal
sealed
class
ProfileContextTracker
{
{
/// <summary>
/// <summary>
/// Necessary, because WeakReference can't be readily comparable (since the reference is... weak).
/// <para>Necessary, because WeakReference can't be readily comparable (since the reference is... weak).</para>
///
/// <para>This lets us detect leaks* with some reasonable confidence, and cleanup periodically.</para>
/// This lets us detect leaks* with some reasonable confidence, and cleanup periodically.
/// <para>
///
/// Some calisthenics are done to avoid allocating WeakReferences for no reason, as often
/// Some calisthenics are done to avoid allocating WeakReferences for no reason, as often
/// we're just looking up ProfileStorage.
/// we're just looking up ProfileStorage.
///
///
</para>
///
* Somebody starts profiling, but for whatever reason never *stops* with a context object
///
<para>* Somebody starts profiling, but for whatever reason never *stops* with a context object</para>
/// </summary>
/// </summary>
private
struct
ProfileContextCell
:
IEquatable
<
ProfileContextCell
>
private
struct
ProfileContextCell
:
IEquatable
<
ProfileContextCell
>
{
{
...
@@ -47,20 +46,22 @@ private ProfileContextCell(object forObj, bool isEphemeral)
...
@@ -47,20 +46,22 @@ private ProfileContextCell(object forObj, bool isEphemeral)
}
}
/// <summary>
/// <summary>
///
Suitable for use as a key into something.
///
<para>Suitable for use as a key into something.</para>
///
///
<para>
/// This instance **WILL NOT** keep forObj alive, so it can
/// This instance **WILL NOT** keep forObj alive, so it can
/// be copied out of the calling method's scope.
/// be copied out of the calling method's scope.
/// </para>
/// </summary>
/// </summary>
/// <param name="forObj">The object to get a context for.</param>
/// <param name="forObj">The object to get a context for.</param>
public
static
ProfileContextCell
ToStoreUnder
(
object
forObj
)
=>
new
ProfileContextCell
(
forObj
,
isEphemeral
:
false
);
public
static
ProfileContextCell
ToStoreUnder
(
object
forObj
)
=>
new
ProfileContextCell
(
forObj
,
isEphemeral
:
false
);
/// <summary>
/// <summary>
///
Only suitable for looking up.
///
<para>Only suitable for looking up.</para>
///
///
<para>
/// This instance **ABSOLUTELY WILL** keep forObj alive, so this
/// This instance **ABSOLUTELY WILL** keep forObj alive, so this
/// had better not be copied into anything outside the scope of the
/// had better not be copied into anything outside the scope of the
/// calling method.
/// calling method.
/// </para>
/// </summary>
/// </summary>
/// <param name="forObj">The object to lookup a context by.</param>
/// <param name="forObj">The object to lookup a context by.</param>
public
static
ProfileContextCell
ToLookupBy
(
object
forObj
)
=>
new
ProfileContextCell
(
forObj
,
isEphemeral
:
true
);
public
static
ProfileContextCell
ToLookupBy
(
object
forObj
)
=>
new
ProfileContextCell
(
forObj
,
isEphemeral
:
true
);
...
@@ -130,9 +131,8 @@ public ProfileContextTracker()
...
@@ -130,9 +131,8 @@ public ProfileContextTracker()
}
}
/// <summary>
/// <summary>
/// Registers the passed context with a collection that can be retried with subsequent calls to TryGetValue.
/// <para>Registers the passed context with a collection that can be retried with subsequent calls to TryGetValue.</para>
///
/// <para>Returns false if the passed context object is already registered.</para>
/// Returns false if the passed context object is already registered.
/// </summary>
/// </summary>
/// <param name="ctx">The context to use.</param>
/// <param name="ctx">The context to use.</param>
public
bool
TryCreate
(
object
ctx
)
public
bool
TryCreate
(
object
ctx
)
...
@@ -146,10 +146,11 @@ public bool TryCreate(object ctx)
...
@@ -146,10 +146,11 @@ public bool TryCreate(object ctx)
}
}
/// <summary>
/// <summary>
/// <para>
/// Returns true and sets val to the tracking collection associated with the given context if the context
/// Returns true and sets val to the tracking collection associated with the given context if the context
/// was registered with TryCreate.
/// was registered with TryCreate.
///
///
</para>
///
Otherwise returns false and sets val to null.
///
<para>Otherwise returns false and sets val to null.</para>
/// </summary>
/// </summary>
/// <param name="ctx">The context to get a value for.</param>
/// <param name="ctx">The context to get a value for.</param>
/// <param name="val">The collection (if present) for <paramref name="ctx"/>.</param>
/// <param name="val">The collection (if present) for <paramref name="ctx"/>.</param>
...
@@ -160,13 +161,15 @@ public bool TryGetValue(object ctx, out ConcurrentProfileStorageCollection val)
...
@@ -160,13 +161,15 @@ public bool TryGetValue(object ctx, out ConcurrentProfileStorageCollection val)
}
}
/// <summary>
/// <summary>
/// <para>
/// Removes a context, setting all commands to a (non-thread safe) enumerable of
/// Removes a context, setting all commands to a (non-thread safe) enumerable of
/// all the commands attached to that context.
/// all the commands attached to that context.
///
///
</para>
///
If the context was never registered, will return false and set commands to null.
///
<para>If the context was never registered, will return false and set commands to null.</para>
///
///
<para>
/// Subsequent calls to TryRemove with the same context will return false unless it is
/// Subsequent calls to TryRemove with the same context will return false unless it is
/// re-registered with TryCreate.
/// re-registered with TryCreate.
/// </para>
/// </summary>
/// </summary>
/// <param name="ctx">The context to remove for.</param>
/// <param name="ctx">The context to remove for.</param>
/// <param name="commands">The commands to remove.</param>
/// <param name="commands">The commands to remove.</param>
...
@@ -219,4 +222,4 @@ public bool TryCleanup()
...
@@ -219,4 +222,4 @@ public bool TryCleanup()
return
true
;
return
true
;
}
}
}
}
}
}
\ No newline at end of file
StackExchange.Redis/StackExchange/Redis/RedisKey.cs
View file @
4e5bbd11
...
@@ -277,19 +277,21 @@ internal static byte[] ConcatenateBytes(byte[] a, object b, byte[] c)
...
@@ -277,19 +277,21 @@ internal static byte[] ConcatenateBytes(byte[] a, object b, byte[] c)
}
}
/// <summary>
/// <summary>
///
Prepends p to this RedisKey, returning a new RedisKey.
///
<para>Prepends p to this RedisKey, returning a new RedisKey.</para>
///
///
<para>
/// Avoids some allocations if possible, repeated Prepend/Appends make
/// Avoids some allocations if possible, repeated Prepend/Appends make
/// it less possible.
/// it less possible.
/// </para>
/// </summary>
/// </summary>
/// <param name="prefix">The prefix to prepend.</param>
/// <param name="prefix">The prefix to prepend.</param>
public
RedisKey
Prepend
(
RedisKey
prefix
)
=>
WithPrefix
(
prefix
,
this
);
public
RedisKey
Prepend
(
RedisKey
prefix
)
=>
WithPrefix
(
prefix
,
this
);
/// <summary>
/// <summary>
///
Appends p to this RedisKey, returning a new RedisKey.
///
<para>Appends p to this RedisKey, returning a new RedisKey.</para>
///
///
<para>
/// Avoids some allocations if possible, repeated Prepend/Appends make
/// Avoids some allocations if possible, repeated Prepend/Appends make
/// it less possible.
/// it less possible.
/// </para>
/// </summary>
/// </summary>
/// <param name="suffix">The suffix to append.</param>
/// <param name="suffix">The suffix to append.</param>
public
RedisKey
Append
(
RedisKey
suffix
)
=>
WithPrefix
(
this
,
suffix
);
public
RedisKey
Append
(
RedisKey
suffix
)
=>
WithPrefix
(
this
,
suffix
);
...
...
StackExchange.Redis/StackExchange/Redis/RedisValue.cs
View file @
4e5bbd11
...
@@ -432,6 +432,7 @@ internal static RedisValue TryParse(object obj)
...
@@ -432,6 +432,7 @@ internal static RedisValue TryParse(object obj)
/// <summary>
/// <summary>
/// Creates a new <see cref="RedisValue"/> from a <see cref="T:ReadOnlyMemory{byte}"/>.
/// Creates a new <see cref="RedisValue"/> from a <see cref="T:ReadOnlyMemory{byte}"/>.
/// </summary>
/// </summary>
/// <param name="value">The <see cref="T:ReadOnlyMemory{byte}"/> to convert to a <see cref="RedisValue"/>.</param>
public
static
implicit
operator
RedisValue
(
ReadOnlyMemory
<
byte
>
value
)
public
static
implicit
operator
RedisValue
(
ReadOnlyMemory
<
byte
>
value
)
{
{
if
(
value
.
Length
==
0
)
return
EmptyString
;
if
(
value
.
Length
==
0
)
return
EmptyString
;
...
@@ -440,6 +441,7 @@ internal static RedisValue TryParse(object obj)
...
@@ -440,6 +441,7 @@ internal static RedisValue TryParse(object obj)
/// <summary>
/// <summary>
/// Creates a new <see cref="RedisValue"/> from a <see cref="T:Memory{byte}"/>.
/// Creates a new <see cref="RedisValue"/> from a <see cref="T:Memory{byte}"/>.
/// </summary>
/// </summary>
/// <param name="value">The <see cref="T:Memory{byte}"/> to convert to a <see cref="RedisValue"/>.</param>
public
static
implicit
operator
RedisValue
(
Memory
<
byte
>
value
)
=>
(
ReadOnlyMemory
<
byte
>)
value
;
public
static
implicit
operator
RedisValue
(
Memory
<
byte
>
value
)
=>
(
ReadOnlyMemory
<
byte
>)
value
;
/// <summary>
/// <summary>
...
...
StackExchange.Redis/StackExchange/Redis/ScriptParameterMapper.cs
View file @
4e5bbd11
...
@@ -272,16 +272,19 @@ private static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool,
...
@@ -272,16 +272,19 @@ private static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool,
}
}
/// <summary>
/// <summary>
///
Creates a Func that extracts parameters from the given type for use by a LuaScript.
///
<para>Creates a Func that extracts parameters from the given type for use by a LuaScript.</para>
///
///
<para>
/// Members that are RedisKey's get extracted to be passed in as keys to redis; all members that
/// Members that are RedisKey's get extracted to be passed in as keys to redis; all members that
/// appear in the script get extracted as RedisValue arguments to be sent up as args.
/// appear in the script get extracted as RedisValue arguments to be sent up as args.
///
/// </para>
/// <para>
/// We send all values as arguments so we don't have to prepare the same script for different parameter
/// We send all values as arguments so we don't have to prepare the same script for different parameter
/// types.
/// types.
///
/// </para>
/// <para>
/// The created Func takes a RedisKey, which will be prefixed to all keys (and arguments of type RedisKey) for
/// The created Func takes a RedisKey, which will be prefixed to all keys (and arguments of type RedisKey) for
/// keyspace isolation.
/// keyspace isolation.
/// </para>
/// </summary>
/// </summary>
/// <param name="t">The type to extract for.</param>
/// <param name="t">The type to extract for.</param>
/// <param name="script">The script to extract for.</param>
/// <param name="script">The script to extract for.</param>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment