package main

import (
	"fmt"
	"math/rand"
	"sync"
	"sync/atomic"
	"time"

	"database/sql"
	_ "github.com/go-sql-driver/mysql"
)

const GOROUTINE = 64

func prepare() {
	db, err := sql.Open("mysql", "root@tcp(127.0.0.1:4000)/test")
	if err != nil {
		panic(err)
	}
	defer db.Close()

	if _, err = db.Exec("create table `t1` (`a` int(11) not null auto_increment,`b` int(11) default null,primark key (`a`)"); err != nil {
		panic(err)
	}
	if _, err = db.Exec(`create table t2 (
		a int(11) not null auto_increment,
		b int(11),
		primary key (a),
		key i_b (b)
	)`); err != nil {
		panic(err)
	}

	var ok, fail uint64
	var wg sync.WaitGroup
	wg.Add(2 * GOROUTINE)
	for i := 0; i < GOROUTINE; i++ {
		go run(&wg, db, &ok, &fail, "t1")
	}
	for i := 0; i < GOROUTINE; i++ {
		go run(&wg, db, &ok, &fail, "t2")
	}
	go message(&ok, &fail)

	wg.Wait()
}

func message(ok, fail *uint64) {
	for i := 0; ; i++ {
		time.Sleep(time.Second)
		if i%10 == 0 {
			fmt.Println("QPS = ", atomic.LoadUint64(ok), "err = ", atomic.LoadUint64(fail))
			atomic.StoreUint64(ok, 0)
			atomic.StoreUint64(fail, 0)
		}
	}
}

func run(wg *sync.WaitGroup, db *sql.DB, ok, fail *uint64, tbl string) {
	defer wg.Done()
	for i := 0; i < 1000000; i++ {
		_, err := db.Exec(fmt.Sprintf("insert into %s (b) values (%d)", tbl, rand.Intn(200)))
		if err != nil {
			fmt.Println(err)
			atomic.AddUint64(fail, 1)
		} else {
			atomic.AddUint64(ok, 1)
		}
	}
}
