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}