// unpackMeta reads the metadata from the snapshot and initializes a raft // cluster and replaces the root metadata. func (cmd *Command) unpackMeta(mr *snapshot.MultiReader, sf snapshot.File, config *Config) error { // Read meta into buffer. var buf bytes.Buffer if _, err := io.CopyN(&buf, mr, sf.Size); err != nil { return fmt.Errorf("copy: %s", err) } // Unpack into metadata. var data meta.Data if err := data.UnmarshalBinary(buf.Bytes()); err != nil { return fmt.Errorf("unmarshal: %s", err) } // Copy meta config and remove peers so it starts in single mode. c := config.Meta c.Peers = nil // Initialize meta store. store := meta.NewStore(config.Meta) store.RaftListener = newNopListener() store.ExecListener = newNopListener() // Determine advertised address. _, port, err := net.SplitHostPort(config.Meta.BindAddress) if err != nil { return fmt.Errorf("split bind address: %s", err) } hostport := net.JoinHostPort(config.Meta.Hostname, port) // Resolve address. addr, err := net.ResolveTCPAddr("tcp", hostport) if err != nil { return fmt.Errorf("resolve tcp: addr=%s, err=%s", hostport, err) } store.Addr = addr // Open the meta store. if err := store.Open(); err != nil { return fmt.Errorf("open store: %s", err) } defer store.Close() // Wait for the store to be ready or error. select { case <-store.Ready(): case err := <-store.Err(): return err } // Force set the full metadata. if err := store.SetData(&data); err != nil { return fmt.Errorf("set data: %s", err) } return nil }
// Ensure the data can be marshaled and unmarshaled. func TestData_MarshalBinary(t *testing.T) { data := meta.Data{ Term: 10, Index: 20, Nodes: []meta.NodeInfo{ {ID: 1, Host: "host0"}, {ID: 2, Host: "host1"}, }, Databases: []meta.DatabaseInfo{ { Name: "db0", DefaultRetentionPolicy: "default", RetentionPolicies: []meta.RetentionPolicyInfo{ { Name: "rp0", ReplicaN: 3, Duration: 10 * time.Second, ShardGroupDuration: 3 * time.Millisecond, ShardGroups: []meta.ShardGroupInfo{ { ID: 100, StartTime: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC), EndTime: time.Date(2000, time.February, 1, 0, 0, 0, 0, time.UTC), Shards: []meta.ShardInfo{ { ID: 200, OwnerIDs: []uint64{1, 3, 4}, }, }, }, }, }, }, // ContinuousQueries: []meta.ContinuousQueryInfo{ // {Query: "SELECT count() FROM foo"}, // }, }, }, Users: []meta.UserInfo{ { Name: "susy", Hash: "ABC123", Admin: true, Privileges: map[string]sql.Privilege{"db0": sql.AllPrivileges}, }, }, } // Marshal the data struture. buf, err := data.MarshalBinary() if err != nil { t.Fatal(err) } // Unmarshal into new data. var other meta.Data if err := other.UnmarshalBinary(buf); err != nil { t.Fatal(err) } if !reflect.DeepEqual(data.Nodes, other.Nodes) { t.Fatalf("unexpected nodes: %#v", other.Nodes) } else if !reflect.DeepEqual(data.Databases, other.Databases) { spew.Dump(data.Databases) spew.Dump(other.Databases) t.Fatalf("unexpected databases: %#v", other.Databases) } else if !reflect.DeepEqual(data.Users, other.Users) { t.Fatalf("unexpected users: %#v", other.Users) } }