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  }