func TestStdinRegistrarWait(t *testing.T) { p, r := newTestStdinRegistrar() // Start the stdin registrar go func() { r.Run() }() c := r.Connect() c.Add(registrar.NewAckEvent(newEventSpool(13))) c.Send() r.Wait(13) wait := make(chan int) go func() { p.Wait() wait <- 1 }() select { case <-wait: break case <-time.After(5 * time.Second): t.Error("Timeout waiting for stdin registrar shutdown") return } if r.last_offset != 13 { t.Error("Last offset was incorrect: ", r.last_offset) } else if r.wait_offset == nil || *r.wait_offset != 13 { t.Error("Wait offset was incorrect: ", r.wait_offset) } }
func (p *Publisher) processAck(message []byte) (err error) { if len(message) != 20 { err = fmt.Errorf("ACKN message corruption (%d)", len(message)) return } // Read the nonce and sequence number acked nonce, sequence := string(message[:16]), binary.BigEndian.Uint32(message[16:20]) log.Debug("ACKN message received for payload %x sequence %d", nonce, sequence) // Grab the payload the ACK corresponds to by using nonce payload, found := p.pending_payloads[nonce] if !found { // Don't fail here in case we had temporary issues and resend a payload, only for us to receive duplicate ACKN return } ack_events := payload.ack_events // Process ACK lines, complete := payload.Ack(int(sequence)) p.line_count += int64(lines) if complete { // No more events left for this payload, remove from pending list delete(p.pending_payloads, nonce) } // We potentially receive out-of-order ACKs due to payloads distributed across servers // This is where we enforce ordering again to ensure registrar receives ACK in order if payload == p.first_payload { // The out of sync count we have will never include the first payload, so // take the value +1 out_of_sync := p.out_of_sync + 1 // For each full payload we mark off, we decrease this count, the first we // mark off will always be the first payload - thus the +1. Subsequent // payloads are the out of sync ones - so if we mark them off we decrease // the out of sync count for payload.HasAck() { p.registrar_spool.Add(registrar.NewAckEvent(payload.Rollup())) if !payload.Complete() { break } payload = payload.next p.first_payload = payload out_of_sync-- p.out_of_sync = out_of_sync p.Lock() p.num_payloads-- p.Unlock() // Resume sending if we stopped due to excessive pending payload count if !p.shutdown && p.can_send == nil { p.can_send = p.transport.CanSend() } if payload == nil { break } } p.registrar_spool.Send() } else if ack_events == 0 { // If this is NOT the first payload, and this is the first acknowledgement // for this payload, then increase out of sync payload count p.out_of_sync++ } return }