vitess.io/vitess@v0.16.2/go/vt/topo/vschema.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package topo 18 19 import ( 20 "path" 21 22 "google.golang.org/protobuf/proto" 23 24 "context" 25 26 "vitess.io/vitess/go/vt/log" 27 "vitess.io/vitess/go/vt/vterrors" 28 29 vschemapb "vitess.io/vitess/go/vt/proto/vschema" 30 "vitess.io/vitess/go/vt/vtgate/vindexes" 31 ) 32 33 // SaveVSchema first validates the VSchema, then saves it. 34 // If the VSchema is empty, just remove it. 35 func (ts *Server) SaveVSchema(ctx context.Context, keyspace string, vschema *vschemapb.Keyspace) error { 36 err := vindexes.ValidateKeyspace(vschema) 37 if err != nil { 38 return err 39 } 40 41 nodePath := path.Join(KeyspacesPath, keyspace, VSchemaFile) 42 data, err := proto.Marshal(vschema) 43 if err != nil { 44 return err 45 } 46 47 _, err = ts.globalCell.Update(ctx, nodePath, data, nil) 48 if err != nil { 49 log.Errorf("failed to update vschema for keyspace %s: %v", keyspace, err) 50 } else { 51 log.Infof("successfully updated vschema for keyspace %s: %+v", keyspace, vschema) 52 } 53 return err 54 } 55 56 // DeleteVSchema delete the keyspace if it exists 57 func (ts *Server) DeleteVSchema(ctx context.Context, keyspace string) error { 58 log.Infof("deleting vschema for keyspace %s", keyspace) 59 nodePath := path.Join(KeyspacesPath, keyspace, VSchemaFile) 60 return ts.globalCell.Delete(ctx, nodePath, nil) 61 } 62 63 // GetVSchema fetches the vschema from the topo. 64 func (ts *Server) GetVSchema(ctx context.Context, keyspace string) (*vschemapb.Keyspace, error) { 65 nodePath := path.Join(KeyspacesPath, keyspace, VSchemaFile) 66 data, _, err := ts.globalCell.Get(ctx, nodePath) 67 if err != nil { 68 return nil, err 69 } 70 var vs vschemapb.Keyspace 71 err = proto.Unmarshal(data, &vs) 72 if err != nil { 73 return nil, vterrors.Wrapf(err, "bad vschema data: %q", data) 74 } 75 return &vs, nil 76 } 77 78 // EnsureVSchema makes sure that a vschema is present for this keyspace or creates a blank one if it is missing 79 func (ts *Server) EnsureVSchema(ctx context.Context, keyspace string) error { 80 vschema, err := ts.GetVSchema(ctx, keyspace) 81 if err != nil && !IsErrType(err, NoNode) { 82 log.Infof("error in getting vschema for keyspace %s: %v", keyspace, err) 83 } 84 if vschema == nil || IsErrType(err, NoNode) { 85 err = ts.SaveVSchema(ctx, keyspace, &vschemapb.Keyspace{ 86 Sharded: false, 87 Vindexes: make(map[string]*vschemapb.Vindex), 88 Tables: make(map[string]*vschemapb.Table), 89 }) 90 if err != nil { 91 log.Errorf("could not create blank vschema: %v", err) 92 return err 93 } 94 } 95 return nil 96 } 97 98 // SaveRoutingRules saves the routing rules into the topo. 99 func (ts *Server) SaveRoutingRules(ctx context.Context, routingRules *vschemapb.RoutingRules) error { 100 data, err := proto.Marshal(routingRules) 101 if err != nil { 102 return err 103 } 104 105 if len(data) == 0 { 106 // No vschema, remove it. So we can remove the keyspace. 107 if err := ts.globalCell.Delete(ctx, RoutingRulesFile, nil); err != nil && !IsErrType(err, NoNode) { 108 return err 109 } 110 return nil 111 } 112 113 _, err = ts.globalCell.Update(ctx, RoutingRulesFile, data, nil) 114 return err 115 } 116 117 // GetRoutingRules fetches the routing rules from the topo. 118 func (ts *Server) GetRoutingRules(ctx context.Context) (*vschemapb.RoutingRules, error) { 119 rr := &vschemapb.RoutingRules{} 120 data, _, err := ts.globalCell.Get(ctx, RoutingRulesFile) 121 if err != nil { 122 if IsErrType(err, NoNode) { 123 return rr, nil 124 } 125 return nil, err 126 } 127 err = proto.Unmarshal(data, rr) 128 if err != nil { 129 return nil, vterrors.Wrapf(err, "bad routing rules data: %q", data) 130 } 131 return rr, nil 132 } 133 134 // SaveShardRoutingRules saves the shard routing rules into the topo. 135 func (ts *Server) SaveShardRoutingRules(ctx context.Context, shardRoutingRules *vschemapb.ShardRoutingRules) error { 136 data, err := proto.Marshal(shardRoutingRules) 137 if err != nil { 138 return err 139 } 140 141 if len(data) == 0 { 142 if err := ts.globalCell.Delete(ctx, ShardRoutingRulesFile, nil); err != nil && !IsErrType(err, NoNode) { 143 return err 144 } 145 return nil 146 } 147 148 _, err = ts.globalCell.Update(ctx, ShardRoutingRulesFile, data, nil) 149 return err 150 } 151 152 // GetShardRoutingRules fetches the shard routing rules from the topo. 153 func (ts *Server) GetShardRoutingRules(ctx context.Context) (*vschemapb.ShardRoutingRules, error) { 154 srr := &vschemapb.ShardRoutingRules{} 155 data, _, err := ts.globalCell.Get(ctx, ShardRoutingRulesFile) 156 if err != nil { 157 if IsErrType(err, NoNode) { 158 return srr, nil 159 } 160 return nil, err 161 } 162 err = proto.Unmarshal(data, srr) 163 if err != nil { 164 return nil, vterrors.Wrapf(err, "invalid shard routing rules: %q", data) 165 } 166 return srr, nil 167 }