func handleChosen(slot uint64) { var msg fproto.InstructionChosen msg.Slot = new(uint64) *msg.Slot = slot msgBuf, err := proto.Marshal(&msg) if err != nil { panic("generated bad instruction chosen message") } var baseMsg baseproto.Message baseMsg.MsgType = new(uint32) *baseMsg.MsgType = 7 baseMsg.Content = msgBuf connectionsLock.Lock() for _, conn := range connections { conn.lock.Lock() if !conn.sendingBurst { conn.conn.Send(&baseMsg) } if timer, exists := conn.offerTimers[slot]; exists { timer.Stop() delete(conn.offerTimers, slot) } conn.lock.Unlock() } connectionsLock.Unlock() }
// Sends a burst to the given connection. // The Bursting message should already have been sent, // and f.sendingBurst set to true, before calling this asynchronously. func sendBurst(f *followConn) { log.Print("shared/follow: sending burst to ", f.node) globalProp := new(fproto.GlobalProperty) globalProp.Key = new(string) globalProp.Value = new(string) entityProp := new(fproto.EntityProperty) entityProp.Entity = new(uint64) entityProp.Key = new(string) entityProp.Value = new(string) aborted := false store.Burst(func(key, value string) bool { *globalProp.Key = key *globalProp.Value = value if !f.conn.SendProto(4, globalProp) { aborted = true } return !aborted }, func(entity uint64, key, value string) bool { *entityProp.Entity = entity *entityProp.Key = key *entityProp.Value = value if !f.conn.SendProto(5, entityProp) { aborted = true } return !aborted }) if aborted { return } store.StartTransaction() defer store.EndTransaction() f.lock.Lock() defer f.lock.Unlock() f.sendingBurst = false burstDone := new(fproto.BurstDone) burstDone.FirstUnapplied = new(uint64) *burstDone.FirstUnapplied = store.InstructionFirstUnapplied() f.conn.SendProto(6, burstDone) // Send an instruction chosen message for all chosen instructions above // our first unapplied point. instructions := store.InstructionSlots() firstUnapplied := store.InstructionFirstUnapplied() relativeSlot := int(firstUnapplied - store.InstructionStart()) for ; relativeSlot < len(instructions); relativeSlot++ { slot := store.InstructionStart() + uint64(relativeSlot) slotValues := instructions[relativeSlot] if len(slotValues) != 1 || !slotValues[0].IsChosen() { continue } // Convert the change request to our internal format. chosen := new(fproto.InstructionChosen) chosen.Slot = new(uint64) *chosen.Slot = slot f.conn.SendProto(7, chosen) } }