[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class DrydockLease extends DrydockDAO 4 implements PhabricatorPolicyInterface { 5 6 protected $resourceID; 7 protected $resourceType; 8 protected $until; 9 protected $ownerPHID; 10 protected $attributes = array(); 11 protected $status = DrydockLeaseStatus::STATUS_PENDING; 12 protected $taskID; 13 14 private $resource = self::ATTACHABLE; 15 private $releaseOnDestruction; 16 17 /** 18 * Flag this lease to be released when its destructor is called. This is 19 * mostly useful if you have a script which acquires, uses, and then releases 20 * a lease, as you don't need to explicitly handle exceptions to properly 21 * release the lease. 22 */ 23 public function releaseOnDestruction() { 24 $this->releaseOnDestruction = true; 25 return $this; 26 } 27 28 public function __destruct() { 29 if ($this->releaseOnDestruction) { 30 if ($this->isActive()) { 31 $this->release(); 32 } 33 } 34 } 35 36 public function getLeaseName() { 37 return pht('Lease %d', $this->getID()); 38 } 39 40 public function getConfiguration() { 41 return array( 42 self::CONFIG_AUX_PHID => true, 43 self::CONFIG_SERIALIZATION => array( 44 'attributes' => self::SERIALIZATION_JSON, 45 ), 46 self::CONFIG_COLUMN_SCHEMA => array( 47 'status' => 'uint32', 48 'until' => 'epoch?', 49 'resourceType' => 'text128', 50 'taskID' => 'id?', 51 'ownerPHID' => 'phid?', 52 'resourceID' => 'id?', 53 ), 54 self::CONFIG_KEY_SCHEMA => array( 55 'key_phid' => null, 56 'phid' => array( 57 'columns' => array('phid'), 58 'unique' => true, 59 ), 60 ), 61 ) + parent::getConfiguration(); 62 } 63 64 public function setAttribute($key, $value) { 65 $this->attributes[$key] = $value; 66 return $this; 67 } 68 69 public function getAttribute($key, $default = null) { 70 return idx($this->attributes, $key, $default); 71 } 72 73 public function generatePHID() { 74 return PhabricatorPHID::generateNewPHID(DrydockLeasePHIDType::TYPECONST); 75 } 76 77 public function getInterface($type) { 78 return $this->getResource()->getInterface($this, $type); 79 } 80 81 public function getResource() { 82 return $this->assertAttached($this->resource); 83 } 84 85 public function attachResource(DrydockResource $resource = null) { 86 $this->resource = $resource; 87 return $this; 88 } 89 90 public function hasAttachedResource() { 91 return ($this->resource !== null); 92 } 93 94 public function loadResource() { 95 return id(new DrydockResource())->loadOneWhere( 96 'id = %d', 97 $this->getResourceID()); 98 } 99 100 public function queueForActivation() { 101 if ($this->getID()) { 102 throw new Exception( 103 'Only new leases may be queued for activation!'); 104 } 105 106 $this->setStatus(DrydockLeaseStatus::STATUS_PENDING); 107 $this->save(); 108 109 $task = PhabricatorWorker::scheduleTask( 110 'DrydockAllocatorWorker', 111 $this->getID()); 112 113 // NOTE: Scheduling the task might execute it in-process, if we're running 114 // from a CLI script. Reload the lease to make sure we have the most 115 // up-to-date information. Normally, this has no effect. 116 $this->reload(); 117 118 $this->setTaskID($task->getID()); 119 $this->save(); 120 121 return $this; 122 } 123 124 public function release() { 125 $this->assertActive(); 126 $this->setStatus(DrydockLeaseStatus::STATUS_RELEASED); 127 $this->save(); 128 129 $this->resource = null; 130 131 return $this; 132 } 133 134 public function isActive() { 135 switch ($this->status) { 136 case DrydockLeaseStatus::STATUS_ACTIVE: 137 case DrydockLeaseStatus::STATUS_ACQUIRING: 138 return true; 139 } 140 return false; 141 } 142 143 private function assertActive() { 144 if (!$this->isActive()) { 145 throw new Exception( 146 'Lease is not active! You can not interact with resources through '. 147 'an inactive lease.'); 148 } 149 } 150 151 public static function waitForLeases(array $leases) { 152 assert_instances_of($leases, 'DrydockLease'); 153 154 $task_ids = array_filter(mpull($leases, 'getTaskID')); 155 156 PhabricatorWorker::waitForTasks($task_ids); 157 158 $unresolved = $leases; 159 while (true) { 160 foreach ($unresolved as $key => $lease) { 161 $lease->reload(); 162 switch ($lease->getStatus()) { 163 case DrydockLeaseStatus::STATUS_ACTIVE: 164 unset($unresolved[$key]); 165 break; 166 case DrydockLeaseStatus::STATUS_RELEASED: 167 throw new Exception('Lease has already been released!'); 168 case DrydockLeaseStatus::STATUS_EXPIRED: 169 throw new Exception('Lease has already expired!'); 170 case DrydockLeaseStatus::STATUS_BROKEN: 171 throw new Exception('Lease has been broken!'); 172 case DrydockLeaseStatus::STATUS_PENDING: 173 case DrydockLeaseStatus::STATUS_ACQUIRING: 174 break; 175 default: 176 throw new Exception('Unknown status??'); 177 } 178 } 179 180 if ($unresolved) { 181 sleep(1); 182 } else { 183 break; 184 } 185 } 186 187 foreach ($leases as $lease) { 188 $lease->attachResource($lease->loadResource()); 189 } 190 } 191 192 public function waitUntilActive() { 193 if (!$this->getID()) { 194 $this->queueForActivation(); 195 } 196 197 self::waitForLeases(array($this)); 198 return $this; 199 } 200 201 202 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 203 204 205 public function getCapabilities() { 206 return array( 207 PhabricatorPolicyCapability::CAN_VIEW, 208 ); 209 } 210 211 public function getPolicy($capability) { 212 if ($this->getResource()) { 213 return $this->getResource()->getPolicy($capability); 214 } 215 return PhabricatorPolicies::getMostOpenPolicy(); 216 } 217 218 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 219 if ($this->getResource()) { 220 return $this->getResource()->hasAutomaticCapability($capability, $viewer); 221 } 222 return false; 223 } 224 225 public function describeAutomaticCapability($capability) { 226 return pht('Leases inherit policies from the resources they lease.'); 227 } 228 229 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |