-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Eliminated GrainState #1060
Eliminated GrainState #1060
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using System; | ||
|
||
namespace Orleans | ||
{ | ||
public interface IGrainState | ||
{ | ||
object State { get; set; } | ||
string ETag { get; set; } | ||
} | ||
|
||
[Serializable] | ||
internal class GrainState<T> : IGrainState | ||
{ | ||
public T State; | ||
|
||
object IGrainState.State | ||
{ | ||
get | ||
{ | ||
return State; | ||
|
||
} | ||
set | ||
{ | ||
State = (T)value; | ||
} | ||
} | ||
|
||
public string ETag { get; set; } | ||
|
||
public GrainState() | ||
{ | ||
} | ||
|
||
public GrainState(T state) : this(state, null) | ||
{ | ||
} | ||
|
||
public GrainState(T state, string eTag) | ||
{ | ||
State = state; | ||
ETag = eTag; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,10 +12,11 @@ namespace Orleans.Core | |
internal class GrainStateStorageBridge : IStorage | ||
{ | ||
private readonly IStorageProvider store; | ||
private readonly Grain grain; | ||
private readonly IStatefulGrain grain; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you please explain what is the difference between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
private readonly Grain baseGrain; | ||
private readonly string grainTypeName; | ||
|
||
public GrainStateStorageBridge(string grainTypeName, Grain grain, IStorageProvider store) | ||
public GrainStateStorageBridge(string grainTypeName, IStatefulGrain grain, IStorageProvider store) | ||
{ | ||
if (grainTypeName == null) | ||
{ | ||
|
@@ -31,6 +32,7 @@ public GrainStateStorageBridge(string grainTypeName, Grain grain, IStorageProvid | |
} | ||
this.grainTypeName = grainTypeName; | ||
this.grain = grain; | ||
this.baseGrain = grain as Grain; | ||
this.store = store; | ||
} | ||
|
||
|
@@ -42,11 +44,11 @@ public async Task ReadStateAsync() | |
{ | ||
const string what = "ReadState"; | ||
Stopwatch sw = Stopwatch.StartNew(); | ||
GrainReference grainRef = grain.GrainReference; | ||
GrainReference grainRef = baseGrain.GrainReference; | ||
try | ||
{ | ||
await store.ReadStateAsync(grainTypeName, grainRef, grain.GrainState); | ||
|
||
StorageStatisticsGroup.OnStorageRead(store, grainTypeName, grainRef, sw.Elapsed); | ||
} | ||
catch (Exception exc) | ||
|
@@ -70,12 +72,11 @@ public async Task WriteStateAsync() | |
{ | ||
const string what = "WriteState"; | ||
Stopwatch sw = Stopwatch.StartNew(); | ||
GrainReference grainRef = grain.GrainReference; | ||
GrainReference grainRef = baseGrain.GrainReference; | ||
Exception errorOccurred; | ||
try | ||
{ | ||
await store.WriteStateAsync(grainTypeName, grainRef, grain.GrainState); | ||
|
||
StorageStatisticsGroup.OnStorageWrite(store, grainTypeName, grainRef, sw.Elapsed); | ||
errorOccurred = null; | ||
} | ||
|
@@ -125,13 +126,14 @@ public async Task ClearStateAsync() | |
{ | ||
const string what = "ClearState"; | ||
Stopwatch sw = Stopwatch.StartNew(); | ||
GrainReference grainRef = grain.GrainReference; | ||
GrainReference grainRef = baseGrain.GrainReference; | ||
try | ||
{ | ||
// Clear (most likely Delete) state from external storage | ||
await store.ClearStateAsync(grainTypeName, grainRef, grain.GrainState); | ||
// Null out the in-memory copy of the state | ||
grain.GrainState.SetAll(null); | ||
|
||
// Reset the in-memory copy of the state | ||
grain.GrainState.State = Activator.CreateInstance(grain.GrainState.State.GetType()); | ||
|
||
// Update counters | ||
StorageStatisticsGroup.OnStorageDelete(store, grainTypeName, grainRef, sw.Elapsed); | ||
|
@@ -159,7 +161,7 @@ private string MakeErrorMsg(string what, Exception exc) | |
if(decoder != null) | ||
decoder.DecodeException(exc, out httpStatusCode, out errorCode, true); | ||
|
||
GrainReference grainReference = grain.GrainReference; | ||
GrainReference grainReference = baseGrain.GrainReference; | ||
return string.Format("Error from storage provider during {0} for grain Type={1} Pk={2} Id={3} Error={4}" + Environment.NewLine + " {5}", | ||
what, grainTypeName, grainReference.GrainId.ToDetailedString(), grainReference, errorCode, TraceLogger.PrintException(exc)); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using Orleans.Core; | ||
|
||
namespace Orleans | ||
{ | ||
internal interface IStatefulGrain | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we need this new interface? Can't Grain have those? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new interface makes easy to access grain state properties. I wonder if there's better way of doing this, and implementing #1060 (comment) will not remove the need in this interface. |
||
{ | ||
IGrainState GrainState { get; } | ||
|
||
void SetStorage(IStorage storage); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
|
||
namespace Orleans.Storage | ||
|
@@ -12,24 +10,20 @@ public interface IMemoryStorageGrain : IGrainWithIntegerKey | |
/// <summary> | ||
/// Async method to cause retrieval of the specified grain state data from memory store. | ||
/// </summary> | ||
/// <param name="stateStore">The name of the store that is used to store this grain state</param> | ||
/// <param name="grainStoreKey">Store key for this grain.</param> | ||
/// <returns>Value promise for the currently stored grain state for the specified grain and the etag of this data.</returns> | ||
Task<Tuple<IDictionary<string, object>, string>> ReadStateAsync(string stateStore, string grainStoreKey); | ||
/// <param name="grainType">Type of this grain [fully qualified class name]</param> | ||
/// <param name="grainId">Grain id for this grain.</param> | ||
/// <returns>Value promise for the currently stored grain state for the specified grain.</returns> | ||
Task<IGrainState> ReadStateAsync(string stateStore, string grainStoreKey); | ||
|
||
/// <summary> | ||
/// Async method to cause update of the specified grain state data into memory store. | ||
/// </summary> | ||
/// <param name="stateStore">The name of the store that is used to store this grain state</param> | ||
/// <param name="grainStoreKey">Store key for this grain.</param> | ||
/// <param name="grainState">New state data to be stored for this grain.</param> | ||
/// <param name="eTag">The previous etag that was read.</param> | ||
/// <returns>Value promise of the etag of the update operation for stored grain state for the specified grain.</returns> | ||
Task<string> WriteStateAsync(string stateStore, string grainStoreKey, IDictionary<string, object> grainState, string eTag); | ||
|
||
/// <summary> | ||
/// Async method to cause deletion of the specified grain state data from memory store. | ||
/// </summary> | ||
/// <returns>Completion promise with new eTag for the update operation for stored grain state for the specified grain.</returns> | ||
Task<string> WriteStateAsync(string grainType, string grainId, IGrainState grainState); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be returning the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ReubenBond Why are you concerned? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I updated the a comment to say something to that effect :) Thanks |
||
|
||
/// <param name="stateStore">The name of the store that is used to store this grain state</param> | ||
/// <param name="grainStoreKey">Store key for this grain.</param> | ||
/// <param name="eTag">The previous etag that was read.</param> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should ETag be here? I think the storage providers which need an ETag should create their own implementation of this interface which includes one. We should give storage providers a
CreateGrainState()
method (or some such) which returns a new instance of theIGrainState
implementation used by the storage provider.The storage provider can mutate the ETag on its implementation instead of returning
Task<string>
.