public void ExecuteCommand(ReplayCommand command)
        {
            LastCommandTime = DateTime.Now;

            if (conn == null)
            {
                try
                {
                    ConnectionInfo.ApplicationName = "WorkloadTools-ReplayWorker";
                    if (MimicApplicationName)
                    {
                        ConnectionInfo.ApplicationName = command.ApplicationName;
                        if (String.IsNullOrEmpty(ConnectionInfo.ApplicationName))
                        {
                            ConnectionInfo.ApplicationName = "WorkloadTools-ReplayWorker";
                        }
                    }
                    InitializeConnection();
                }
                catch (SqlException se)
                {
                    logger.Error(se.Message);
                    logger.Error($"Worker [{Name}] - Unable to acquire the connection. Quitting the ReplayWorker");
                    return;
                }
            }

            if (conn != null)
            {
                while (conn.State == System.Data.ConnectionState.Connecting)
                {
                    if (stopped)
                    {
                        break;
                    }

                    Thread.Sleep(5);
                }
            }

            if (conn == null || (conn.State == System.Data.ConnectionState.Closed) || (conn.State == System.Data.ConnectionState.Broken))
            {
                InitializeConnection();
            }


            // Extract the handle from the prepared statement
            NormalizedSqlText nst = transformer.Normalize(command.CommandText);

            if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_RESET_CONNECTION)
            {
                //Stop(false);
                return;
            }
            else if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_PREPARE)
            {
                command.CommandText = nst.NormalizedText;
            }
            else if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_UNPREPARE || nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_EXECUTE)
            {
                // look up the statement to unprepare in the dictionary
                if (preparedStatements.ContainsKey(nst.Handle))
                {
                    command.CommandText = nst.NormalizedText + " " + preparedStatements[nst.Handle];

                    if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_UNPREPARE)
                    {
                        preparedStatements.Remove(nst.Handle);
                    }
                }
                else
                {
                    return; // statement not found: better return
                }
            }


            try
            {
                if (conn.Database != command.Database)
                {
                    logger.Trace($"Worker [{Name}] - Changing database to {command.Database} ");
                    conn.ChangeDatabase(command.Database);
                }

                // if the command comes with a replay sleep, do it now
                // the amount of milliseconds to sleep is set in
                // FileWorkloadListener
                // The other listeners do not set this value, as they
                // already come with the original timing
                //
                // Don't remove the IF test: even Sleep(0) can end up
                // sleeping for 10ms or more. Sleep guarantees that
                // the current thread sleeps for AT LEAST the amount
                // of milliseconds set.
                if (command.BeforeSleepMilliseconds > 2)
                {
                    Thread.Sleep(command.BeforeSleepMilliseconds);
                }

                using (SqlCommand cmd = new SqlCommand(command.CommandText))
                {
                    cmd.Connection     = conn;
                    cmd.CommandTimeout = QueryTimeoutSeconds;

                    if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_PREPARE)
                    {
                        if (cmd.CommandText == null)
                        {
                            return;
                        }
                        int handle = -1;
                        try
                        {
                            object res = cmd.ExecuteScalar();
                            if (res != null)
                            {
                                handle = (int)res;
                                if (!preparedStatements.ContainsKey(nst.Handle))
                                {
                                    preparedStatements.Add(nst.Handle, handle);
                                }
                            }
                        }
                        catch (NullReferenceException)
                        {
                            throw;
                        }
                    }
                    else if (ConsumeResults)
                    {
                        using (SqlDataReader reader = cmd.ExecuteReader())
                            using (ResultSetConsumer consumer = new ResultSetConsumer(reader))
                            {
                                consumer.Consume();
                            }
                    }
                    else
                    {
                        cmd.ExecuteNonQuery();
                    }
                }

                logger.Trace($"Worker [{Name}] - SUCCES - \n{command.CommandText}");
                if (commandCount > 0 && commandCount % WorkerStatsCommandCount == 0)
                {
                    var seconds = (DateTime.Now - previousCPSComputeTime).TotalSeconds;
                    var cps     = (commandCount - previousCommandCount) / ((seconds == 0) ? 1 : seconds);
                    previousCPSComputeTime = DateTime.Now;
                    previousCommandCount   = commandCount;

                    if (DisplayWorkerStats)
                    {
                        commandsPerSecond.Add((int)cps);
                        cps = commandsPerSecond.Average();

                        logger.Info($"Worker [{Name}] - {commandCount} commands executed.");
                        logger.Info($"Worker [{Name}] - {Commands.Count} commands pending.");
                        logger.Info($"Worker [{Name}] - {(int)cps} commands per second.");
                    }
                }
            }
            catch (SqlException e)
            {
                // handle timeouts
                if (e.Number == -2)
                {
                    RaiseTimeoutEvent(command.CommandText, conn);
                }
                else
                {
                    RaiseErrorEvent(command, e.Message, conn);
                }

                if (StopOnError)
                {
                    logger.Error($"Worker[{Name}] - Error: \n{command.CommandText}");
                    throw;
                }
                else
                {
                    logger.Trace($"Worker [{Name}] - Error: {command.CommandText}");
                    logger.Warn($"Worker [{Name}] - Error: {e.Message}");
                    logger.Trace(e.StackTrace);
                }
            }
            catch (Exception e)
            {
                if (StopOnError)
                {
                    logger.Error($"Worker[{Name}] - Error: \n{command.CommandText}");
                    throw;
                }
                else
                {
                    logger.Error($"Worker [{Name}] - Error: {e.Message}");
                    logger.Error(e.StackTrace);
                }
            }
        }
