public override void CreateUninitializedItem(HttpContext context, string id, int timeout) { Debug.Assert(context != null, "Http context is null"); SecUtility.CheckParameter(ref id, true, true, false, ProvidersConfiguration.MaxStringPropertySizeInChars, "id"); if (timeout < 0) { throw new ArgumentException("Parameter timeout must be a non-negative integer!"); } try { TableServiceContext svc = this.CreateDataServiceContext(); var session = new SessionRow(id, this.applicationName) { Lock = 0, Initialized = false, Id = id, Timeout = timeout, ExpiresUtc = DateTime.UtcNow.AddMinutes(timeout) }; // no lock svc.AddObject(this.tableName, session); svc.SaveChangesWithRetries(); } catch (InvalidOperationException e) { throw new ProviderException("Error accessing the data store.", e); } }
private static void ReleaseItemExclusive(TableServiceContext svc, SessionRow session, object lockId) { if ((int)lockId != session.Lock) { // obviously that can happen, but let's see when at least in Debug mode Debug.Assert(false, "Error"); return; } session.ExpiresUtc = DateTime.UtcNow.AddMinutes(session.Timeout); session.Locked = false; svc.UpdateObject(session); svc.SaveChangesWithRetries(); }
public override void SetAndReleaseItemExclusive( HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { Debug.Assert(context != null, "Http context is null"); SecUtility.CheckParameter(ref id, true, true, false, ProvidersConfiguration.MaxStringPropertySizeInChars, "id"); this.providerRetryPolicy(() => { TableServiceContext svc = CreateDataServiceContext(); SessionRow session; if (!newItem) { session = GetSession(id, svc); if (session == null || session.Lock != (int)lockId) { Debug.Assert(false, "Error"); return; } } else { session = new SessionRow(id, this.applicationName); session.Lock = 1; session.LockDateUtc = DateTime.UtcNow; } session.Initialized = true; Debug.Assert(session.Timeout >= 0, "Session timeout is < 0"); session.Timeout = item.Timeout; session.ExpiresUtc = DateTime.UtcNow.AddMinutes(session.Timeout); session.Locked = false; // yes, we always create a new blob here session.BlobName = GetBlobNamePrefix(id) + Guid.NewGuid().ToString("N"); // Serialize the session and write the blob byte[] items, statics; SerializeSession(item, out items, out statics); string serializedItems = Convert.ToBase64String(items); string serializedStatics = Convert.ToBase64String(statics); MemoryStream output = new MemoryStream(); StreamWriter writer = new StreamWriter(output); try { writer.WriteLine(serializedItems); writer.WriteLine(serializedStatics); writer.Flush(); // for us, it shouldn't matter whether newItem is set to true or false // because we always create the entire blob and cannot append to an // existing one this.blobProvider.UploadStream(session.BlobName, output); writer.Close(); output.Close(); } catch (Exception e) { if (!newItem) { ReleaseItemExclusive(svc, session, lockId); } throw new ProviderException("Error accessing the data store.", e); } finally { if (writer != null) { writer.Close(); } if (output != null) { output.Close(); } } if (newItem) { svc.AddObject(this.tableName, session); svc.SaveChangesWithRetries(); } else { // Unlock the session and save changes ReleaseItemExclusive(svc, session, lockId); } }); }