func main() {
	var err error
	srv := &clonesrv_t{}
	if len(os.Args) == 2 && os.Args[1] == "-p" {
		log.Println("I: primary active, waiting for backup (passive)")
		srv.bstar, err = bstar.New(bstar.PRIMARY, "tcp://*:5003", "tcp://localhost:5004")
		if err != nil {
			log.Println(err)
			return
		}
		srv.bstar.Voter("tcp://*:5556", zmq.ROUTER, func(soc *zmq.Socket) error { return snapshots(soc, srv) })
		srv.port = 5556
		srv.peer = 5566
		srv.primary = true
	} else if len(os.Args) == 2 && os.Args[1] == "-b" {
		log.Println("I: backup passive, waiting for primary (active)")
		srv.bstar, err = bstar.New(bstar.BACKUP, "tcp://*:5004", "tcp://localhost:5003")
		srv.bstar.Voter("tcp://*:5566", zmq.ROUTER, func(soc *zmq.Socket) error { return snapshots(soc, srv) })
		srv.port = 5566
		srv.peer = 5556
		srv.primary = false
	} else {
		fmt.Println("Usage: clonesrv4 { -p | -b }")
		return
	}
	if srv.primary {
		srv.kvmap = make(map[string]*kvmsg.Kvmsg, 0)
		srv.kvmap_init = true
	}
	srv.pending = make([]*kvmsg.Kvmsg, 0)
	srv.bstar.SetVerbose(true)
	srv.publisher, _ = zmq.NewSocket(zmq.PUB)
	srv.collector, _ = zmq.NewSocket(zmq.SUB)
	srv.collector.SetSubscribe("")
	srv.publisher.Bind(fmt.Sprint("tcp://*:", srv.port+1))
	srv.collector.Bind(fmt.Sprint("tcp://*:", srv.port+2))
	srv.subscriber, _ = zmq.NewSocket(zmq.SUB)
	srv.subscriber.SetSubscribe("")
	srv.subscriber.Connect(fmt.Sprint("tcp://localhost:", srv.peer+1))
	srv.bstar.NewActive(func() error { return new_active(srv) })
	srv.bstar.NewPassive(func() error { return new_passive(srv) })
	srv.bstar.Reactor.AddSocket(srv.collector, zmq.POLLIN,
		func(e zmq.State) error { return collector(srv) })
	srv.bstar.Reactor.AddChannelTime(time.Tick(1000*time.Millisecond), 1,
		func(i interface{}) error {
			if e := flush_ttl(srv); e != nil {
				return e
			}
			return send_hugz(srv)
		})
	err = srv.bstar.Start()
	log.Println(err)
}
The main task parses the command line to decide whether to start
as primary or backup server. We're using the Binary Star pattern
for reliability. This interconnects the two servers so they can
agree on which is primary, and which is backup. To allow the two
servers to run on the same box, we use different ports for primary
and backup. Ports 5003/5004 are used to interconnect the servers.
Ports 5556/5566 are used to receive voting events (snapshot requests
in the clone pattern). Ports 5557/5567 are used by the publisher,
and ports 5558/5568 by the collector:
package main
import (
	zmq "github.com/pebbe/zmq3"
	"github.com/pebbe/zmq3/examples/bstar"
	"github.com/pebbe/zmq3/examples/kvmsg"
	"errors"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
	"time"
)
type clonesrv_t struct {
	kvmap      map[string]*kvmsg.Kvmsg  
	kvmap_init bool
	bstar      *bstar.Bstar    
	sequence   int64           
	port       int             
	peer       int             
	publisher  *zmq.Socket     
	collector  *zmq.Socket     
	subscriber *zmq.Socket     
	pending    []*kvmsg.Kvmsg  
	primary    bool            
	active     bool            
	passive    bool            
}