Example #2
0
        public NormalizedSqlText Normalize(string command)
        {
            NormalizedSqlText result = new NormalizedSqlText(command);

            int num = 0;

            if (command.Contains("sp_reset_connection"))
            {
                result.CommandType = NormalizedSqlText.CommandTypeEnum.SP_RESET_CONNECTION;
                return(result);
            }


            Match match3 = _prepareSql.Match(command);

            if (match3.Success)
            {
                if (match3.Groups["preptype"].ToString().ToLower() == "sp_prepare")
                {
                    if (match3.Groups["stmtnum"].Success)
                    {
                        num = !(match3.Groups["stmtnum"].ToString() == "NULL") ? Convert.ToInt32(match3.Groups["stmtnum"].ToString()) : 0;
                    }
                    string sql    = match3.Groups["remaining"].ToString();
                    Match  match4 = _preppedSqlStatement.Match(sql);
                    if (match4.Success)
                    {
                        sql = match4.Groups["statement"].ToString();
                        sql = _doubleApostrophe.Replace(sql, "'${string}'");
                        result.Statement = sql;
                        string originalHandle;
                        result.NormalizedText = RemoveFirstP1(result.OriginalText, out originalHandle);
                        if (int.TryParse(originalHandle, out int n))
                        {
                            result.Handle = n;
                        }
                        else
                        {
                            result.Handle = num;
                        }
                        result.CommandType = NormalizedSqlText.CommandTypeEnum.SP_PREPARE;
                    }
                }
                return(result);
            }

            Match match5 = _execPrepped.Match(command);

            if (match5.Success)
            {
                num           = Convert.ToInt32(match5.Groups["stmtnum"].ToString());
                result.Handle = num;
                string textWithPlaceHolder = RemoveFirstPrepStatementNum(result.Statement, out string originalHandle);
                if (int.TryParse(originalHandle, out int n))
                {
                    result.Handle = n;
                }
                else
                {
                    result.Handle = num;
                }
                result.Statement      = textWithPlaceHolder;
                result.NormalizedText = textWithPlaceHolder;
                result.CommandType    = NormalizedSqlText.CommandTypeEnum.SP_EXECUTE;
                return(result);
            }

            Match match6 = _execUnprep.Match(command);

            if (match6.Success)
            {
                num                   = Convert.ToInt32(match6.Groups["stmtnum"].ToString());
                result.Handle         = num;
                result.Statement      = "EXEC sp_unprepare §";
                result.NormalizedText = "EXEC sp_unprepare §";
                result.CommandType    = NormalizedSqlText.CommandTypeEnum.SP_UNPREPARE;
                return(result);
            }


            return(result);
        }
