コード例 #1
0
ファイル: process.go プロジェクト: jbeshir/unanimity
// Performs handling of all Change Request Protocol messages,
// over all connections. Has exclusive access to forward timeout information,
// and uses requestTimeoutLock for access to request timeout information.
// Top-level function of the processing goroutine.
func process() {
	for {
		select {
		// Requesting Change Request Timeout
		case timeout := <-requestTimedOut:

			requestTimeoutLock.Lock()

			if timeout.canceled {
				break
			}

			log.Print("shared/chrequest: request timeout: ",
				*timeout.request.RequestId)

			// Remove this request timeout.
			cancelRequestTimeout(
				uint16(*timeout.request.RequestNode),
				*timeout.request.RequestId)

			// Request the change again, with double the timeout.
			addRequestTimeout(timeout.request, timeout.duration*2)

			requestTimeoutLock.Unlock()

			forward := new(chproto.ChangeForward)
			forward.Request = timeout.request
			processForward(forward)

		// Forwarded Change Forward Timeout
		case timeout := <-forwardTimedOut:
			if timeout.canceled {
				break
			}

			// Remove this forward timeout.
			cancelForwardTimeout(
				uint16(*timeout.forward.Request.RequestNode),
				*timeout.forward.Request.RequestId)

			// Try sending it somewhere else.
			processForward(timeout.forward)

		// New Change Request
		case newRequest := <-newRequestCh:

			requestTimeoutLock.Lock()

			addRequestTimeout(newRequest,
				config.CHANGE_TIMEOUT_PERIOD)

			requestTimeoutLock.Unlock()

			forward := new(chproto.ChangeForward)
			forward.Request = newRequest
			processForward(forward)

		// Received Change Forward Message
		case receivedForward := <-receivedForwardCh:
			processForward(receivedForward.forward)

		// Received Change Forward Ack Message
		case receivedAck := <-receivedAckCh:

			ack := receivedAck.ack

			// If we did not have a forwarded change forward,
			// with this requesting node and request ID,
			// and this node as the last node it was sent to,
			// discard the message.
			timeout, exists := getForwardTimeout(
				uint16(*ack.RequestNode),
				*ack.RequestId)
			if !exists {
				break
			}
			ignores := timeout.forward.Ignores
			if uint16(ignores[len(ignores)-1]) != receivedAck.node {
				break
			}

			// Remove this forward timeout.
			cancelForwardTimeout(
				uint16(*timeout.forward.Request.RequestNode),
				*timeout.forward.Request.RequestId)

		// Connection Terminated
		case terminatedConn := <-terminatedConnCh:
			node := terminatedConn.node
			conn := terminatedConn.conn

			// Remove this connection from our connection list.
			index := -1
			for i, _ := range connections[node] {
				if conn == connections[node][i] {
					index = i
					break
				}
			}
			if index == -1 {
				break
			}

			connections[node] = append(connections[node][:index],
				connections[node][index+1:]...)

		// Connection Received
		case receivedConn := <-receivedConnCh:
			node := receivedConn.node
			conn := receivedConn.conn

			// Add to our connections list.
			connections[node] = append(connections[node], conn)
		}
	}
}