1
1
package spanner
2
2
3
3
import (
4
+ "errors"
4
5
"fmt"
5
6
"io"
6
7
"io/ioutil"
@@ -20,6 +21,7 @@ import (
20
21
"github.com/golang-migrate/migrate/v4/database"
21
22
22
23
"github.com/hashicorp/go-multierror"
24
+ uatomic "go.uber.org/atomic"
23
25
"google.golang.org/api/iterator"
24
26
adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
25
27
)
@@ -32,12 +34,19 @@ func init() {
32
34
// DefaultMigrationsTable is used if no custom table is specified
33
35
const DefaultMigrationsTable = "SchemaMigrations"
34
36
37
+ const (
38
+ unlockedVal = 0
39
+ lockedVal = 1
40
+ )
41
+
35
42
// Driver errors
36
43
var (
37
- ErrNilConfig = fmt .Errorf ("no config" )
38
- ErrNoDatabaseName = fmt .Errorf ("no database name" )
39
- ErrNoSchema = fmt .Errorf ("no schema" )
40
- ErrDatabaseDirty = fmt .Errorf ("database is dirty" )
44
+ ErrNilConfig = errors .New ("no config" )
45
+ ErrNoDatabaseName = errors .New ("no database name" )
46
+ ErrNoSchema = errors .New ("no schema" )
47
+ ErrDatabaseDirty = errors .New ("database is dirty" )
48
+ ErrLockHeld = errors .New ("unable to obtain lock" )
49
+ ErrLockNotHeld = errors .New ("unable to release already released lock" )
41
50
)
42
51
43
52
// Config used for a Spanner instance
@@ -56,6 +65,8 @@ type Spanner struct {
56
65
db * DB
57
66
58
67
config * Config
68
+
69
+ lock * uatomic.Uint32
59
70
}
60
71
61
72
type DB struct {
@@ -87,6 +98,7 @@ func WithInstance(instance *DB, config *Config) (database.Driver, error) {
87
98
sx := & Spanner {
88
99
db : instance ,
89
100
config : config ,
101
+ lock : uatomic .NewUint32 (unlockedVal ),
90
102
}
91
103
92
104
if err := sx .ensureVersionTable (); err != nil {
@@ -143,12 +155,18 @@ func (s *Spanner) Close() error {
143
155
// Lock implements database.Driver but doesn't do anything because Spanner only
144
156
// enqueues the UpdateDatabaseDdlRequest.
145
157
func (s * Spanner ) Lock () error {
146
- return nil
158
+ if swapped := s .lock .CAS (unlockedVal , lockedVal ); swapped {
159
+ return nil
160
+ }
161
+ return ErrLockHeld
147
162
}
148
163
149
164
// Unlock implements database.Driver but no action required, see Lock.
150
165
func (s * Spanner ) Unlock () error {
151
- return nil
166
+ if swapped := s .lock .CAS (lockedVal , unlockedVal ); swapped {
167
+ return nil
168
+ }
169
+ return ErrLockNotHeld
152
170
}
153
171
154
172
// Run implements database.Driver
0 commit comments