forked from linxGnu/mssqlx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
types.go
145 lines (122 loc) · 2.68 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package mssqlx
import (
"runtime"
"sync/atomic"
"github.com/jmoiron/sqlx"
)
type wrapper struct {
db *sqlx.DB
dsn string
}
func (w *wrapper) checkWsrepReady() bool {
type wsrepVariable struct {
VariableName string `db:"Variable_name"`
Value string `db:"Value"`
}
var v wsrepVariable
if err := w.db.Get(&v, "SHOW VARIABLES LIKE 'wsrep_on'"); err != nil {
reportError("SHOW VARIABLES LIKE 'wsrep_on'", err)
return false
}
if v.Value != "ON" {
return true
}
if err := w.db.Get(&v, "SHOW STATUS LIKE 'wsrep_ready'"); err != nil || v.Value != "ON" {
reportError("SHOW STATUS LIKE 'wsrep_ready'", err)
return false
}
return true
}
var empty = []*wrapper{}
type dbList struct {
list atomic.Value // []*wrapper
_p1 [9]uint64 // prevent false sharing
state int32
_p2 [9]uint64
currentIndex uint32
_p3 [9]uint64
}
func (b *dbList) size() (v int) {
list, stored := b.list.Load().([]*wrapper)
if stored {
v = len(list)
}
return
}
func (b *dbList) current() (w *wrapper) {
list, stored := b.list.Load().([]*wrapper)
if stored {
if n := uint32(len(list)); n > 0 {
w = list[atomic.LoadUint32(&b.currentIndex)%n]
}
}
return
}
func (b *dbList) next() (w *wrapper) {
list, stored := b.list.Load().([]*wrapper)
if stored {
if n := uint32(len(list)); n > 0 {
w = list[atomic.AddUint32(&b.currentIndex, 1)%n]
}
}
return
}
func (b *dbList) add(w *wrapper) {
if w != nil {
for {
if atomic.CompareAndSwapInt32(&b.state, 0, 1) { // lock first
list, stored := b.list.Load().([]*wrapper)
if !stored {
list = make([]*wrapper, 0, 8)
} else {
n := len(list)
newList := make([]*wrapper, n, n+1)
copy(newList, list) // copy-on-write
list = newList
}
// append to list
list = append(list, w)
// store back
b.list.Store(list)
atomic.CompareAndSwapInt32(&b.state, 1, 0)
return
}
runtime.Gosched()
}
}
}
func (b *dbList) remove(w *wrapper) (removed bool) {
if w != nil {
for {
if atomic.CompareAndSwapInt32(&b.state, 0, 1) { // lock first
list, stored := b.list.Load().([]*wrapper)
if stored {
if n := len(list); n > 0 {
for i := range list {
if list[i] == w { // found
removed = true
newList := make([]*wrapper, n-1, n)
if i > 0 {
copy(newList, list[:i])
}
if i < n-1 {
copy(newList[i:], list[i+1:])
}
b.list.Store(newList)
break
}
}
}
}
atomic.CompareAndSwapInt32(&b.state, 1, 0)
return
}
runtime.Gosched()
}
}
return
}
func (b *dbList) clear() {
atomic.StoreUint32(&b.currentIndex, 0)
b.list.Store(empty)
}