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 22 AbstractProcessNode::AbstractProcessNode(AbstractProcess* process) 23 : 24 fLock(), 25 fListener(NULL), 26 fProcess(process) 27 { 28 } 29 30 31 AbstractProcessNode::~AbstractProcessNode() 32 { 33 delete fProcess; 34 } 35 36 37 AbstractProcess* 38 AbstractProcessNode::Process() const 39 { 40 return fProcess; 41 } 42 43 44 bool 45 AbstractProcessNode::IsRunning() 46 { 47 return Process()->ProcessState() == PROCESS_RUNNING; 48 } 49 50 51 void 52 AbstractProcessNode::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 65 status_t 66 AbstractProcessNode::_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 88 void 89 AbstractProcessNode::AddPredecessor(AbstractProcessNode *node) 90 { 91 fPredecessorNodes.AddItem(node); 92 node->_AddSuccessor(this); 93 } 94 95 96 int32 97 AbstractProcessNode::CountPredecessors() const 98 { 99 return fPredecessorNodes.CountItems(); 100 } 101 102 103 AbstractProcessNode* 104 AbstractProcessNode::PredecessorAt(int32 index) const 105 { 106 return fPredecessorNodes.ItemAt(index); 107 } 108 109 110 bool 111 AbstractProcessNode::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 122 void 123 AbstractProcessNode::_AddSuccessor(AbstractProcessNode* node) 124 { 125 fSuccessorNodes.AddItem(node); 126 } 127 128 129 int32 130 AbstractProcessNode::CountSuccessors() const 131 { 132 return fSuccessorNodes.CountItems(); 133 } 134 135 136 AbstractProcessNode* 137 AbstractProcessNode::SuccessorAt(int32 index) const 138 { 139 return fSuccessorNodes.ItemAt(index); 140 } 141 142 143 BString 144 AbstractProcessNode::LogReport() 145 { 146 return Process()->LogReport(); 147 }