/// <summary> /// Constructor. /// </summary> public SchedulingEvent(DateTime eventTime, SchedulableRequest request, SchedulableRequestState oldState, SchedulableRequestState newState) { _eventTime = eventTime; _request = request; _oldState = oldState; _newState = newState; }
/// <summary> /// Change to the specified state. Update internal counters. /// </summary> private void ChangeToState(SchedulableRequestState newState) { DateTime currentTime = DateTime.UtcNow; _timeRecords[_state].EndState(currentTime); _timeRecords[newState].StartState(currentTime); if (_state != newState) { SchedulableRequestState previousState = _state; _state = newState; _schedulingData.UpdateFromState(this, previousState); } }
/// <summary> /// Verifies that the request is scheduled and in the expected state. /// </summary> private void ExpectScheduledRequestState(int globalRequestId, SchedulableRequestState state) { SchedulableRequest request = InternalGetScheduledRequestByGlobalRequestId(globalRequestId); if (request == null) { ErrorUtilities.ThrowInternalError("Request {0} was expected to be in state {1} but is not scheduled at all (it may be unscheduled or may be unknown to the system.)", globalRequestId, state); } else { request.VerifyState(state); } }
/// <summary> /// Verifies that the current state is as expected. /// </summary> public void VerifyOneOfStates(SchedulableRequestState[] requiredStates) { foreach (SchedulableRequestState requiredState in requiredStates) { if (_state == requiredState) { return; } } ErrorUtilities.ThrowInternalError("State {0} is not one of the expected states.", _state); }
/// <summary> /// Verifies that the current state is as expected. /// </summary> public void VerifyState(SchedulableRequestState requiredState) { ErrorUtilities.VerifyThrow(_state == requiredState, "Request {0} expected to be in state {1} but state is actually {2}", _request.GlobalRequestId, requiredState, _state); }
/// <summary> /// Gets the amount of time we spent in the specified state. /// </summary> public TimeSpan GetTimeSpentInState(SchedulableRequestState desiredState) { return _timeRecords[desiredState].AccumulatedTime; }
/// <summary> /// Gets the amount of time we spent in the specified state. /// </summary> public TimeSpan GetTimeSpentInState(SchedulableRequestState desiredState) { return(_timeRecords[desiredState].AccumulatedTime); }
/// <summary> /// Updates the state of the specified request. /// </summary> public void UpdateFromState(SchedulableRequest request, SchedulableRequestState previousState) { // Remove from its old collection switch (previousState) { case SchedulableRequestState.Blocked: _blockedRequests.Remove(request.BuildRequest.GlobalRequestId); break; case SchedulableRequestState.Yielding: _yieldingRequests.Remove(request.BuildRequest.GlobalRequestId); break; case SchedulableRequestState.Completed: ErrorUtilities.ThrowInternalError("Should not be updating a request after it has reached the Completed state."); break; case SchedulableRequestState.Executing: _executingRequests.Remove(request.BuildRequest.GlobalRequestId); _executingRequestByNode[request.AssignedNode] = null; break; case SchedulableRequestState.Ready: _readyRequests.Remove(request.BuildRequest.GlobalRequestId); _readyRequestsByNode[request.AssignedNode].Remove(request); break; case SchedulableRequestState.Unscheduled: LinkedListNode <SchedulableRequest> requestNode = _unscheduledRequestNodesByRequest[request]; _unscheduledRequestNodesByRequest.Remove(request); _unscheduledRequests.Remove(requestNode); if (request.State != SchedulableRequestState.Completed) { // Map the request to the node. HashSet <SchedulableRequest> requestsAssignedToNode; if (!_scheduledRequestsByNode.TryGetValue(request.AssignedNode, out requestsAssignedToNode)) { requestsAssignedToNode = new HashSet <SchedulableRequest>(); _scheduledRequestsByNode[request.AssignedNode] = requestsAssignedToNode; } ErrorUtilities.VerifyThrow(!requestsAssignedToNode.Contains(request), "Request {0} is already scheduled to node {1}", request.BuildRequest.GlobalRequestId, request.AssignedNode); requestsAssignedToNode.Add(request); // Map the configuration to the node. HashSet <int> configurationsAssignedToNode; if (!_configurationsByNode.TryGetValue(request.AssignedNode, out configurationsAssignedToNode)) { configurationsAssignedToNode = new HashSet <int>(); _configurationsByNode[request.AssignedNode] = configurationsAssignedToNode; } if (!configurationsAssignedToNode.Contains(request.BuildRequest.ConfigurationId)) { configurationsAssignedToNode.Add(request.BuildRequest.ConfigurationId); } } break; } // Add it to its new location switch (request.State) { case SchedulableRequestState.Blocked: ErrorUtilities.VerifyThrow(!_blockedRequests.ContainsKey(request.BuildRequest.GlobalRequestId), "Request with global id {0} is already blocked!"); _blockedRequests[request.BuildRequest.GlobalRequestId] = request; break; case SchedulableRequestState.Yielding: ErrorUtilities.VerifyThrow(!_yieldingRequests.ContainsKey(request.BuildRequest.GlobalRequestId), "Request with global id {0} is already yielded!"); _yieldingRequests[request.BuildRequest.GlobalRequestId] = request; break; case SchedulableRequestState.Completed: ErrorUtilities.VerifyThrow(_configurationToRequests.ContainsKey(request.BuildRequest.ConfigurationId), "Configuration {0} never had requests assigned to it.", request.BuildRequest.ConfigurationId); ErrorUtilities.VerifyThrow(_configurationToRequests[request.BuildRequest.ConfigurationId].Count > 0, "Configuration {0} has no requests assigned to it.", request.BuildRequest.ConfigurationId); _configurationToRequests[request.BuildRequest.ConfigurationId].Remove(request); if (_scheduledRequestsByNode.ContainsKey(request.AssignedNode)) { _scheduledRequestsByNode[request.AssignedNode].Remove(request); } request.EndTime = EventTime; break; case SchedulableRequestState.Executing: ErrorUtilities.VerifyThrow(!_executingRequests.ContainsKey(request.BuildRequest.GlobalRequestId), "Request with global id {0} is already executing!"); ErrorUtilities.VerifyThrow(!_executingRequestByNode.ContainsKey(request.AssignedNode) || _executingRequestByNode[request.AssignedNode] == null, "Node {0} is currently executing a request.", request.AssignedNode); _executingRequests[request.BuildRequest.GlobalRequestId] = request; _executingRequestByNode[request.AssignedNode] = request; _configurationToNode[request.BuildRequest.ConfigurationId] = request.AssignedNode; if (previousState == SchedulableRequestState.Unscheduled) { request.StartTime = EventTime; } break; case SchedulableRequestState.Ready: ErrorUtilities.VerifyThrow(!_readyRequests.ContainsKey(request.BuildRequest.GlobalRequestId), "Request with global id {0} is already ready!"); _readyRequests[request.BuildRequest.GlobalRequestId] = request; HashSet <SchedulableRequest> readyRequestsOnNode; if (!_readyRequestsByNode.TryGetValue(request.AssignedNode, out readyRequestsOnNode)) { readyRequestsOnNode = new HashSet <SchedulableRequest>(); _readyRequestsByNode[request.AssignedNode] = readyRequestsOnNode; } ErrorUtilities.VerifyThrow(!readyRequestsOnNode.Contains(request), "Request with global id {0} is already marked as ready on node {1}", request.BuildRequest.GlobalRequestId, request.AssignedNode); readyRequestsOnNode.Add(request); break; case SchedulableRequestState.Unscheduled: ErrorUtilities.ThrowInternalError("Request with global id {0} cannot transition to the Unscheduled state", request.BuildRequest.GlobalRequestId); break; } _buildEvents.Add(new SchedulingEvent(EventTime, request, previousState, request.State)); }
/// <summary> /// Updates the state of the specified request. /// </summary> public void UpdateFromState(SchedulableRequest request, SchedulableRequestState previousState) { // Remove from its old collection switch (previousState) { case SchedulableRequestState.Blocked: _blockedRequests.Remove(request.BuildRequest.GlobalRequestId); break; case SchedulableRequestState.Yielding: _yieldingRequests.Remove(request.BuildRequest.GlobalRequestId); break; case SchedulableRequestState.Completed: ErrorUtilities.ThrowInternalError("Should not be updating a request after it has reached the Completed state."); break; case SchedulableRequestState.Executing: _executingRequests.Remove(request.BuildRequest.GlobalRequestId); _executingRequestByNode[request.AssignedNode] = null; break; case SchedulableRequestState.Ready: _readyRequests.Remove(request.BuildRequest.GlobalRequestId); _readyRequestsByNode[request.AssignedNode].Remove(request); break; case SchedulableRequestState.Unscheduled: LinkedListNode<SchedulableRequest> requestNode = _unscheduledRequestNodesByRequest[request]; _unscheduledRequestNodesByRequest.Remove(request); _unscheduledRequests.Remove(requestNode); if (request.State != SchedulableRequestState.Completed) { // Map the request to the node. HashSet<SchedulableRequest> requestsAssignedToNode; if (!_scheduledRequestsByNode.TryGetValue(request.AssignedNode, out requestsAssignedToNode)) { requestsAssignedToNode = new HashSet<SchedulableRequest>(); _scheduledRequestsByNode[request.AssignedNode] = requestsAssignedToNode; } ErrorUtilities.VerifyThrow(!requestsAssignedToNode.Contains(request), "Request {0} is already scheduled to node {1}", request.BuildRequest.GlobalRequestId, request.AssignedNode); requestsAssignedToNode.Add(request); // Map the configuration to the node. HashSet<int> configurationsAssignedToNode; if (!_configurationsByNode.TryGetValue(request.AssignedNode, out configurationsAssignedToNode)) { configurationsAssignedToNode = new HashSet<int>(); _configurationsByNode[request.AssignedNode] = configurationsAssignedToNode; } if (!configurationsAssignedToNode.Contains(request.BuildRequest.ConfigurationId)) { configurationsAssignedToNode.Add(request.BuildRequest.ConfigurationId); } } break; } // Add it to its new location switch (request.State) { case SchedulableRequestState.Blocked: ErrorUtilities.VerifyThrow(!_blockedRequests.ContainsKey(request.BuildRequest.GlobalRequestId), "Request with global id {0} is already blocked!"); _blockedRequests[request.BuildRequest.GlobalRequestId] = request; break; case SchedulableRequestState.Yielding: ErrorUtilities.VerifyThrow(!_yieldingRequests.ContainsKey(request.BuildRequest.GlobalRequestId), "Request with global id {0} is already yielded!"); _yieldingRequests[request.BuildRequest.GlobalRequestId] = request; break; case SchedulableRequestState.Completed: ErrorUtilities.VerifyThrow(_configurationToRequests.ContainsKey(request.BuildRequest.ConfigurationId), "Configuration {0} never had requests assigned to it.", request.BuildRequest.ConfigurationId); ErrorUtilities.VerifyThrow(_configurationToRequests[request.BuildRequest.ConfigurationId].Count > 0, "Configuration {0} has no requests assigned to it.", request.BuildRequest.ConfigurationId); _configurationToRequests[request.BuildRequest.ConfigurationId].Remove(request); if (_scheduledRequestsByNode.ContainsKey(request.AssignedNode)) { _scheduledRequestsByNode[request.AssignedNode].Remove(request); } request.EndTime = EventTime; break; case SchedulableRequestState.Executing: ErrorUtilities.VerifyThrow(!_executingRequests.ContainsKey(request.BuildRequest.GlobalRequestId), "Request with global id {0} is already executing!"); ErrorUtilities.VerifyThrow(!_executingRequestByNode.ContainsKey(request.AssignedNode) || _executingRequestByNode[request.AssignedNode] == null, "Node {0} is currently executing a request.", request.AssignedNode); _executingRequests[request.BuildRequest.GlobalRequestId] = request; _executingRequestByNode[request.AssignedNode] = request; _configurationToNode[request.BuildRequest.ConfigurationId] = request.AssignedNode; if (previousState == SchedulableRequestState.Unscheduled) { request.StartTime = EventTime; } break; case SchedulableRequestState.Ready: ErrorUtilities.VerifyThrow(!_readyRequests.ContainsKey(request.BuildRequest.GlobalRequestId), "Request with global id {0} is already ready!"); _readyRequests[request.BuildRequest.GlobalRequestId] = request; HashSet<SchedulableRequest> readyRequestsOnNode; if (!_readyRequestsByNode.TryGetValue(request.AssignedNode, out readyRequestsOnNode)) { readyRequestsOnNode = new HashSet<SchedulableRequest>(); _readyRequestsByNode[request.AssignedNode] = readyRequestsOnNode; } ErrorUtilities.VerifyThrow(!readyRequestsOnNode.Contains(request), "Request with global id {0} is already marked as ready on node {1}", request.BuildRequest.GlobalRequestId, request.AssignedNode); readyRequestsOnNode.Add(request); break; case SchedulableRequestState.Unscheduled: ErrorUtilities.ThrowInternalError("Request with global id {0} cannot transition to the Unscheduled state", request.BuildRequest.GlobalRequestId); break; } _buildEvents.Add(new SchedulingEvent(EventTime, request, previousState, request.State)); }