Example #1
0
// LoadVSchema loads the VSchema from the topo. The function does
// not return an error. It instead logs warnings on failure.
func (plr *Planner) LoadVSchema(ctx context.Context) {
	formal := &vindexes.VSchemaFormal{
		Keyspaces: make(map[string]vindexes.KeyspaceFormal),
	}
	keyspaces, err := plr.serv.GetSrvKeyspaceNames(ctx, plr.cell)
	if err != nil {
		log.Warningf("Error loading vschema: could not read keyspaces: %v", err)
		return
	}
	for _, keyspace := range keyspaces {
		formal.Keyspaces[keyspace] = vindexes.KeyspaceFormal{}
		kschema, err := plr.serv.GetVSchema(context.TODO(), keyspace)
		if err != nil {
			log.Warningf("Error loading vschema for keyspace: %s: %v", keyspace, err)
			continue
		}
		var kformal vindexes.KeyspaceFormal
		err = json.Unmarshal([]byte(kschema), &kformal)
		if err != nil {
			log.Warningf("Error unmarshalling vschema for keyspace: %s: %v", keyspace, err)
			continue
		}
		formal.Keyspaces[keyspace] = kformal
	}
	vschema, err := vindexes.BuildVSchema(formal)
	if err != nil {
		log.Warningf("Error creating VSchema: %v", err)
		return
	}
	plr.mu.Lock()
	plr.vschema = vschema
	plr.mu.Unlock()
}
Example #2
0
func loadSchema(t *testing.T, filename string) *vindexes.VSchema {
	formal, err := vindexes.LoadFormal(locateFile(filename))
	if err != nil {
		t.Fatal(err)
	}
	vschema, err := vindexes.BuildVSchema(formal)
	if err != nil {
		t.Fatal(err)
	}
	return vschema
}
Example #3
0
// WatchSrvVSchema watches the SrvVSchema from the topo. The function does
// not return an error. It instead logs warnings on failure.
// The SrvVSchema object is roll-up of all the Keyspace information,
// so when a keyspace is added or removed, it will be properly updated.
//
// This function will wait until the first value has either been processed
// or triggered an error before returning.
func (plr *Planner) WatchSrvVSchema(ctx context.Context, cell string) {
	wg := sync.WaitGroup{}
	wg.Add(1)

	go func() {
		foundFirstValue := false

		// Create a closure to save the vschema. If the value
		// passed is nil, it means we encountered an error and
		// we don't know the real value. In this case, we want
		// to use the previous value if it was set, or an
		// empty vschema if it wasn't.
		saveVSchema := func(v *vschemapb.SrvVSchema, errorMessage string) {
			// transform the provided SrvVSchema into a VSchema
			var vschema *vindexes.VSchema
			if v != nil {
				var err error
				vschema, err = vindexes.BuildVSchema(v)
				if err != nil {
					log.Warningf("Error creating VSchema for cell %v (will try again next update): %v", cell, err)
					v = nil
					errorMessage = fmt.Sprintf("Error creating VSchema for cell %v: %v", cell, err)
					if vschemaCounters != nil {
						vschemaCounters.Add("Parsing", 1)
					}
				}
			}
			if v == nil {
				// we encountered an error, build an
				// empty vschema
				vschema, _ = vindexes.BuildVSchema(&vschemapb.SrvVSchema{})
			}

			// Build the display version.
			stats := NewVSchemaStats(vschema, errorMessage)

			// save our value
			plr.mu.Lock()
			if v != nil {
				// no errors, we can save our schema
				plr.vschema = vschema
			} else {
				// we had an error, use the empty vschema
				// if we had nothing before.
				if plr.vschema == nil {
					plr.vschema = vschema
				}
			}
			plr.vschemaStats = stats
			plr.mu.Unlock()
			plr.plans.Clear()

			if vschemaCounters != nil {
				vschemaCounters.Add("Reload", 1)
			}

			// notify the listener
			if !foundFirstValue {
				foundFirstValue = true
				wg.Done()
			}
		}

		for {
			current, changes, _ := plr.serv.WatchSrvVSchema(ctx, cell)
			if current.Err != nil {
				// Don't log if there is no VSchema to start with.
				if current.Err != topo.ErrNoNode {
					log.Warningf("Error watching vschema for cell %s (will wait 5s before retrying): %v", cell, current.Err)
				}
				saveVSchema(nil, fmt.Sprintf("Error watching SvrVSchema: %v", current.Err.Error()))
				if vschemaCounters != nil {
					vschemaCounters.Add("WatchError", 1)
				}
				time.Sleep(5 * time.Second)
				continue
			}
			saveVSchema(current.Value, "")

			for c := range changes {
				if c.Err != nil {
					// If the SrvVschema disappears, we need to clear our record.
					// Otherwise, keep what we already had before.
					if c.Err == topo.ErrNoNode {
						saveVSchema(nil, "SrvVSchema object was removed from topology.")
					}
					log.Warningf("Error while watching vschema for cell %s (will wait 5s before retrying): %v", cell, c.Err)
					if vschemaCounters != nil {
						vschemaCounters.Add("WatchError", 1)
					}
					break
				}
				saveVSchema(c.Value, "")
			}

			// Sleep a bit before trying again.
			time.Sleep(5 * time.Second)
		}
	}()

	// wait for the first value to have been processed
	wg.Wait()
}
Example #4
0
// WatchSrvVSchema watches the SrvVSchema from the topo. The function does
// not return an error. It instead logs warnings on failure.
// The SrvVSchema object is roll-up of all the Keyspace information,
// so when a keyspace is added or removed, it will be properly updated.
//
// This function will wait until the first value has either been processed
// or triggered an error before returning.
func (plr *Planner) WatchSrvVSchema(ctx context.Context, cell string) {
	wg := sync.WaitGroup{}
	wg.Add(1)

	go func() {
		foundFirstValue := false

		// Create a closure to save the vschema. If the value
		// passed is nil, it means we encountered an error and
		// we don't know the real value. In this case, we want
		// to use the previous value if it was set, or an
		// empty vschema if it wasn't.
		saveVSchema := func(v *vschemapb.SrvVSchema) {
			// transform the provided SrvVSchema into a VSchema
			var vschema *vindexes.VSchema
			if v != nil {
				var err error
				vschema, err = vindexes.BuildVSchema(v)
				if err != nil {
					log.Warningf("Error creating VSchema for cell %v (will try again next update): %v", cell, err)
					v = nil
				}
			}
			if v == nil {
				// we encountered an error, build an
				// empty vschema
				vschema, _ = vindexes.BuildVSchema(&vschemapb.SrvVSchema{})
			}

			// save our value
			plr.mu.Lock()
			if v != nil {
				// no errors, we can save our schema
				plr.vschema = vschema
			} else {
				// we had an error, use the empty vschema
				// if we had nothing before.
				if plr.vschema == nil {
					plr.vschema = vschema
				}
			}
			plr.mu.Unlock()
			plr.plans.Clear()

			// notify the listener
			if !foundFirstValue {
				foundFirstValue = true
				wg.Done()
			}
		}

		for {
			n, err := plr.serv.WatchSrvVSchema(ctx, cell)
			if err != nil {
				log.Warningf("Error watching vschema for cell %s (will wait 5s before retrying): %v", cell, err)
				saveVSchema(nil)
				time.Sleep(5 * time.Second)
				continue
			}

			for value := range n {
				if value == nil {
					log.Warningf("Got an empty vschema for cell %v", cell)
					saveVSchema(&vschemapb.SrvVSchema{})
					continue
				}

				saveVSchema(value)
			}

			log.Warningf("Watch on vschema for cell %v ended, will wait 5s before retrying", cell)
			saveVSchema(nil)
			time.Sleep(5 * time.Second)
		}
	}()

	// wait for the first value to have been processed
	wg.Wait()
}