예제 #1
0
        internal LockSession(ILockManagerImplementation manager, string path, object shardingID, string description = null, int?maxAgeSec = null)
        {
            if (path.IsNullOrWhiteSpace())
            {
                throw new LockingException(StringConsts.ARGUMENT_ERROR + "LockSession.ctor(path==null|empty)");
            }

            if (shardingID == null)
            {
                throw new LockingException(StringConsts.ARGUMENT_ERROR + "LockSession.ctor(shardingID==null)");
            }

            Data       = new Server.LockSessionData(new LockSessionID(null), description, maxAgeSec);
            Manager    = manager;
            Path       = path;
            ShardingID = shardingID;

            try
            {
                var shardingHash = shardingID.GetHashCode();

                var zone         = manager.App.GetMetabase().CatalogReg.NavigateZone(Path);
                var primaryZgovs = zone
                                   .FindNearestParentZoneGovernors(iAmZoneGovernor: false, filter: (host) => !host.IsZGovLockFailover, transcendNOC: true)
                                   .OrderBy(host => host.Name)
                                   .ToArray();

                if (primaryZgovs.Length < 1)
                {
                    throw new LockingException(StringConsts.LOCK_SESSION_PATH_LEVEL_NO_ZGOVS_ERROR.Args(Path));
                }

                var failoverZgovs = zone
                                    .FindNearestParentZoneGovernors(iAmZoneGovernor: false, filter: (host) => host.IsZGovLockFailover, transcendNOC: true)
                                    .OrderBy(host => host.Name)
                                    .ToArray();

                if (failoverZgovs.Length > 0 &&
                    (primaryZgovs.Length != failoverZgovs.Length ||
                     !primaryZgovs[0].ParentZone.IsLogicallyTheSame(failoverZgovs[0].ParentZone))
                    )
                {
                    throw new LockingException(StringConsts.LOCK_SESSION_ZGOV_SETUP_ERROR.Args(primaryZgovs[0].ParentZone.RegionPath));
                }

                var idx = (shardingHash & CoreConsts.ABS_HASH_MASK) % primaryZgovs.Length;
                ServerHostPrimary = primaryZgovs[idx].RegionPath;
                if (failoverZgovs.Length > 0)
                {
                    ServerHostSecondary = failoverZgovs[idx].RegionPath;
                }
            }
            catch (Exception error)
            {
                throw new LockingException(StringConsts.LOCK_SESSION_PATH_ERROR.Args(Path, error.ToMessageWithType()), error);
            }
        }
예제 #2
0
        public LockTransactionResult ExecuteLockTransaction(LockSessionData session, LockTransaction transaction)
        {
            var result = executeLockTransaction(session, transaction);

            if (m_InstrumentationEnabled)
            {
                var key = result.Status == LockStatus.TransactionOK ? "OK" //for speed not to concat strings
                                                          : result.Status.ToString() + ':' + result.ErrorCause.ToString();
                m_stat_ExecuteTranCalls.IncrementLong(key);
            }

            return(result);
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
 internal ServerLockSession(LockSessionData data)
 {
     Data = data;
 }