Example #3
0
        public void ExecuteCommand(ReplayCommand command)
        {
            LastCommandTime = DateTime.Now;

            if (conn == null)
            {
                try
                {
                    ConnectionInfo.ApplicationName = "WorkloadTools-ReplayWorker";
                    if (MIMIC_APPLICATION_NAME)
                    {
                        ConnectionInfo.ApplicationName = command.ApplicationName;
                        if (String.IsNullOrEmpty(ConnectionInfo.ApplicationName))
                        {
                            ConnectionInfo.ApplicationName = "WorkloadTools-ReplayWorker";
                        }
                    }
                    InitializeConnection();
                }
                catch (SqlException se)
                {
                    logger.Error(se.Message);
                    logger.Error(String.Format("Worker [{0}] - Unable to acquire the connection. Quitting the ReplayWorker", Name));
                    return;
                }
            }

            if (conn != null)
            {
                while (conn.State == System.Data.ConnectionState.Connecting)
                {
                    if (stopped)
                    {
                        break;
                    }

                    Thread.Sleep(5);
                }
            }

            if (conn == null || (conn.State == System.Data.ConnectionState.Closed) || (conn.State == System.Data.ConnectionState.Broken))
            {
                conn.ConnectionString += ";MultipleActiveResultSets=true;";
                conn.Open();
            }


            // Extract the handle from the prepared statement
            NormalizedSqlText nst = transformer.Normalize(command.CommandText);

            if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_RESET_CONNECTION)
            {
                //Stop(false);
                return;
            }
            else if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_PREPARE)
            {
                command.CommandText = nst.NormalizedText;
            }
            else if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_UNPREPARE || nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_EXECUTE)
            {
                // look up the statement to unprepare in the dictionary
                if (preparedStatements.ContainsKey(nst.Handle))
                {
                    command.CommandText = nst.NormalizedText + " " + preparedStatements[nst.Handle];

                    if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_UNPREPARE)
                    {
                        preparedStatements.Remove(nst.Handle);
                    }
                }
                else
                {
                    return; // statement not found: better return
                }
            }


            try
            {
                if (conn.Database != command.Database)
                {
                    logger.Trace(String.Format("Worker [{0}] - Changing database to {1} ", Name, command.Database));
                    conn.ChangeDatabase(command.Database);
                }

                using (SqlCommand cmd = new SqlCommand(command.CommandText))
                {
                    cmd.Connection     = conn;
                    cmd.CommandTimeout = DEFAULT_QUERY_TIMEOUT_SECONDS;

                    if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_PREPARE)
                    {
                        if (cmd.CommandText == null)
                        {
                            return;
                        }
                        int handle = -1;
                        try
                        {
                            handle = (int)cmd.ExecuteScalar();
                            if (!preparedStatements.ContainsKey(nst.Handle))
                            {
                                preparedStatements.Add(nst.Handle, handle);
                            }
                        }
                        catch (NullReferenceException)
                        {
                            throw;
                        }
                    }
                    else if (CONSUME_RESULTS)
                    {
                        using (SqlDataReader reader = cmd.ExecuteReader())
                            using (ResultSetConsumer consumer = new ResultSetConsumer(reader))
                            {
                                consumer.Consume();
                            }
                    }
                    else
                    {
                        cmd.ExecuteNonQuery();
                    }
                }

                logger.Trace(String.Format("Worker [{0}] - SUCCES - \n{1}", Name, command.CommandText));
                if (commandCount > 0 && commandCount % WORKLOAD_INFO_COMMAND_COUNT == 0)
                {
                    var seconds = (DateTime.Now - previousCPSComputeTime).TotalSeconds;
                    var cps     = (commandCount - previousCommandCount) / ((seconds == 0) ? 1 : seconds);
                    previousCPSComputeTime = DateTime.Now;
                    previousCommandCount   = commandCount;

                    if (COMPUTE_AVERAGE_STATS)
                    {
                        commandsPerSecond.Add((int)cps);
                        cps = commandsPerSecond.Average();
                    }

                    logger.Info(String.Format("Worker [{0}] - {1} commands executed.", Name, commandCount));
                    logger.Info(String.Format("Worker [{0}] - {1} commands pending.", Name, Commands.Count));
                    logger.Info(String.Format("Worker [{0}] - {1} commands per second.", Name, (int)cps));
                }
            }
            catch (SqlException e)
            {
                // handle timeouts
                if (e.Number == -2)
                {
                    RaiseTimeoutEvent(command.CommandText, conn);
                }

                if (StopOnError)
                {
                    logger.Error(String.Format("Worker[{0}] - Error: \n{1}", Name, command.CommandText));
                    throw;
                }
                else
                {
                    logger.Trace(String.Format("Worker [{0}] - Error: {1}", Name, command.CommandText));
                    logger.Warn(String.Format("Worker [{0}] - Error: {1}", Name, e.Message));
                    logger.Trace(e.StackTrace);
                }
            }
            catch (Exception e)
            {
                if (StopOnError)
                {
                    logger.Error(String.Format("Worker[{0}] - Error: \n{1}", Name, command.CommandText));
                    throw;
                }
                else
                {
                    logger.Error(String.Format("Worker [{0}] - Error: {1}", Name, e.Message));
                    logger.Error(e.StackTrace);
                }
            }
        }
        public void ExecuteCommand(ReplayCommand command)
        {
            LastCommandTime = DateTime.Now;

            if (conn == null)
            {
                try
                {
                    ConnectionInfo.ApplicationName = "WorkloadTools-ReplayWorker";
                    if (MimicApplicationName)
                    {
                        ConnectionInfo.ApplicationName = command.ApplicationName;
                        if (String.IsNullOrEmpty(ConnectionInfo.ApplicationName))
                        {
                            ConnectionInfo.ApplicationName = "WorkloadTools-ReplayWorker";
                        }
                    }
                    InitializeConnection();
                }
                catch (SqlException se)
                {
                    logger.Error(se.Message);
                    logger.Error($"Worker [{Name}] - Unable to acquire the connection. Quitting the ReplayWorker");
                    return;
                }
            }

            if (conn != null)
            {
                while (conn.State == System.Data.ConnectionState.Connecting)
                {
                    if (stopped)
                    {
                        break;
                    }

                    Thread.Sleep(5);
                }
            }

            if (conn == null || (conn.State == System.Data.ConnectionState.Closed) || (conn.State == System.Data.ConnectionState.Broken))
            {
                InitializeConnection();
            }


            // Extract the handle from the prepared statement
            NormalizedSqlText nst = transformer.Normalize(command.CommandText);

            if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_RESET_CONNECTION)
            {
                //Stop(false);
                return;
            }
            else if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_PREPARE)
            {
                command.CommandText = nst.NormalizedText;
            }
            else if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_UNPREPARE || nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_EXECUTE)
            {
                // look up the statement to unprepare in the dictionary
                if (preparedStatements.ContainsKey(nst.Handle))
                {
                    command.CommandText = nst.NormalizedText + " " + preparedStatements[nst.Handle];

                    if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_UNPREPARE)
                    {
                        preparedStatements.Remove(nst.Handle);
                    }
                }
                else
                {
                    return; // statement not found: better return
                }
            }


            try
            {
                // Try to remap the database according to the database map
                if (DatabaseMap.ContainsKey(command.Database))
                {
                    command.Database = DatabaseMap[command.Database];
                }

                if (conn.Database != command.Database)
                {
                    logger.Trace($"Worker [{Name}] - Changing database to {command.Database} ");
                    conn.ChangeDatabase(command.Database);
                }

                // if the command comes with a replay offset, do it now
                // the offset in milliseconds is set in
                // FileWorkloadListener
                // The other listeners do not set this value, as they
                // already come with the original timing
                if (command.ReplayOffset > 0)
                {
                    // I am using 7 here as an average compensation for sleep
                    // fluctuations due to Windows preemptive scheduling
                    while ((DateTime.Now - StartTime).TotalMilliseconds < command.ReplayOffset - 7)
                    {
                        // Thread.Sleep will not sleep exactly 1 millisecond.
                        // It will yield the current thread and put it back
                        // in the runnable queue once the sleep delay has expired.
                        // This means that the actual sleep time before the
                        // current thread gains back control can be much higher
                        // (15 milliseconds or more)
                        // However we do not need to be super precise here:
                        // each command has a requested offset from the beginning
                        // of the workload and this class does its best to respect it.
                        // If the previous commands take longer in the target environment
                        // the offset cannot be respected and the command will execute
                        // without further waits, but there is no way to recover
                        // the delay that has built up to that point.
                        Thread.Sleep(1);
                    }
                }

                using (SqlCommand cmd = new SqlCommand(command.CommandText))
                {
                    cmd.Connection     = conn;
                    cmd.CommandTimeout = QueryTimeoutSeconds;

                    if (nst.CommandType == NormalizedSqlText.CommandTypeEnum.SP_PREPARE)
                    {
                        if (cmd.CommandText == null)
                        {
                            return;
                        }
                        int handle = -1;
                        try
                        {
                            object res = cmd.ExecuteScalar();
                            if (res != null)
                            {
                                handle = (int)res;
                                if (!preparedStatements.ContainsKey(nst.Handle))
                                {
                                    preparedStatements.Add(nst.Handle, handle);
                                }
                            }
                        }
                        catch (NullReferenceException)
                        {
                            throw;
                        }
                    }
                    else if (ConsumeResults)
                    {
                        using (SqlDataReader reader = cmd.ExecuteReader())
                            using (ResultSetConsumer consumer = new ResultSetConsumer(reader))
                            {
                                consumer.Consume();
                            }
                    }
                    else
                    {
                        cmd.ExecuteNonQuery();
                    }
                }

                logger.Trace($"Worker [{Name}] - SUCCES - \n{command.CommandText}");
                if (commandCount > 0 && commandCount % WorkerStatsCommandCount == 0)
                {
                    var seconds = (DateTime.Now - previousCPSComputeTime).TotalSeconds;
                    var cps     = (commandCount - previousCommandCount) / ((seconds == 0) ? 1 : seconds);
                    previousCPSComputeTime = DateTime.Now;
                    previousCommandCount   = commandCount;

                    if (DisplayWorkerStats)
                    {
                        commandsPerSecond.Add((int)cps);
                        cps = commandsPerSecond.Average();

                        logger.Info($"Worker [{Name}] - {commandCount} commands executed.");
                        logger.Info($"Worker [{Name}] - {Commands.Count} commands pending.");
                        logger.Info($"Worker [{Name}] - Last Event Sequence: {command.EventSequence}");
                        logger.Info($"Worker [{Name}] - {(int)cps} commands per second.");
                    }
                }
            }
            catch (SqlException e)
            {
                // handle timeouts
                if (e.Number == -2)
                {
                    RaiseTimeoutEvent(command.CommandText, conn);
                }
                else
                {
                    RaiseErrorEvent(command, e.Message, conn);
                }

                if (StopOnError)
                {
                    logger.Error($"Worker[{Name}] - Sequence[{command.EventSequence}] - Error: \n{command.CommandText}");
                    throw;
                }
                else
                {
                    logger.Trace($"Worker [{Name}] - Sequence[{command.EventSequence}] - Error: {command.CommandText}");
                    logger.Warn($"Worker [{Name}] - Sequence[{command.EventSequence}] - Error: {e.Message}");
                    logger.Trace(e.StackTrace);
                }
            }
            catch (Exception e)
            {
                if (StopOnError)
                {
                    logger.Error($"Worker[{Name}] - Sequence[{command.EventSequence}] - Error: \n{command.CommandText}");
                    throw;
                }
                else
                {
                    logger.Error($"Worker [{Name}] - Sequence[{command.EventSequence}] - Error: {e.Message}");
                    logger.Error(e.StackTrace);
                }
            }
        }