blob: 9ead44d7bc9a6658b1ef52d615925fe8b4e244eb [file]
/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package iggcon
import (
"bytes"
"encoding/binary"
"fmt"
ierror "github.com/apache/iggy/foreign/go/errors"
)
type ClusterNode struct {
Name string
IP string
Endpoints TransportEndpoints
Role ClusterNodeRole
Status ClusterNodeStatus
}
func (n *ClusterNode) BufferSize() int {
return 4 + len(n.Name) + 4 + len(n.IP) + n.Endpoints.GetBufferSize() + 1 + 1
}
func (n *ClusterNode) MarshalBinary() ([]byte, error) {
size := n.BufferSize()
buf := bytes.NewBuffer(make([]byte, 0, size))
// name
if err := binary.Write(buf, binary.LittleEndian, uint32(len(n.Name))); err != nil {
return nil, err
}
if _, err := buf.WriteString(n.Name); err != nil {
return nil, err
}
// ip
if err := binary.Write(buf, binary.LittleEndian, uint32(len(n.IP))); err != nil {
return nil, err
}
if _, err := buf.WriteString(n.IP); err != nil {
return nil, err
}
// endpoints (use MarshalBinary on TransportEndpoints)
epb, err := n.Endpoints.MarshalBinary()
if err != nil {
return nil, err
}
if _, err := buf.Write(epb); err != nil {
return nil, err
}
// role
rb, err := n.Role.MarshalBinary()
if err != nil {
return nil, err
}
if _, err := buf.Write(rb); err != nil {
return nil, err
}
// status
sb, err := n.Status.MarshalBinary()
if err != nil {
return nil, err
}
if _, err := buf.Write(sb); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (n *ClusterNode) UnmarshalBinary(b []byte) error {
// Minimal size check: 4 (name_len) + 4 (ip_len) + 1 (role) + 1 (status)
if len(b) < 10 {
return ierror.ErrInvalidCommand
}
pos := 0
// name length
if len(b) < pos+4 {
return ierror.ErrInvalidNumberEncoding
}
nameLen := int(binary.LittleEndian.Uint32(b[pos : pos+4]))
pos += 4
if len(b) < pos+nameLen {
return ierror.ErrInvalidCommand
}
n.Name = string(b[pos : pos+nameLen])
pos += nameLen
// ip length
if len(b) < pos+4 {
return ierror.ErrInvalidNumberEncoding
}
ipLen := int(binary.LittleEndian.Uint32(b[pos : pos+4]))
pos += 4
if len(b) < pos+ipLen {
return ierror.ErrInvalidCommand
}
n.IP = string(b[pos : pos+ipLen])
pos += ipLen
// endpoints: use BufferSize and UnmarshalBinary
ep := TransportEndpoints{}
epSize := ep.GetBufferSize()
if len(b) < pos+epSize {
return ierror.ErrInvalidCommand
}
if err := ep.UnmarshalBinary(b[pos : pos+epSize]); err != nil {
return err
}
n.Endpoints = ep
pos += epSize
// role (1 byte)
if len(b) < pos+1 {
return ierror.ErrInvalidCommand
}
var r ClusterNodeRole
if err := r.UnmarshalBinary(b[pos : pos+1]); err != nil {
return err
}
n.Role = r
pos++
// status (1 byte)
if len(b) < pos+1 {
return ierror.ErrInvalidCommand
}
var s ClusterNodeStatus
if err := s.UnmarshalBinary(b[pos : pos+1]); err != nil {
return err
}
n.Status = s
return nil
}
func (n *ClusterNode) String() string {
return fmt.Sprintf("ClusterNode { name: %s, ip: %s, endpoints: %s, role: %s, status: %s }",
n.Name, n.IP, n.Endpoints.String(), n.Role.String(), n.Status.String())
}