Guest User

Untitled

a guest
Dec 24th, 2018
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.97 KB | None | 0 0
  1. //This application tests the behaviour of mysql's lock functions: get_lock and release_lock.
  2. package main
  3.  
  4. import (
  5. "database/sql"
  6. "fmt"
  7. "log"
  8. "time"
  9.  
  10. _ "github.com/go-sql-driver/mysql"
  11. )
  12.  
  13. var db *sql.DB
  14.  
  15. func main() {
  16. db = open()
  17. //comment the func which you want to test
  18. normal()
  19. // lockTimeOut()
  20. // shortConnLife()
  21.  
  22. }
  23.  
  24. type Params struct {
  25. name string
  26. numGetters int
  27.  
  28. programDuration time.Duration
  29. maxConnLifeTime time.Duration
  30. lockTimeout int
  31. holdLockDuration time.Duration
  32. }
  33.  
  34. // normal tests the behaviour of lock function where everything works as expected
  35. //
  36. // Output:
  37. // 2018/12/24 11:28:36 {name:lock1 numGetters:2 programDuration:20000000000 maxConnLifeTime:90000000000 lockTimeout:10 holdLockDuration:5000000000}
  38. // 2018/12/24 11:28:36 Process 1: trying to get lock
  39. // 2018/12/24 11:28:36 Process 0: trying to get lock
  40. // 2018/12/24 11:28:36 Process 0: get_lock result: 1
  41. // 2018/12/24 11:28:37 tock
  42. // 2018/12/24 11:28:38 tick
  43. // 2018/12/24 11:28:39 tock
  44. // 2018/12/24 11:28:40 tick
  45. // 2018/12/24 11:28:41 Process 0: releasing lock
  46. // 2018/12/24 11:28:41 Process 1: get_lock result: 1
  47. // 2018/12/24 11:28:41 Process 0: release result 1
  48. // 2018/12/24 11:28:41 Process 0: ending
  49. // 2018/12/24 11:28:41 tock
  50. // 2018/12/24 11:28:42 tick
  51. // 2018/12/24 11:28:43 tock
  52. // 2018/12/24 11:28:44 tick
  53. // 2018/12/24 11:28:45 tock
  54. // 2018/12/24 11:28:46 Process 1: releasing lock
  55. // 2018/12/24 11:28:46 Process 1: release result 1
  56. // 2018/12/24 11:28:46 Process 1: ending
  57. // 2018/12/24 11:28:46 tick
  58. // ...
  59. // 2018/12/24 11:28:55 tock
  60. // 2018/12/24 11:28:56 ending program
  61. func normal() {
  62. getLockTest(Params{
  63. name: "lock1",
  64. numGetters: 2,
  65. programDuration: 20 * time.Second,
  66. maxConnLifeTime: 90 * time.Second,
  67. lockTimeout: 10,
  68. holdLockDuration: 5 * time.Second,
  69. })
  70. }
  71.  
  72. // shortConnLife tests what happens if connection is the pool are closed before releaseing lock.
  73. // As expected, lock is released while the process still thinks it has the lock.
  74. //
  75. // Output:
  76. // 2018/12/24 11:29:54 {name:lock1 numGetters:2 programDuration:20000000000 maxConnLifeTime:3000000000 lockTimeout:10 holdLockDuration:7000000000}
  77. // 2018/12/24 11:29:54 Process 1: trying to get lock
  78. // 2018/12/24 11:29:54 Process 0: trying to get lock
  79. // 2018/12/24 11:29:54 Process 1: get_lock result: 1
  80. // 2018/12/24 11:29:55 tock
  81. // 2018/12/24 11:29:56 tick
  82. // 2018/12/24 11:29:57 tock
  83. // 2018/12/24 11:29:57 Process 0: get_lock result: 1
  84. // 2018/12/24 11:29:58 tick
  85. // 2018/12/24 11:29:59 tock
  86. // 2018/12/24 11:30:00 tick
  87. // 2018/12/24 11:30:01 Process 1: releasing lock
  88. // 2018/12/24 11:30:01 Process 1: release res is nil
  89. // 2018/12/24 11:30:01 Process 1: ending
  90. // 2018/12/24 11:30:01 tock
  91. // 2018/12/24 11:30:02 tick
  92. // 2018/12/24 11:30:03 tock
  93. // 2018/12/24 11:30:04 Process 0: releasing lock
  94. // 2018/12/24 11:30:04 Process 0: release res is nil
  95. // 2018/12/24 11:30:04 Process 0: ending
  96. // 2018/12/24 11:30:04 tick
  97. // ...
  98. // 2018/12/24 11:30:13 tock
  99. // 2018/12/24 11:30:14 ending program
  100. func shortConnLife() {
  101. getLockTest(Params{
  102. name: "lock1",
  103. numGetters: 2,
  104. programDuration: 20 * time.Second,
  105. maxConnLifeTime: 3 * time.Second,
  106. lockTimeout: 10,
  107. holdLockDuration: 7 * time.Second,
  108. })
  109. }
  110.  
  111. // lockTimeOut tests what happens the lock time outs while the process still has the lock.
  112. //
  113. // Output:
  114. // 2018/12/24 11:31:16 {name:lock1 numGetters:2 programDuration:20000000000 maxConnLifeTime:90000000000 lockTimeout:3 holdLockDuration:10000000000}
  115. // 2018/12/24 11:31:16 Process 0: trying to get lock
  116. // 2018/12/24 11:31:16 Process 1: trying to get lock
  117. // 2018/12/24 11:31:16 Process 0: get_lock result: 1
  118. // 2018/12/24 11:31:17 tock
  119. // 2018/12/24 11:31:18 tick
  120. // 2018/12/24 11:31:19 tock
  121. // 2018/12/24 11:31:19 Process 1: get_lock result: 0
  122. // 2018/12/24 11:31:20 tick
  123. // 2018/12/24 11:31:20 Process 1: trying to get lock
  124. // 2018/12/24 11:31:20 Process 1: get_lock result: 1
  125. // 2018/12/24 11:31:21 tock
  126. // 2018/12/24 11:31:22 tick
  127. // 2018/12/24 11:31:23 tock
  128. // 2018/12/24 11:31:24 tick
  129. // 2018/12/24 11:31:25 tock
  130. // 2018/12/24 11:31:26 Process 0: releasing lock
  131. // 2018/12/24 11:31:26 Process 0: release result 0
  132. // 2018/12/24 11:31:26 Process 0: ending
  133. // 2018/12/24 11:31:26 tick
  134. // 2018/12/24 11:31:27 tock
  135. // 2018/12/24 11:31:28 tick
  136. // 2018/12/24 11:31:29 tock
  137. // 2018/12/24 11:31:30 Process 1: releasing lock
  138. // 2018/12/24 11:31:30 Process 1: release result 1
  139. // 2018/12/24 11:31:30 Process 1: ending
  140. // 2018/12/24 11:31:30 tick
  141. // 2018/12/24 11:31:31 tock
  142. // 2018/12/24 11:31:32 tick
  143. // 2018/12/24 11:31:33 tock
  144. // 2018/12/24 11:31:34 tick
  145. // 2018/12/24 11:31:35 tock
  146. // 2018/12/24 11:31:36 ending program
  147. func lockTimeOut() {
  148. getLockTest(Params{
  149. name: "lock1",
  150. numGetters: 2,
  151. programDuration: 20 * time.Second,
  152. maxConnLifeTime: 90 * time.Second,
  153. lockTimeout: 3,
  154. holdLockDuration: 10 * time.Second,
  155. })
  156. }
  157.  
  158. //getLockTest
  159. func getLockTest(p Params) error {
  160. log.Printf("%+v", p)
  161. db.SetConnMaxLifetime(p.maxConnLifeTime)
  162.  
  163. for i := 0; i < p.numGetters; i++ {
  164. go getLock(i, p.name, p.lockTimeout, p.holdLockDuration)
  165. }
  166.  
  167. go func() {
  168. var tick bool
  169. var tmap = map[bool]string{true: "tick", false: "tock"}
  170. for {
  171. time.Sleep(time.Second)
  172. log.Print(tmap[tick])
  173. tick = !tick
  174. }
  175. }()
  176. time.Sleep(p.programDuration)
  177. log.Print("ending program")
  178. return nil
  179. }
  180.  
  181. func getLock(i int, name string, lockTimeout int, holdLockDuration time.Duration) {
  182. q := fmt.Sprintf("SELECT GET_LOCK('%s',%d)", name, lockTimeout)
  183. var res *int
  184. for range time.After(time.Second) {
  185. log.Printf("Process %d: trying to get lock", i)
  186.  
  187. err := db.QueryRow(q).Scan(&res)
  188. if err != nil {
  189. log.Printf("Process %d: QueryRow error: %s", i, err.Error())
  190. }
  191. log.Printf("Process %d: get_lock result: %d", i, *res)
  192. if *res == 1 {
  193. <-time.After(holdLockDuration)
  194. log.Printf("Process %d: releasing lock", i)
  195. err := db.QueryRow(fmt.Sprintf("SELECT RELEASE_LOCK('%s')", name)).Scan(&res)
  196. //Returns 1 if the lock was released, 0 if the lock was not established by this thread
  197. //(in which case the lock is not released), and NULL if the named lock did not exist.
  198. //The lock does not exist if it was never obtained by a call to GET_LOCK() or if it
  199. //has previously been released.
  200. if err != nil {
  201. log.Printf("Process %d: release error: %s", i, err.Error())
  202. } else if res == nil {
  203. log.Printf("Process %d: release res is nil", i)
  204. } else {
  205. log.Printf("Process %d: release result %d", i, *res)
  206. }
  207. break
  208. }
  209. }
  210.  
  211. log.Printf("Process %d: ending", i)
  212. }
  213.  
  214. type SQLConnection struct {
  215. Domain string
  216. Port int
  217. Username string
  218. Password string
  219. Database string
  220. }
  221.  
  222. func open() *sql.DB {
  223. sc := SQLConnection{
  224. Domain: "127.0.0.1",
  225. Port: 3306,
  226. Username: "root",
  227. Password: "root",
  228. Database: "benchmark",
  229. }
  230.  
  231. // get connection string
  232. connStr := fmt.Sprintf(
  233. //FIXME tls
  234. "%s:%s@tcp(%s:%d)/%s",
  235. sc.Username,
  236. sc.Password,
  237. sc.Domain,
  238. sc.Port,
  239. sc.Database,
  240. )
  241. db, err := sql.Open("mysql", connStr)
  242. if err != nil {
  243. panic(fmt.Sprintf("conn error: %s", err.Error()))
  244. }
  245.  
  246. return db
  247. }
Add Comment
Please, Sign In to add comment