Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
CAP
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
CAP
Commits
c84bccff
Commit
c84bccff
authored
Aug 10, 2018
by
Savorboard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tweak ObjectId
parent
681e3822
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
27 additions
and
253 deletions
+27
-253
ObjectId.cs
src/DotNetCore.CAP/Infrastructure/ObjectId.cs
+27
-253
No files found.
src/DotNetCore.CAP/Infrastructure/ObjectId.cs
View file @
c84bccff
...
...
@@ -18,15 +18,13 @@ namespace DotNetCore.CAP.Infrastructure
public
struct
ObjectId
:
IComparable
<
ObjectId
>,
IEquatable
<
ObjectId
>
{
// private static fields
private
static
readonly
DateTime
__u
nixEpoch
;
private
static
readonly
DateTime
U
nixEpoch
;
private
static
readonly
long
__dateTimeMaxValueMillisecondsSinceEpoch
;
private
static
readonly
long
__dateTimeMinValueMillisecondsSinceEpoch
;
private
static
readonly
int
__staticMachine
;
private
static
readonly
short
__staticPid
;
private
static
int
__staticIncrement
;
// high byte will be masked out when generating new ObjectId
private
static
readonly
int
StaticMachine
;
private
static
readonly
short
StaticPid
;
private
static
int
_staticIncrement
;
// high byte will be masked out when generating new ObjectId
private
static
readonly
uint
[]
_l
ookup32
=
Enumerable
.
Range
(
0
,
256
).
Select
(
i
=>
private
static
readonly
uint
[]
L
ookup32
=
Enumerable
.
Range
(
0
,
256
).
Select
(
i
=>
{
var
s
=
i
.
ToString
(
"x2"
);
return
(
uint
)
s
[
0
]
+
((
uint
)
s
[
1
]
<<
16
);
...
...
@@ -44,40 +42,13 @@ namespace DotNetCore.CAP.Infrastructure
// static constructor
static
ObjectId
()
{
__unixEpoch
=
new
DateTime
(
1970
,
1
,
1
,
0
,
0
,
0
,
DateTimeKind
.
Utc
);
__dateTimeMaxValueMillisecondsSinceEpoch
=
(
DateTime
.
MaxValue
-
__unixEpoch
).
Ticks
/
10000
;
__dateTimeMinValueMillisecondsSinceEpoch
=
(
DateTime
.
MinValue
-
__unixEpoch
).
Ticks
/
10000
;
__staticMachine
=
GetMachineHash
();
__staticIncrement
=
new
Random
().
Next
();
__staticPid
=
(
short
)
GetCurrentProcessId
();
UnixEpoch
=
new
DateTime
(
1970
,
1
,
1
,
0
,
0
,
0
,
DateTimeKind
.
Utc
);
StaticMachine
=
GetMachineHash
();
_staticIncrement
=
new
Random
().
Next
();
StaticPid
=
(
short
)
GetCurrentProcessId
();
}
// constructors
/// <summary>
/// Initializes a new instance of the ObjectId class.
/// </summary>
/// <param name="bytes">The bytes.</param>
public
ObjectId
(
byte
[]
bytes
)
{
if
(
bytes
==
null
)
{
throw
new
ArgumentNullException
(
"bytes"
);
}
Unpack
(
bytes
,
out
_timestamp
,
out
_machine
,
out
_pid
,
out
_increment
);
}
/// <summary>
/// Initializes a new instance of the ObjectId class.
/// </summary>
/// <param name="timestamp">The timestamp (expressed as a DateTime).</param>
/// <param name="machine">The machine hash.</param>
/// <param name="pid">The PID.</param>
/// <param name="increment">The increment.</param>
public
ObjectId
(
DateTime
timestamp
,
int
machine
,
short
pid
,
int
increment
)
:
this
(
GetTimestampFromDateTime
(
timestamp
),
machine
,
pid
,
increment
)
{
}
/// <summary>
/// Initializes a new instance of the ObjectId class.
...
...
@@ -90,14 +61,14 @@ namespace DotNetCore.CAP.Infrastructure
{
if
((
machine
&
0xff000000
)
!=
0
)
{
throw
new
ArgumentOutOfRangeException
(
"machine"
,
"The machine value must be between 0 and 16777215 (it must fit in 3 bytes)."
);
throw
new
ArgumentOutOfRangeException
(
nameof
(
machine
)
,
@
"The machine value must be between 0 and 16777215 (it must fit in 3 bytes)."
);
}
if
((
increment
&
0xff000000
)
!=
0
)
{
throw
new
ArgumentOutOfRangeException
(
"increment"
,
"The increment value must be between 0 and 16777215 (it must fit in 3 bytes)."
);
throw
new
ArgumentOutOfRangeException
(
nameof
(
increment
)
,
@
"The increment value must be between 0 and 16777215 (it must fit in 3 bytes)."
);
}
_timestamp
=
timestamp
;
...
...
@@ -105,76 +76,7 @@ namespace DotNetCore.CAP.Infrastructure
_pid
=
pid
;
_increment
=
increment
;
}
/// <summary>
/// Initializes a new instance of the ObjectId class.
/// </summary>
/// <param name="value">The value.</param>
public
ObjectId
(
string
value
)
{
if
(
value
==
null
)
{
throw
new
ArgumentNullException
(
"value"
);
}
Unpack
(
ParseHexString
(
value
),
out
_timestamp
,
out
_machine
,
out
_pid
,
out
_increment
);
}
// public static properties
/// <summary>
/// Gets an instance of ObjectId where the value is empty.
/// </summary>
public
static
ObjectId
Empty
{
get
;
}
=
default
(
ObjectId
);
// public properties
/// <summary>
/// Gets the timestamp.
/// </summary>
public
int
Timestamp
=>
_timestamp
;
/// <summary>
/// Gets the machine.
/// </summary>
public
int
Machine
=>
_machine
;
/// <summary>
/// Gets the PID.
/// </summary>
public
short
Pid
=>
_pid
;
/// <summary>
/// Gets the increment.
/// </summary>
public
int
Increment
=>
_increment
;
/// <summary>
/// Gets the creation time (derived from the timestamp).
/// </summary>
public
DateTime
CreationTime
=>
__unixEpoch
.
AddSeconds
(
_timestamp
);
// public operators
/// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId</param>
/// <returns>True if the first ObjectId is less than the second ObjectId.</returns>
public
static
bool
operator
<(
ObjectId
lhs
,
ObjectId
rhs
)
{
return
lhs
.
CompareTo
(
rhs
)
<
0
;
}
/// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId</param>
/// <returns>True if the first ObjectId is less than or equal to the second ObjectId.</returns>
public
static
bool
operator
<=(
ObjectId
lhs
,
ObjectId
rhs
)
{
return
lhs
.
CompareTo
(
rhs
)
<=
0
;
}
/// <summary>
/// Compares two ObjectIds.
/// </summary>
...
...
@@ -196,29 +98,7 @@ namespace DotNetCore.CAP.Infrastructure
{
return
!(
lhs
==
rhs
);
}
/// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId</param>
/// <returns>True if the first ObjectId is greather than or equal to the second ObjectId.</returns>
public
static
bool
operator
>=(
ObjectId
lhs
,
ObjectId
rhs
)
{
return
lhs
.
CompareTo
(
rhs
)
>=
0
;
}
/// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId</param>
/// <returns>True if the first ObjectId is greather than the second ObjectId.</returns>
public
static
bool
operator
>(
ObjectId
lhs
,
ObjectId
rhs
)
{
return
lhs
.
CompareTo
(
rhs
)
>
0
;
}
// public static methods
/// <summary>
/// Generates a new ObjectId with a unique value.
...
...
@@ -228,17 +108,7 @@ namespace DotNetCore.CAP.Infrastructure
{
return
GenerateNewId
(
GetTimestampFromDateTime
(
DateTime
.
UtcNow
));
}
/// <summary>
/// Generates a new ObjectId with a unique value (with the timestamp component based on a given DateTime).
/// </summary>
/// <param name="timestamp">The timestamp component (expressed as a DateTime).</param>
/// <returns>An ObjectId.</returns>
public
static
ObjectId
GenerateNewId
(
DateTime
timestamp
)
{
return
GenerateNewId
(
GetTimestampFromDateTime
(
timestamp
));
}
/// <summary>
/// Generates a new ObjectId with a unique value (with the given timestamp).
/// </summary>
...
...
@@ -246,8 +116,8 @@ namespace DotNetCore.CAP.Infrastructure
/// <returns>An ObjectId.</returns>
public
static
ObjectId
GenerateNewId
(
int
timestamp
)
{
var
increment
=
Interlocked
.
Increment
(
ref
_
_
staticIncrement
)
&
0x00ffffff
;
// only use low order 3 bytes
return
new
ObjectId
(
timestamp
,
__staticMachine
,
__s
taticPid
,
increment
);
var
increment
=
Interlocked
.
Increment
(
ref
_staticIncrement
)
&
0x00ffffff
;
// only use low order 3 bytes
return
new
ObjectId
(
timestamp
,
StaticMachine
,
S
taticPid
,
increment
);
}
/// <summary>
...
...
@@ -271,14 +141,14 @@ namespace DotNetCore.CAP.Infrastructure
{
if
((
machine
&
0xff000000
)
!=
0
)
{
throw
new
ArgumentOutOfRangeException
(
"machine"
,
"The machine value must be between 0 and 16777215 (it must fit in 3 bytes)."
);
throw
new
ArgumentOutOfRangeException
(
nameof
(
machine
)
,
@
"The machine value must be between 0 and 16777215 (it must fit in 3 bytes)."
);
}
if
((
increment
&
0xff000000
)
!=
0
)
{
throw
new
ArgumentOutOfRangeException
(
"increment"
,
"The increment value must be between 0 and 16777215 (it must fit in 3 bytes)."
);
throw
new
ArgumentOutOfRangeException
(
nameof
(
increment
)
,
@
"The increment value must be between 0 and 16777215 (it must fit in 3 bytes)."
);
}
var
bytes
=
new
byte
[
12
];
...
...
@@ -297,53 +167,6 @@ namespace DotNetCore.CAP.Infrastructure
return
bytes
;
}
/// <summary>
/// Parses a string and creates a new ObjectId.
/// </summary>
/// <param name="s">The string value.</param>
/// <returns>A ObjectId.</returns>
public
static
ObjectId
Parse
(
string
s
)
{
if
(
s
==
null
)
{
throw
new
ArgumentNullException
(
"s"
);
}
if
(
s
.
Length
!=
24
)
{
throw
new
ArgumentOutOfRangeException
(
"s"
,
"ObjectId string value must be 24 characters."
);
}
return
new
ObjectId
(
ParseHexString
(
s
));
}
/// <summary>
/// Unpacks a byte array into the components of an ObjectId.
/// </summary>
/// <param name="bytes">A byte array.</param>
/// <param name="timestamp">The timestamp.</param>
/// <param name="machine">The machine hash.</param>
/// <param name="pid">The PID.</param>
/// <param name="increment">The increment.</param>
public
static
void
Unpack
(
byte
[]
bytes
,
out
int
timestamp
,
out
int
machine
,
out
short
pid
,
out
int
increment
)
{
if
(
bytes
==
null
)
{
throw
new
ArgumentNullException
(
"bytes"
);
}
if
(
bytes
.
Length
!=
12
)
{
throw
new
ArgumentOutOfRangeException
(
"bytes"
,
"Byte array must be 12 bytes long."
);
}
timestamp
=
(
bytes
[
0
]
<<
24
)
+
(
bytes
[
1
]
<<
16
)
+
(
bytes
[
2
]
<<
8
)
+
bytes
[
3
];
machine
=
(
bytes
[
4
]
<<
16
)
+
(
bytes
[
5
]
<<
8
)
+
bytes
[
6
];
pid
=
(
short
)
((
bytes
[
7
]
<<
8
)
+
bytes
[
8
]);
increment
=
(
bytes
[
9
]
<<
16
)
+
(
bytes
[
10
]
<<
8
)
+
bytes
[
11
];
}
// private static methods
/// <summary>
/// Gets the current process id. This method exists because of how CAS operates on the call stack, checking
/// for permissions before executing the method. Hence, if we inlined this call, the calling method would not execute
...
...
@@ -365,7 +188,7 @@ namespace DotNetCore.CAP.Infrastructure
private
static
int
GetTimestampFromDateTime
(
DateTime
timestamp
)
{
return
(
int
)
Math
.
Floor
((
ToUniversalTime
(
timestamp
)
-
__u
nixEpoch
).
TotalSeconds
);
return
(
int
)
Math
.
Floor
((
ToUniversalTime
(
timestamp
)
-
U
nixEpoch
).
TotalSeconds
);
}
// public methods
...
...
@@ -421,9 +244,9 @@ namespace DotNetCore.CAP.Infrastructure
/// <returns>True if the other object is an ObjectId and equal to this one.</returns>
public
override
bool
Equals
(
object
obj
)
{
if
(
obj
is
ObjectId
)
if
(
obj
is
ObjectId
id
)
{
return
Equals
(
(
ObjectId
)
obj
);
return
Equals
(
id
);
}
return
false
;
...
...
@@ -461,33 +284,6 @@ namespace DotNetCore.CAP.Infrastructure
return
ToHexString
(
ToByteArray
());
}
/// <summary>
/// Parses a hex string into its equivalent byte array.
/// </summary>
/// <param name="s">The hex string to parse.</param>
/// <returns>The byte equivalent of the hex string.</returns>
public
static
byte
[]
ParseHexString
(
string
s
)
{
if
(
s
==
null
)
{
throw
new
ArgumentNullException
(
"s"
);
}
if
(
s
.
Length
%
2
==
1
)
{
throw
new
Exception
(
"The binary key cannot have an odd number of digits"
);
}
var
arr
=
new
byte
[
s
.
Length
>>
1
];
for
(
var
i
=
0
;
i
<
s
.
Length
>>
1
;
++
i
)
{
arr
[
i
]
=
(
byte
)
((
GetHexVal
(
s
[
i
<<
1
])
<<
4
)
+
GetHexVal
(
s
[(
i
<<
1
)
+
1
]));
}
return
arr
;
}
/// <summary>
/// Converts a byte array to a hex string.
/// </summary>
...
...
@@ -497,13 +293,13 @@ namespace DotNetCore.CAP.Infrastructure
{
if
(
bytes
==
null
)
{
throw
new
ArgumentNullException
(
"bytes"
);
throw
new
ArgumentNullException
(
nameof
(
bytes
)
);
}
var
result
=
new
char
[
bytes
.
Length
*
2
];
for
(
var
i
=
0
;
i
<
bytes
.
Length
;
i
++)
{
var
val
=
_l
ookup32
[
bytes
[
i
]];
var
val
=
L
ookup32
[
bytes
[
i
]];
result
[
2
*
i
]
=
(
char
)
val
;
result
[
2
*
i
+
1
]
=
(
char
)
(
val
>>
16
);
}
...
...
@@ -511,17 +307,6 @@ namespace DotNetCore.CAP.Infrastructure
return
new
string
(
result
);
}
/// <summary>
/// Converts a DateTime to number of milliseconds since Unix epoch.
/// </summary>
/// <param name="dateTime">A DateTime.</param>
/// <returns>Number of seconds since Unix epoch.</returns>
public
static
long
ToMillisecondsSinceEpoch
(
DateTime
dateTime
)
{
var
utcDateTime
=
ToUniversalTime
(
dateTime
);
return
(
utcDateTime
-
__unixEpoch
).
Ticks
/
10000
;
}
/// <summary>
/// Converts a DateTime to UTC (with special handling for MinValue and MaxValue).
/// </summary>
...
...
@@ -541,16 +326,5 @@ namespace DotNetCore.CAP.Infrastructure
return
dateTime
.
ToUniversalTime
();
}
private
static
int
GetHexVal
(
char
hex
)
{
int
val
=
hex
;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return
val
-
(
val
<
58
?
48
:
(
val
<
97
?
55
:
87
));
}
}
}
\ No newline at end of file
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