private void prepareTransaction(EvalContext ctx) { var statements = ctx.Transaction.Statements; for (var i = 0; i < statements.Length; i++) { var statement = statements[i]; statement.Prepare(ctx, i.ToString() + ":/"); } }
private string getDescr(string descr, EvalContext ctx) { if (descr.IsNullOrWhiteSpace()) { descr = ctx.Transaction.Description; } if (descr.IsNullOrWhiteSpace()) { descr = ctx.SessionDescription; } return(descr); }
//warning: this is called under the global lock on NS, do not block private LockTransactionResult executeTransaction(EvalContext ctx, uint appRunTimeSec, double trustLevel) { var status = LockStatus.TransactionOK; var errorCause = LockErrorCause.Unspecified; var statements = ctx.Transaction.Statements; for (var i = 0; i < statements.Length; i++) { var statement = statements[i]; statement.Execute(ctx); if (ctx.Aborted) { status = LockStatus.TransactionError; errorCause = LockErrorCause.Statement; break; } } //now Commit/Rollback all changes if (status == LockStatus.TransactionOK) {//commit foreach (var tbl in ctx.Namespace.m_MutatedTables) { tbl.Commit(ctx.Session); } } else {//rollback foreach (var tbl in ctx.Namespace.m_MutatedTables) { tbl.Rollback(ctx.Session); } } ctx.Namespace.m_MutatedTables.Clear(); return(new LockTransactionResult(ctx.Transaction.ID, App.AsSky().HostName, status, errorCause, ctx.FailedStatement, appRunTimeSec,//passed-in not to calculate under lock trustLevel, ctx.Data)); }
/// <summary> /// Returns named variable value or value array created by this or another session. /// If not found then null is returned /// </summary> public object GetVariable(bool many, EvalContext ctx, string name, bool ignoreThisSession) { DataSlot slot; if (!m_Data.TryGetValue(name, out slot)) { return(null); } var list = slot.Data; if (list == null) { return(null); } if (many) { Variable[] result; if (!ignoreThisSession) { result = list.ToArray(); } else { result = list.Where(i => !i.SessionID.Equals(ctx.SessionID)).ToArray(); } return(result.Length > 0 ? result : null); } //else Single if (list.Count == 0) { return(null); } if (!ignoreThisSession) { return(list[0]); } return(list.FirstOrDefault(i => !i.SessionID.Equals(ctx.SessionID))); }
/// <summary> /// Returns true if named variable exists created by this or another session /// </summary> public bool Exists(EvalContext ctx, string name, object value, bool ignoreThisSession) { DataSlot slot; if (!m_Data.TryGetValue(name, out slot)) { return(false); } var list = slot.Data; if (list == null) { return(false); } if (!ignoreThisSession) { if (value == null) { return(list.Count > 0); } return(list.Any(e => e.Value != null && value.Equals(e.Value))); } for (var i = 0; i < list.Count; i++) { var var = list[i]; if (!var.SessionID.Equals(ctx.SessionID)) { if (value == null) { return(true); } if (var.Value != null && var.Value.Equals(value)) { return(true); } } } return(false); }
/// <summary> /// Deletes named var, true if found and removed /// </summary> public bool DeleteVariable(EvalContext ctx, string name, object value) { DataSlot slot; if (!m_Data.TryGetValue(name, out slot)) { return(false); } var list = slot.Data; if (list == null) { return(false); } var anymatch = list.Any(v => v.SessionID.Equals(ctx.SessionID) && (value == null || value.Equals(v.Value))); if (!anymatch) { return(false); } VarList newList = new VarList(); for (var i = 0; i < list.Count; i++) { var var = list[i]; if (var.SessionID.Equals(ctx.SessionID) && (value == null || value.Equals(var.Value))) { continue;//skip what gets deleted } newList.Add(var); } slot.Change(newList); m_PendingChanges.Add(slot); m_Namespace.m_MutatedTables.Add(this); return(true); }
/// <summary> /// Sets named var /// </summary> public bool SetVariable(EvalContext ctx, string name, object value, string description, DateTime?expirationTimeUTC, bool allowDuplicates) { DataSlot slot; VarList list; if (!m_Data.TryGetValue(name, out slot)) { slot = new DataSlot(); list = new VarList(); var var = new Variable(ctx.SessionID, ctx.Transaction.ID, App.TimeSource.UTCNow, expirationTimeUTC, getDescr(description, ctx), value); list.Add(var); slot.Change(list); m_Data.Add(name, slot); m_PendingChanges.Add(slot); m_Namespace.m_MutatedTables.Add(this); return(true); } list = slot.Data; if (list == null) { list = new VarList(); var var = new Variable(ctx.SessionID, ctx.Transaction.ID, App.TimeSource.UTCNow, expirationTimeUTC, getDescr(description, ctx), value); list.Add(var); slot.Change(list); //20161102 //m_Data.Add(name, slot); m_PendingChanges.Add(slot); m_Namespace.m_MutatedTables.Add(this); return(true); } if (list.Count > 0 && !allowDuplicates) { return(false); } var newList = new VarList(list); var replaced = false; for (var i = 0; i < newList.Count; i++) { var var = newList[i]; if (var.SessionID.Equals(ctx.SessionID)) { var nvar = new Variable(ctx.SessionID, ctx.Transaction.ID, App.TimeSource.UTCNow, expirationTimeUTC, getDescr(description, ctx), value); newList[i] = nvar; replaced = true; break; } } if (!replaced) { var nvar = new Variable(ctx.SessionID, ctx.Transaction.ID, App.TimeSource.UTCNow, expirationTimeUTC, getDescr(description, ctx), value); newList.Add(nvar); } slot.Change(newList); m_PendingChanges.Add(slot); m_Namespace.m_MutatedTables.Add(this); return(true); }
private LockTransactionResult executeLockTransaction(LockSessionData session, LockTransaction transaction) { if (!Running) { return(LockTransactionResult.CallFailed); } Interlocked.Increment(ref m_CurrentServerCalls); if (session == null || transaction == null) { throw new LockingException(StringConsts.ARGUMENT_ERROR + GetType().Name + ".ExecuteLockTransaction(session|transaction==null)"); } var isPing = transaction.Statements == null; if (!isPing && transaction.Namespace.IsNullOrWhiteSpace()) { throw new LockingException(StringConsts.ARGUMENT_ERROR + GetType().Name + ".ExecuteLockTransaction(transaction.Namespace==null|empty)"); } var sapp = App.AsSky(); var currentTrustLevel = CurrentTrustLevel; var appRunTimeSec = (uint)(DateTime.UtcNow - m_StartTimeUTC).TotalSeconds; //insufficient runtime period length or trust level if (transaction.MinimumRequiredRuntimeSec > appRunTimeSec || transaction.MinimumRequiredTrustLevel > currentTrustLevel) { return(new LockTransactionResult(transaction.ID, sapp.HostName, LockStatus.TransactionError, LockErrorCause.MinimumRequirements, null, appRunTimeSec, currentTrustLevel, null)); } var sid = session.ID.ToString(); var ss = m_Sessions.GetOrRegister(sid, (sd) => new ServerLockSession(sd), session); lock (ss) { if (ss.Disposed) { return(new LockTransactionResult(transaction.ID, sapp.HostName, LockStatus.TransactionError, LockErrorCause.SessionExpired, null, appRunTimeSec, currentTrustLevel, null)); } ss.m_LastInteractionUTC = App.TimeSource.UTCNow; if (isPing)//ping just touches session above { return(new LockTransactionResult(transaction.ID, sapp.HostName, LockStatus.TransactionOK, LockErrorCause.Unspecified, null, appRunTimeSec, currentTrustLevel, null)); } var ns = m_Namespaces.GetOrRegister <object>(transaction.Namespace, (_) => new Namespace(App, transaction.Namespace), null); var ectx = new EvalContext(ss, ns, transaction); prepareTransaction(ectx); //prepare is not under the lock LockTransactionResult result; lock (ns) //execute is UNDER THE LOCK result = executeTransaction(ectx, appRunTimeSec, currentTrustLevel); return(result); } }