Skip to content

Commit d7641a8

Browse files
committed
api: write a connection schema getter
Write a helper function to load the actual schema for the user. Previously we stored actual schema in a private `schemaResolver` field and `Schema` field was used only to get a current schema. But now because of the new function, we don't need to store the `Schema` as a different field. So `Schema` was also removed. To update the schema, used needs to use `GetSchema` + `SetSchema` in pair. `SetSchema(Schema)` replacing the `OverrideSchema(*Schema)`. `Spaces` and `SpacesById` fields of the `Schema` struct store spaces by value. `Fields` and `FieldsById` fields of the `Space` struct store fields by value. `Index` and `IndexById` fields of the `Space` struct store indexes by value. `Fields` field of the `Index` struct store `IndexField` by value. Closes #7
1 parent 6225ec4 commit d7641a8

File tree

6 files changed

+115
-67
lines changed

6 files changed

+115
-67
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
2626
- Support `IPROTO_FEATURE_SPACE_AND_INDEX_NAMES` for Tarantool
2727
version >= 3.0.0-alpha1 (#338). It allows to use space and index names
2828
in requests instead of their IDs.
29+
- `GetSchema` function to get the actual schema (#7)
2930

3031
### Changed
3132

@@ -51,6 +52,9 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
5152
instead of `crud.OptUint` (#342)
5253
- Change all `Upsert` and `Update` requests to accept `*tarantool.Operations`
5354
as `ops` parameters instead of `interface{}` (#348)
55+
- Change `OverrideSchema(*Schema)` to `SetSchema(Schema)` (#7)
56+
- Change values, stored by pointers in the `Schema`, `Space`, `Index` structs,
57+
to be stored by their values (#7)
5458

5559
### Deprecated
5660

@@ -70,6 +74,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
7074
- UUID_extId (#158)
7175
- IPROTO constants (#158)
7276
- Code() method from the Request interface (#158)
77+
- `Schema` field from the `Connection` struct (#7)
7378

7479
### Fixed
7580

README.md

+11
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,13 @@ now does not attempt to reconnect and tries to establish a connection only once.
248248
Function might be canceled via context. Context accepted as first argument,
249249
and user may cancel it in process.
250250

251+
#### Connection schema
252+
253+
* Removed `Schema` field from the `Connection` struct. Instead, new
254+
`GetSchema(Connector)` function was added to get the actual connection
255+
schema on demand.
256+
* `OverrideSchema(*Schema)` method replaced with the `SetSchema(Schema)`.
257+
251258
#### Protocol changes
252259

253260
* `iproto.Feature` type used instead of `ProtocolFeature`.
@@ -260,6 +267,10 @@ and user may cancel it in process.
260267
interface to get information if the usage of space and index names in requests
261268
is supported.
262269
* `Schema` structure no longer implements `SchemaResolver` interface.
270+
* `Spaces` and `SpacesById` fields of the `Schema` struct store spaces by value.
271+
* `Fields` and `FieldsById` fields of the `Space` struct store fields by value.
272+
`Index` and `IndexById` fields of the `Space` struct store indexes by value.
273+
* `Fields` field of the `Index` struct store `IndexField` by value.
263274

264275
## Contributing
265276

connection.go

+16-11
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,6 @@ type Connection struct {
160160
c Conn
161161
mutex sync.Mutex
162162
cond *sync.Cond
163-
// Schema contains schema loaded on connection.
164-
Schema *Schema
165163
// schemaResolver contains a SchemaResolver implementation.
166164
schemaResolver SchemaResolver
167165
// requestId contains the last request ID for requests with nil context.
@@ -436,12 +434,14 @@ func Connect(ctx context.Context, addr string, opts Opts) (conn *Connection, err
436434

437435
// TODO: reload schema after reconnect.
438436
if !conn.opts.SkipSchema {
439-
if err = conn.loadSchema(); err != nil {
437+
schema, err := GetSchema(conn)
438+
if err != nil {
440439
conn.mutex.Lock()
441440
defer conn.mutex.Unlock()
442441
conn.closeConnection(err, true)
443442
return nil, err
444443
}
444+
conn.SetSchema(schema)
445445
}
446446

447447
return conn, err
@@ -1302,15 +1302,20 @@ func (conn *Connection) ConfiguredTimeout() time.Duration {
13021302
return conn.opts.Timeout
13031303
}
13041304

1305-
// OverrideSchema sets Schema for the connection.
1306-
func (conn *Connection) OverrideSchema(s *Schema) {
1307-
if s != nil {
1308-
conn.mutex.Lock()
1309-
defer conn.mutex.Unlock()
1310-
conn.lockShards()
1311-
defer conn.unlockShards()
1305+
// SetSchema sets Schema for the connection.
1306+
func (conn *Connection) SetSchema(s Schema) {
1307+
spaceAndIndexNamesSupported :=
1308+
isFeatureInSlice(iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES,
1309+
conn.serverProtocolInfo.Features)
13121310

1313-
conn.Schema = s
1311+
conn.mutex.Lock()
1312+
defer conn.mutex.Unlock()
1313+
conn.lockShards()
1314+
defer conn.unlockShards()
1315+
1316+
conn.schemaResolver = &loadedSchemaResolver{
1317+
Schema: s,
1318+
SpaceAndIndexNamesSupported: spaceAndIndexNamesSupported,
13141319
}
13151320
}
13161321

example_test.go

+23-3
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,10 @@ func ExampleSchema() {
10631063
conn := exampleConnect(opts)
10641064
defer conn.Close()
10651065

1066-
schema := conn.Schema
1066+
schema, err := tarantool.GetSchema(conn)
1067+
if err != nil {
1068+
fmt.Printf("unexpected error: %s\n", err.Error())
1069+
}
10671070
if schema.SpacesById == nil {
10681071
fmt.Println("schema.SpacesById is nil")
10691072
}
@@ -1080,13 +1083,30 @@ func ExampleSchema() {
10801083
// Space 2 ID 616 schematest
10811084
}
10821085

1086+
// Example demonstrates how to update the connection schema.
1087+
func ExampleConnection_SetSchema() {
1088+
conn := exampleConnect(opts)
1089+
defer conn.Close()
1090+
1091+
// Get the actual schema.
1092+
schema, err := tarantool.GetSchema(conn)
1093+
if err != nil {
1094+
fmt.Printf("unexpected error: %s\n", err.Error())
1095+
}
1096+
// Update the current schema to match the actual one.
1097+
conn.SetSchema(schema)
1098+
}
1099+
10831100
// Example demonstrates how to retrieve information with space schema.
10841101
func ExampleSpace() {
10851102
conn := exampleConnect(opts)
10861103
defer conn.Close()
10871104

10881105
// Save Schema to a local variable to avoid races
1089-
schema := conn.Schema
1106+
schema, err := tarantool.GetSchema(conn)
1107+
if err != nil {
1108+
fmt.Printf("unexpected error: %s\n", err.Error())
1109+
}
10901110
if schema.SpacesById == nil {
10911111
fmt.Println("schema.SpacesById is nil")
10921112
}
@@ -1120,7 +1140,7 @@ func ExampleSpace() {
11201140
// Space 1 ID 617 test memtx
11211141
// Space 1 ID 0 false
11221142
// Index 0 primary
1123-
// &{0 unsigned} &{2 string}
1143+
// {0 unsigned} {2 string}
11241144
// SpaceField 1 name0 unsigned
11251145
// SpaceField 2 name3 unsigned
11261146
}

schema.go

+27-39
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"errors"
55
"fmt"
66

7-
"github.com/tarantool/go-iproto"
87
"github.com/vmihailenco/msgpack/v5"
98
"github.com/vmihailenco/msgpack/v5/msgpcode"
109
)
@@ -58,9 +57,9 @@ type SchemaResolver interface {
5857
type Schema struct {
5958
Version uint
6059
// Spaces is map from space names to spaces.
61-
Spaces map[string]*Space
60+
Spaces map[string]Space
6261
// SpacesById is map from space numbers to spaces.
63-
SpacesById map[uint32]*Space
62+
SpacesById map[uint32]Space
6463
}
6564

6665
// Space contains information about Tarantool's space.
@@ -72,12 +71,12 @@ type Space struct {
7271
Temporary bool // Is this space temporary?
7372
// Field configuration is not mandatory and not checked by Tarantool.
7473
FieldsCount uint32
75-
Fields map[string]*Field
76-
FieldsById map[uint32]*Field
74+
Fields map[string]Field
75+
FieldsById map[uint32]Field
7776
// Indexes is map from index names to indexes.
78-
Indexes map[string]*Index
77+
Indexes map[string]Index
7978
// IndexesById is map from index numbers to indexes.
80-
IndexesById map[uint32]*Index
79+
IndexesById map[uint32]Index
8180
}
8281

8382
func (space *Space) DecodeMsgpack(d *msgpack.Decoder) error {
@@ -135,17 +134,17 @@ func (space *Space) DecodeMsgpack(d *msgpack.Decoder) error {
135134
return errors.New("unexpected schema format (space flags)")
136135
}
137136
}
138-
space.FieldsById = make(map[uint32]*Field)
139-
space.Fields = make(map[string]*Field)
140-
space.IndexesById = make(map[uint32]*Index)
141-
space.Indexes = make(map[string]*Index)
137+
space.FieldsById = make(map[uint32]Field)
138+
space.Fields = make(map[string]Field)
139+
space.IndexesById = make(map[uint32]Index)
140+
space.Indexes = make(map[string]Index)
142141
if arrayLen >= vspaceSpFormatFieldNum {
143142
fieldCount, err := d.DecodeArrayLen()
144143
if err != nil {
145144
return err
146145
}
147146
for i := 0; i < fieldCount; i++ {
148-
field := &Field{}
147+
field := Field{}
149148
if err := field.DecodeMsgpack(d); err != nil {
150149
return err
151150
}
@@ -206,7 +205,7 @@ type Index struct {
206205
Name string
207206
Type string
208207
Unique bool
209-
Fields []*IndexField
208+
Fields []IndexField
210209
}
211210

212211
func (index *Index) DecodeMsgpack(d *msgpack.Decoder) error {
@@ -261,9 +260,9 @@ func (index *Index) DecodeMsgpack(d *msgpack.Decoder) error {
261260
if err != nil {
262261
return err
263262
}
264-
index.Fields = make([]*IndexField, fieldCount)
263+
index.Fields = make([]IndexField, fieldCount)
265264
for i := 0; i < int(fieldCount); i++ {
266-
index.Fields[i] = new(IndexField)
265+
index.Fields[i] = IndexField{}
267266
if index.Fields[i].Id, err = d.DecodeUint32(); err != nil {
268267
return err
269268
}
@@ -340,51 +339,40 @@ func (indexField *IndexField) DecodeMsgpack(d *msgpack.Decoder) error {
340339
return errors.New("unexpected schema format (index fields)")
341340
}
342341

343-
func (conn *Connection) loadSchema() (err error) {
344-
schema := new(Schema)
345-
schema.SpacesById = make(map[uint32]*Space)
346-
schema.Spaces = make(map[string]*Space)
342+
// GetSchema returns the actual schema for the connection.
343+
func GetSchema(conn Connector) (Schema, error) {
344+
schema := Schema{}
345+
schema.SpacesById = make(map[uint32]Space)
346+
schema.Spaces = make(map[string]Space)
347347

348348
// Reload spaces.
349-
var spaces []*Space
350-
err = conn.SelectTyped(vspaceSpId, 0, 0, maxSchemas, IterAll, []interface{}{}, &spaces)
349+
var spaces []Space
350+
err := conn.SelectTyped(vspaceSpId, 0, 0, maxSchemas, IterAll, []interface{}{}, &spaces)
351351
if err != nil {
352-
return err
352+
return Schema{}, err
353353
}
354354
for _, space := range spaces {
355355
schema.SpacesById[space.Id] = space
356356
schema.Spaces[space.Name] = space
357357
}
358358

359359
// Reload indexes.
360-
var indexes []*Index
360+
var indexes []Index
361361
err = conn.SelectTyped(vindexSpId, 0, 0, maxSchemas, IterAll, []interface{}{}, &indexes)
362362
if err != nil {
363-
return err
363+
return Schema{}, err
364364
}
365365
for _, index := range indexes {
366366
spaceId := index.SpaceId
367367
if _, ok := schema.SpacesById[spaceId]; ok {
368368
schema.SpacesById[spaceId].IndexesById[index.Id] = index
369369
schema.SpacesById[spaceId].Indexes[index.Name] = index
370370
} else {
371-
return errors.New("concurrent schema update")
371+
return Schema{}, errors.New("concurrent schema update")
372372
}
373373
}
374374

375-
spaceAndIndexNamesSupported :=
376-
isFeatureInSlice(iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES,
377-
conn.serverProtocolInfo.Features)
378-
379-
conn.lockShards()
380-
conn.Schema = schema
381-
conn.schemaResolver = &loadedSchemaResolver{
382-
Schema: schema,
383-
SpaceAndIndexNamesSupported: spaceAndIndexNamesSupported,
384-
}
385-
conn.unlockShards()
386-
387-
return nil
375+
return schema, nil
388376
}
389377

390378
// resolveSpaceNumber tries to resolve a space number.
@@ -462,7 +450,7 @@ func resolveIndexNumber(i interface{}) (uint32, error) {
462450
}
463451

464452
type loadedSchemaResolver struct {
465-
Schema *Schema
453+
Schema Schema
466454
// SpaceAndIndexNamesSupported shows if a current Tarantool version supports
467455
// iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES.
468456
SpaceAndIndexNamesSupported bool

0 commit comments

Comments
 (0)