You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: worker.go
    path of file: ./repos/cockroach/pkg/workload/tpcc
    
    the code of the file until where you have to start completion: // Copyright 2017 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package tpcc

import (
	"context"
	"fmt"
	"math"
	"strconv"
	"strings"
	"time"

	"github.com/cockroachdb/cockroach/pkg/util/timeutil"
	"github.com/cockroachdb/cockroach/pkg/workload"
	"github.com/cockroachdb/cockroach/pkg/workload/histogram"
	"github.com/cockroachdb/errors"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"golang.org/x/exp/rand"
)

const (
	// NumWorkersPerWarehouse is the default number of workers per warehouse.
	NumWorkersPerWarehouse = 10
	numConnsPerWarehouse   = 2
)

// tpccTX is an interface for running a TPCC transaction.
type tpccTx interface {
	// run executes the TPCC transaction against the given warehouse ID.
	run(ctx context
    
func (w *worker) run(ctx context.Context) error {
	// 5.2.4.2: the required mix is achieved by selecting each new transaction
	// uniformly at random from a deck whose content guarantees the required
	// transaction mix. Each pass through a deck must be made in a different
	// uniformly random order.
	if w.permIdx == len(w.deckPerm) {
		rand.Shuffle(len(w.deckPerm), func(i, j int) {
			w.deckPerm[i], w.deckPerm[j] = w.deckPerm[j], w.deckPerm[i]
		})
		w.permIdx = 0
	}
	// Move through our permutation slice until its exhausted, using each value to
	// to index into our deck of transactions, which contains indexes into the
	// txInfos / txs slices.
	opIdx := w.deckPerm[w.permIdx]
	txInfo := &w.config.txInfos[opIdx]
	tx := w.txs[opIdx]
	w.permIdx++

	warehouseID := w.warehouse
	// Wait out the entire keying and think time even if the context is
	// expired. This prevents all workers from immediately restarting when
	// the workload's ramp period expires, which can overload a cluster.
	time.Sleep(time.Duration(float64(txInfo.keyingTime) * float64(time.Second) * w.config.waitFraction))

	// Run transactions with a background context because we don't want to
	// cancel them when the context expires. Instead, let them finish normally
	// but don't account for them in the histogram.
	start := timeutil.Now()
	if _, err := tx.run(context.Background(), warehouseID); err != nil {
		w.counters[txInfo.name].error.Inc()
		return errors.Wrapf(err, "error in %s", txInfo.name)
	}
	if ctx.Err() == nil {
		elapsed := timeutil.Since(start)
		// NB: this histogram *should* be named along the lines of
		// `txInfo.name+"_success"` but we already rely on the names and shouldn't
		// change them now.
		w.hists.Get(txInfo.name).Record(elapsed)
	}
	w.counters[txInfo.name].success.Inc()

	// 5.2.5.4: Think time is taken independently from a negative exponential
	// distribution. Think time = -log(r) * u, where r is a uniform random number
	// between 0 and 1 and u is the mean think time per operation.
	// Each distribution is truncated at 10 times its mean value.
	thinkTime := -math.Log(rand.Float64()) * txInfo.thinkTime
	if thinkTime > (txInfo.thinkTime * 10) {
		thinkTime = txInfo.thinkTime * 10
	}
	time.Sleep(time.Duration(thinkTime * float64(time.Second) * w.config.waitFraction))
	return ctx.Err()
}