예제 #1
0
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)
	}
}
예제 #2
0
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
}