1/*
2 * Copyright 2021-2022, Andrew Lindesay <apl@lindesay.co.nz>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6
7#include "AbstractProcessNode.h"
8
9#include <unistd.h>
10
11#include "AbstractProcess.h"
12#include "Logger.h"
13
14
15#define SPIN_DELAY_MI 500 * 1000
16	// half of a second
17
18#define TIMEOUT_UNTIL_STARTED_SECS 10
19#define TIMEOUT_UNTIL_STOPPED_SECS 10
20
21
22AbstractProcessNode::AbstractProcessNode(AbstractProcess* process)
23	:
24	fLock(),
25	fListener(NULL),
26	fProcess(process)
27{
28}
29
30
31AbstractProcessNode::~AbstractProcessNode()
32{
33	delete fProcess;
34}
35
36
37AbstractProcess*
38AbstractProcessNode::Process() const
39{
40	return fProcess;
41}
42
43
44bool
45AbstractProcessNode::IsRunning()
46{
47	return Process()->ProcessState() == PROCESS_RUNNING;
48}
49
50
51void
52AbstractProcessNode::SetListener(ProcessListener* listener)
53{
54	if (fListener != listener) {
55		AutoLocker<BLocker> locker(&fLock);
56		fListener = listener;
57	}
58}
59
60
61/*! This method will spin-lock the thread until the process is in one of the
62    states defined by the mask.
63 */
64
65status_t
66AbstractProcessNode::_SpinUntilProcessState(
67	uint32 desiredStatesMask, int32 timeoutSeconds)
68{
69	bigtime_t start = system_time();
70	while (true) {
71		if ((Process()->ProcessState() & desiredStatesMask) != 0)
72			return B_OK;
73
74		usleep(SPIN_DELAY_MI);
75
76		int32 secondElapsed = static_cast<int32>(
77			(system_time() - start) / (1000 * 1000));
78
79		if (timeoutSeconds > 0 && secondElapsed > timeoutSeconds) {
80			HDERROR("[Node<%s>] timeout waiting for process state after %"
81				B_PRIi32 " seconds", Process()->Name(), secondElapsed);
82			return B_ERROR;
83		}
84	}
85}
86
87
88void
89AbstractProcessNode::AddPredecessor(AbstractProcessNode *node)
90{
91	fPredecessorNodes.AddItem(node);
92	node->_AddSuccessor(this);
93}
94
95
96int32
97AbstractProcessNode::CountPredecessors() const
98{
99	return fPredecessorNodes.CountItems();
100}
101
102
103AbstractProcessNode*
104AbstractProcessNode::PredecessorAt(int32 index) const
105{
106	return fPredecessorNodes.ItemAt(index);
107}
108
109
110bool
111AbstractProcessNode::AllPredecessorsComplete() const
112{
113	for (int32 i = 0; i < CountPredecessors(); i++) {
114		if (PredecessorAt(i)->Process()->ProcessState() != PROCESS_COMPLETE)
115			return false;
116	}
117
118	return true;
119}
120
121
122void
123AbstractProcessNode::_AddSuccessor(AbstractProcessNode* node)
124{
125	fSuccessorNodes.AddItem(node);
126}
127
128
129int32
130AbstractProcessNode::CountSuccessors() const
131{
132	return fSuccessorNodes.CountItems();
133}
134
135
136AbstractProcessNode*
137AbstractProcessNode::SuccessorAt(int32 index) const
138{
139	return fSuccessorNodes.ItemAt(index);
140}
141
142
143BString
144AbstractProcessNode::LogReport()
145{
146	return Process()->LogReport();
147}