Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //This application tests the behaviour of mysql's lock functions: get_lock and release_lock.
- package main
- import (
- "database/sql"
- "fmt"
- "log"
- "time"
- _ "github.com/go-sql-driver/mysql"
- )
- var db *sql.DB
- func main() {
- db = open()
- //comment the func which you want to test
- normal()
- // lockTimeOut()
- // shortConnLife()
- }
- type Params struct {
- name string
- numGetters int
- programDuration time.Duration
- maxConnLifeTime time.Duration
- lockTimeout int
- holdLockDuration time.Duration
- }
- // normal tests the behaviour of lock function where everything works as expected
- //
- // Output:
- // 2018/12/24 11:28:36 {name:lock1 numGetters:2 programDuration:20000000000 maxConnLifeTime:90000000000 lockTimeout:10 holdLockDuration:5000000000}
- // 2018/12/24 11:28:36 Process 1: trying to get lock
- // 2018/12/24 11:28:36 Process 0: trying to get lock
- // 2018/12/24 11:28:36 Process 0: get_lock result: 1
- // 2018/12/24 11:28:37 tock
- // 2018/12/24 11:28:38 tick
- // 2018/12/24 11:28:39 tock
- // 2018/12/24 11:28:40 tick
- // 2018/12/24 11:28:41 Process 0: releasing lock
- // 2018/12/24 11:28:41 Process 1: get_lock result: 1
- // 2018/12/24 11:28:41 Process 0: release result 1
- // 2018/12/24 11:28:41 Process 0: ending
- // 2018/12/24 11:28:41 tock
- // 2018/12/24 11:28:42 tick
- // 2018/12/24 11:28:43 tock
- // 2018/12/24 11:28:44 tick
- // 2018/12/24 11:28:45 tock
- // 2018/12/24 11:28:46 Process 1: releasing lock
- // 2018/12/24 11:28:46 Process 1: release result 1
- // 2018/12/24 11:28:46 Process 1: ending
- // 2018/12/24 11:28:46 tick
- // ...
- // 2018/12/24 11:28:55 tock
- // 2018/12/24 11:28:56 ending program
- func normal() {
- getLockTest(Params{
- name: "lock1",
- numGetters: 2,
- programDuration: 20 * time.Second,
- maxConnLifeTime: 90 * time.Second,
- lockTimeout: 10,
- holdLockDuration: 5 * time.Second,
- })
- }
- // shortConnLife tests what happens if connection is the pool are closed before releaseing lock.
- // As expected, lock is released while the process still thinks it has the lock.
- //
- // Output:
- // 2018/12/24 11:29:54 {name:lock1 numGetters:2 programDuration:20000000000 maxConnLifeTime:3000000000 lockTimeout:10 holdLockDuration:7000000000}
- // 2018/12/24 11:29:54 Process 1: trying to get lock
- // 2018/12/24 11:29:54 Process 0: trying to get lock
- // 2018/12/24 11:29:54 Process 1: get_lock result: 1
- // 2018/12/24 11:29:55 tock
- // 2018/12/24 11:29:56 tick
- // 2018/12/24 11:29:57 tock
- // 2018/12/24 11:29:57 Process 0: get_lock result: 1
- // 2018/12/24 11:29:58 tick
- // 2018/12/24 11:29:59 tock
- // 2018/12/24 11:30:00 tick
- // 2018/12/24 11:30:01 Process 1: releasing lock
- // 2018/12/24 11:30:01 Process 1: release res is nil
- // 2018/12/24 11:30:01 Process 1: ending
- // 2018/12/24 11:30:01 tock
- // 2018/12/24 11:30:02 tick
- // 2018/12/24 11:30:03 tock
- // 2018/12/24 11:30:04 Process 0: releasing lock
- // 2018/12/24 11:30:04 Process 0: release res is nil
- // 2018/12/24 11:30:04 Process 0: ending
- // 2018/12/24 11:30:04 tick
- // ...
- // 2018/12/24 11:30:13 tock
- // 2018/12/24 11:30:14 ending program
- func shortConnLife() {
- getLockTest(Params{
- name: "lock1",
- numGetters: 2,
- programDuration: 20 * time.Second,
- maxConnLifeTime: 3 * time.Second,
- lockTimeout: 10,
- holdLockDuration: 7 * time.Second,
- })
- }
- // lockTimeOut tests what happens the lock time outs while the process still has the lock.
- //
- // Output:
- // 2018/12/24 11:31:16 {name:lock1 numGetters:2 programDuration:20000000000 maxConnLifeTime:90000000000 lockTimeout:3 holdLockDuration:10000000000}
- // 2018/12/24 11:31:16 Process 0: trying to get lock
- // 2018/12/24 11:31:16 Process 1: trying to get lock
- // 2018/12/24 11:31:16 Process 0: get_lock result: 1
- // 2018/12/24 11:31:17 tock
- // 2018/12/24 11:31:18 tick
- // 2018/12/24 11:31:19 tock
- // 2018/12/24 11:31:19 Process 1: get_lock result: 0
- // 2018/12/24 11:31:20 tick
- // 2018/12/24 11:31:20 Process 1: trying to get lock
- // 2018/12/24 11:31:20 Process 1: get_lock result: 1
- // 2018/12/24 11:31:21 tock
- // 2018/12/24 11:31:22 tick
- // 2018/12/24 11:31:23 tock
- // 2018/12/24 11:31:24 tick
- // 2018/12/24 11:31:25 tock
- // 2018/12/24 11:31:26 Process 0: releasing lock
- // 2018/12/24 11:31:26 Process 0: release result 0
- // 2018/12/24 11:31:26 Process 0: ending
- // 2018/12/24 11:31:26 tick
- // 2018/12/24 11:31:27 tock
- // 2018/12/24 11:31:28 tick
- // 2018/12/24 11:31:29 tock
- // 2018/12/24 11:31:30 Process 1: releasing lock
- // 2018/12/24 11:31:30 Process 1: release result 1
- // 2018/12/24 11:31:30 Process 1: ending
- // 2018/12/24 11:31:30 tick
- // 2018/12/24 11:31:31 tock
- // 2018/12/24 11:31:32 tick
- // 2018/12/24 11:31:33 tock
- // 2018/12/24 11:31:34 tick
- // 2018/12/24 11:31:35 tock
- // 2018/12/24 11:31:36 ending program
- func lockTimeOut() {
- getLockTest(Params{
- name: "lock1",
- numGetters: 2,
- programDuration: 20 * time.Second,
- maxConnLifeTime: 90 * time.Second,
- lockTimeout: 3,
- holdLockDuration: 10 * time.Second,
- })
- }
- //getLockTest
- func getLockTest(p Params) error {
- log.Printf("%+v", p)
- db.SetConnMaxLifetime(p.maxConnLifeTime)
- for i := 0; i < p.numGetters; i++ {
- go getLock(i, p.name, p.lockTimeout, p.holdLockDuration)
- }
- go func() {
- var tick bool
- var tmap = map[bool]string{true: "tick", false: "tock"}
- for {
- time.Sleep(time.Second)
- log.Print(tmap[tick])
- tick = !tick
- }
- }()
- time.Sleep(p.programDuration)
- log.Print("ending program")
- return nil
- }
- func getLock(i int, name string, lockTimeout int, holdLockDuration time.Duration) {
- q := fmt.Sprintf("SELECT GET_LOCK('%s',%d)", name, lockTimeout)
- var res *int
- for range time.After(time.Second) {
- log.Printf("Process %d: trying to get lock", i)
- err := db.QueryRow(q).Scan(&res)
- if err != nil {
- log.Printf("Process %d: QueryRow error: %s", i, err.Error())
- }
- log.Printf("Process %d: get_lock result: %d", i, *res)
- if *res == 1 {
- <-time.After(holdLockDuration)
- log.Printf("Process %d: releasing lock", i)
- err := db.QueryRow(fmt.Sprintf("SELECT RELEASE_LOCK('%s')", name)).Scan(&res)
- //Returns 1 if the lock was released, 0 if the lock was not established by this thread
- //(in which case the lock is not released), and NULL if the named lock did not exist.
- //The lock does not exist if it was never obtained by a call to GET_LOCK() or if it
- //has previously been released.
- if err != nil {
- log.Printf("Process %d: release error: %s", i, err.Error())
- } else if res == nil {
- log.Printf("Process %d: release res is nil", i)
- } else {
- log.Printf("Process %d: release result %d", i, *res)
- }
- break
- }
- }
- log.Printf("Process %d: ending", i)
- }
- type SQLConnection struct {
- Domain string
- Port int
- Username string
- Password string
- Database string
- }
- func open() *sql.DB {
- sc := SQLConnection{
- Domain: "127.0.0.1",
- Port: 3306,
- Username: "root",
- Password: "root",
- Database: "benchmark",
- }
- // get connection string
- connStr := fmt.Sprintf(
- //FIXME tls
- "%s:%s@tcp(%s:%d)/%s",
- sc.Username,
- sc.Password,
- sc.Domain,
- sc.Port,
- sc.Database,
- )
- db, err := sql.Open("mysql", connStr)
- if err != nil {
- panic(fmt.Sprintf("conn error: %s", err.Error()))
- }
- return db
- }
Add Comment
Please, Sign In to add comment