Beispiel #1
0
func snapshots(socket *zmq.Socket, srv *clonesrv_t) (err error) {

	msg, err := socket.RecvMessage(0)
	if err != nil {
		return
	}
	identity := msg[0]

	//  Request is in second frame of message
	request := msg[1]
	if request != "ICANHAZ?" {
		err = errors.New("E: bad request, aborting")
		return
	}
	subtree := msg[2]

	//  Send state socket to client
	for _, kvmsg := range srv.kvmap {
		if key, _ := kvmsg.GetKey(); strings.HasPrefix(key, subtree) {
			socket.Send(identity, zmq.SNDMORE)
			kvmsg.Send(socket)
		}
	}

	//  Now send END message with sequence number
	log.Println("I: sending shapshot =", srv.sequence)
	socket.Send(identity, zmq.SNDMORE)
	kvmsg := kvmsg.NewKvmsg(srv.sequence)
	kvmsg.SetKey("KTHXBAI")
	kvmsg.SetBody(subtree)
	kvmsg.Send(socket)

	return
}
Beispiel #2
0
func flush_ttl(srv *clonesrv_t) (err error) {
	for _, kvmsg := range srv.kvmap {

		//  If key-value pair has expired, delete it and publish the
		//  fact to listening clients.

		if ttls, e := kvmsg.GetProp("ttl"); e == nil {
			ttl, e := strconv.ParseInt(ttls, 10, 64)
			if e != nil {
				err = e
				continue
			}
			if time.Now().After(time.Unix(ttl, 0)) {
				srv.sequence++
				kvmsg.SetSequence(srv.sequence)
				kvmsg.SetBody("")
				e = kvmsg.Send(srv.publisher)
				if e != nil {
					err = e
				}
				kvmsg.Store(srv.kvmap)
				log.Println("I: publishing delete =", srv.sequence)
			}
		}
	}
	return
}
Beispiel #3
0
func collector(srv *clonesrv_t) (err error) {

	kvmsg, err := kvmsg.RecvKvmsg(srv.collector)
	if err != nil {
		return
	}

	if srv.active {
		srv.sequence++
		kvmsg.SetSequence(srv.sequence)
		kvmsg.Send(srv.publisher)
		if ttls, e := kvmsg.GetProp("ttl"); e == nil {
			ttl, e := strconv.ParseInt(ttls, 10, 64)
			if e != nil {
				err = e
				return
			}
			kvmsg.SetProp("ttl", fmt.Sprint(time.Now().Add(time.Duration(ttl)*time.Second).Unix()))
		}
		kvmsg.Store(srv.kvmap)
		log.Println("I: publishing update =", srv.sequence)
	} else {
		//  If we already got message from active, drop it, else
		//  hold on pending list
		if !srv.was_pending(kvmsg) {
			srv.pending = append(srv.pending, kvmsg)
		}
	}
	return
}
Beispiel #4
0
func send_hugz(srv *clonesrv_t) (err error) {

	kvmsg := kvmsg.NewKvmsg(srv.sequence)
	kvmsg.SetKey("HUGZ")
	kvmsg.SetBody("")
	err = kvmsg.Send(srv.publisher)
	return
}
Beispiel #5
0
func (agent *agent_t) control_message() (err error) {
	msg, e := agent.pipe.RecvMessage(0)
	if e != nil {
		return e
	}
	command := msg[0]
	msg = msg[1:]

	switch command {
	case "SUBTREE":
		agent.subtree = msg[0]
	case "CONNECT":
		address := msg[0]
		service := msg[1]
		if agent.nbr_servers < server_MAX {
			serv, _ := strconv.Atoi(service)
			agent.server[agent.nbr_servers] = server_new(address, serv, agent.subtree)
			agent.nbr_servers++
			//  We broadcast updates to all known servers
			agent.publisher.Connect(fmt.Sprintf("%s:%d", address, serv+2))
		} else {
			fmt.Printf("E: too many servers (max. %d)\n", server_MAX)
		}
	case "SET":
		//  When we set a property, we push the new key-value pair onto
		//  all our connected servers:
		key := msg[0]
		value := msg[1]
		ttl := msg[2]

		//  Send key-value pair on to server
		kvmsg := kvmsg.NewKvmsg(0)
		kvmsg.SetKey(key)
		kvmsg.SetUuid()
		kvmsg.SetBody(value)
		kvmsg.SetProp("ttl", ttl)
		kvmsg.Store(agent.kvmap)
		kvmsg.Send(agent.publisher)
	case "GET":
		key := msg[0]
		value := ""
		if kvmsg, ok := agent.kvmap[key]; ok {
			value, _ = kvmsg.GetBody()
		}
		agent.pipe.SendMessage(value)
	}
	return
}
Beispiel #6
0
func collector(srv *clonesrv_t) (err error) {
	kvmsg, err := kvmsg.RecvKvmsg(srv.collector)
	if err != nil {
		return
	}

	srv.sequence++
	kvmsg.SetSequence(srv.sequence)
	kvmsg.Send(srv.publisher)
	if ttls, e := kvmsg.GetProp("ttl"); e == nil {
		// change duration into specific time, using the same property: ugly!
		ttl, e := strconv.ParseInt(ttls, 10, 64)
		if e != nil {
			err = e
			return
		}
		kvmsg.SetProp("ttl", fmt.Sprint(time.Now().Add(time.Duration(ttl)*time.Second).Unix()))
	}
	kvmsg.Store(srv.kvmap)
	log.Println("I: publishing update =", srv.sequence)

	return
}
Beispiel #7
0
func main() {
	snapshot, _ := zmq.NewSocket(zmq.DEALER)
	snapshot.Connect("tcp://localhost:5556")
	subscriber, _ := zmq.NewSocket(zmq.SUB)
	subscriber.SetSubscribe(SUBTREE)
	subscriber.Connect("tcp://localhost:5557")
	publisher, _ := zmq.NewSocket(zmq.PUSH)
	publisher.Connect("tcp://localhost:5558")

	kvmap := make(map[string]*kvmsg.Kvmsg)
	rand.Seed(time.Now().UnixNano())

	//  We first request a state snapshot:
	sequence := int64(0)
	snapshot.SendMessage("ICANHAZ?", SUBTREE)
	for {
		kvmsg, err := kvmsg.RecvKvmsg(snapshot)
		if err != nil {
			break //  Interrupted
		}
		if key, _ := kvmsg.GetKey(); key == "KTHXBAI" {
			sequence, _ := kvmsg.GetSequence()
			fmt.Println("I: received snapshot =", sequence)
			break //  Done
		}
		kvmsg.Store(kvmap)
	}
	snapshot.Close()

	poller := zmq.NewPoller()
	poller.Add(subscriber, zmq.POLLIN)
	alarm := time.Now().Add(1000 * time.Millisecond)
	for {
		tickless := alarm.Sub(time.Now())
		if tickless < 0 {
			tickless = 0
		}
		polled, err := poller.Poll(tickless)
		if err != nil {
			break //  Context has been shut down
		}
		if len(polled) == 1 {
			kvmsg, err := kvmsg.RecvKvmsg(subscriber)
			if err != nil {
				break //  Interrupted
			}

			//  Discard out-of-sequence kvmsgs, incl. heartbeats
			if seq, _ := kvmsg.GetSequence(); seq > sequence {
				sequence = seq
				kvmsg.Store(kvmap)
				fmt.Println("I: received update =", sequence)
			}
		}
		//  If we timed-out, generate a random kvmsg
		if time.Now().After(alarm) {
			kvmsg := kvmsg.NewKvmsg(0)
			kvmsg.SetKey(fmt.Sprintf("%s%d", SUBTREE, rand.Intn(10000)))
			kvmsg.SetBody(fmt.Sprint(rand.Intn(1000000)))
			kvmsg.SetProp("ttl", fmt.Sprintf("%d", rand.Intn((30)))) // seconds
			kvmsg.Send(publisher)
			alarm = time.Now().Add(1000 * time.Millisecond)
		}
	}
	fmt.Printf("Interrupted\n%d messages in\n", sequence)
}