def run(self):
        global vote_result_counter
        global tot_executions
        global tot_executions_latency
        global tot_execution_secs
        global check_latency
        global latency_counter
        global min_execution_secs
        global max_execution_secs
        global requestPermit
        global shouldContinue
        global max_contestant
        global results_lock
        global params_lock
        global availableThreads
        global invocation_params
        num_sp_calls = 0
        while shouldContinue:
            #coordinate so that threads can always block on either semaphores or a request, indicate availability and then wait for a permit
            #to generate a request
            availableThreads.release();
            requestPermit.acquire()
            num_sp_calls = num_sp_calls + 1

            params_lock.acquire();
            params = invocation_params.pop()
            params_lock.release()

            # invokes the stored procedure 'Vote' to cast a vote for some contestant by voter with some phone number
            # times the invocation
            # uses quick parse hack to process the response of the invocation
            # analyzes the processed data to determine if invocation was successful (if not, exits)
            time_before = time.time()
            response = self.proc.call( [params[0], params[1], max_contestant] )
            time_after = time.time()
            if response.status != 1:
                print "Failed to execute!!!"
                exit(-1)
            else:
                # updates statistics about execution count, execution times, vote successes/failures, and latency
                # lock necessary, because any other thread may need to access the same global variables, which could result in inconsistencies without proper thread safety
                results_lock.acquire()
                tot_executions = tot_executions + 1
                table = response.tables[0]
                vote_result = table.tuples[0][0]
                vote_result_counter[vote_result] = vote_result_counter[vote_result] + 1
                if check_latency:
                    execution_time = time_after - time_before
                    tot_executions_latency = tot_executions_latency + 1
                    tot_execution_secs = tot_execution_secs + execution_time

                    if execution_time < min_execution_secs:
                        min_execution_secs = execution_time
                    if execution_time > max_execution_secs:
                        max_execution_secs = execution_time

                    latency_bucket = int(execution_time * 40)
                    if latency_bucket > 8:
                        latency_bucket = 8
                    latency_counter[latency_bucket] = latency_counter[latency_bucket] + 1
                results_lock.release()

# used to call main method of voter client
dataset/ETHPy150Open VoltDB/voltdb-client-python/examples/voter.py/doQueries.run/original