Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F19485791
D13507.id33781.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
D13507.id33781.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -869,6 +869,7 @@
'DrydockWebrootInterface' => 'applications/drydock/interface/webroot/DrydockWebrootInterface.php',
'DrydockWinRMCommandInterface' => 'applications/drydock/interface/command/DrydockWinRMCommandInterface.php',
'DrydockWorkingCopyBlueprintImplementation' => 'applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php',
+ 'DrydockWorkingCopyCacheBlueprintImplementation' => 'applications/drydock/blueprint/DrydockWorkingCopyCacheBlueprintImplementation.php',
'FeedConduitAPIMethod' => 'applications/feed/conduit/FeedConduitAPIMethod.php',
'FeedPublishConduitAPIMethod' => 'applications/feed/conduit/FeedPublishConduitAPIMethod.php',
'FeedPublisherHTTPWorker' => 'applications/feed/worker/FeedPublisherHTTPWorker.php',
@@ -4577,6 +4578,7 @@
'DrydockWebrootInterface' => 'DrydockInterface',
'DrydockWinRMCommandInterface' => 'DrydockCommandInterface',
'DrydockWorkingCopyBlueprintImplementation' => 'DrydockBlueprintImplementation',
+ 'DrydockWorkingCopyCacheBlueprintImplementation' => 'DrydockBlueprintImplementation',
'FeedConduitAPIMethod' => 'ConduitAPIMethod',
'FeedPublishConduitAPIMethod' => 'FeedConduitAPIMethod',
'FeedPublisherHTTPWorker' => 'FeedPushWorker',
diff --git a/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php
@@ -35,7 +35,9 @@
DrydockResource $resource,
DrydockLease $lease) {
return
- $lease->getAttribute('platform') === $resource->getAttribute('platform');
+ $lease->getAttribute('platform') ===
+ $resource->getAttribute('platform') ||
+ $lease->getAttribute('platform') === null;
}
protected function shouldAllocateLease(
@@ -87,6 +89,10 @@
$cmd->execx('mkdir %s', $full_path);
$lease->setAttribute('path', $full_path);
+ if ($lease->getAttribute('platform') === null) {
+ // If the lease does not have a platform set, set it now.
+ $lease->setAttribute('platform', $v_platform);
+ }
}
public function getType() {
diff --git a/src/applications/drydock/blueprint/DrydockWorkingCopyCacheBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockWorkingCopyCacheBlueprintImplementation.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/blueprint/DrydockWorkingCopyCacheBlueprintImplementation.php
@@ -0,0 +1,258 @@
+<?php
+
+final class DrydockWorkingCopyCacheBlueprintImplementation
+ extends DrydockBlueprintImplementation {
+
+ public function isEnabled() {
+ return true;
+ }
+
+ public function getBlueprintName() {
+ return pht('Working Copy Cache');
+ }
+
+ public function getDescription() {
+ return pht('Allows Drydock to cache repositories on host resources.');
+ }
+
+ public function canAllocateResourceForLease(DrydockLease $lease) {
+ return true;
+ }
+
+ protected function canAllocateLease(
+ DrydockResource $resource,
+ DrydockLease $lease) {
+
+ $resource_match = $lease->getAttribute('host.resource') ===
+ $resource->getAttribute('host.resource');
+ $url_match = $lease->getAttribute('url') ===
+ $resource->getAttribute('url');
+
+ $can_allocate = $resource_match && $url_match;
+
+ if ($can_allocate) {
+ $this->log(pht(
+ 'This blueprint can allocate a resource for the specified lease.'));
+ } else {
+ $this->log(pht(
+ 'This blueprint can not allocate a resource for the specified lease.'));
+ }
+
+ return $can_allocate;
+ }
+
+ protected function shouldAllocateLease(
+ DrydockAllocationContext $context,
+ DrydockResource $resource,
+ DrydockLease $lease) {
+
+ return true;
+ }
+
+ protected function executeInitializePendingResource(
+ DrydockResource $resource,
+ DrydockLease $lease) {
+
+ $url = $lease->getAttribute('url');
+ $host_resource_id = $lease->getAttribute('host.resource');
+
+ $resource
+ ->setAttribute('url', $url)
+ ->setAttribute('host.resource', $host_resource_id)
+ ->save();
+ }
+
+ protected function executeAllocateResource(
+ DrydockResource $resource,
+ DrydockLease $lease) {
+
+ $url = $lease->getAttribute('url');
+ $host_resource_id = $lease->getAttribute('host.resource');
+
+ $resource
+ ->setName(pht(
+ 'Working Copy Cache (%s on host resource %d)',
+ $url,
+ $host_resource_id))
+ ->setStatus(DrydockResourceStatus::STATUS_PENDING)
+ ->save();
+
+ $host_lease = id(new DrydockLease())
+ ->setResourceType('host')
+ ->setAttributes(
+ array(
+ 'resourceID' => $host_resource_id,
+ ))
+ ->queueForActivation();
+ $this->log(pht(
+ 'Acquiring new host lease %d for working copy cache (on resource %d)...',
+ $host_lease->getID(),
+ $host_resource_id));
+ $host_lease->waitUntilActive();
+ $this->log(pht(
+ 'Lease %d acquired for working copy resource.',
+ $host_lease->getID()));
+
+ $resource
+ ->setAttribute('host.lease', $host_lease->getID())
+ ->save();
+
+ $this->log(pht(
+ 'Cloning repository at "%s" to "%s"...',
+ $url,
+ $host_lease->getAttribute('path')));
+
+ $cmd = $this->getCommandInterfaceForLease($host_lease);
+ $cmd->execx(
+ 'git clone --bare %s .',
+ $url);
+
+ $this->log('Cloned repository cache.');
+
+ $resource
+ ->setStatus(DrydockResourceStatus::STATUS_OPEN)
+ ->save();
+ return $resource;
+ }
+
+ protected function executeAcquireLease(
+ DrydockResource $resource,
+ DrydockLease $lease) {
+
+ $this->log(pht(
+ 'Starting acquisition of lease from resource %d',
+ $resource->getID()));
+
+ while ($resource->getStatus() == DrydockResourceStatus::STATUS_PENDING) {
+ $this->log(pht(
+ 'Resource %d is still pending, waiting until it is in an open status',
+ $resource->getID()));
+
+ // This resource is still being set up by another allocator, wait until
+ // it is set to open.
+ sleep(5);
+ $resource->reload();
+ }
+
+ $host_lease = id(new DrydockLeaseQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withIDs(array($resource->getAttribute('host.lease')))
+ ->executeOne();
+ if ($host_lease === null) {
+ throw new Exception(pht(
+ 'No resource found with ID %d',
+ $resource->getAttribute('host.lease')));
+ }
+
+ // Ensure the host lease and resource are still active and open.
+ if ($host_lease->getStatus() != DrydockLeaseStatus::STATUS_ACTIVE ||
+ $host_lease->getResource()->getStatus() !=
+ DrydockResourceStatus::STATUS_OPEN) {
+
+ // Our host lease has been released or our host resource has been
+ // closed. No further leases against this working copy cache
+ // resource will succeed, so force ourselves into the closed
+ // status and fail this lease.
+ $resource
+ ->setStatus(DrydockResourceStatus::STATUS_DESTROYED)
+ ->save();
+ throw new Exception(pht(
+ 'The host lease or resource for this working copy '.
+ 'cache was released or closed. Lease was in status "%s", '.
+ 'resource was in status "%s". Automatically '.
+ 'marking this working copy resource as destroyed.',
+ DrydockLeaseStatus::getNameForStatus($host_lease->getStatus()),
+ DrydockResourceStatus::getNameForStatus(
+ $host_lease->getResource()->getStatus())));
+ }
+
+ // We must lock the resource while we perform the cache update,
+ // because otherwise we'll end up running multiple read-write
+ // VCS operations in the same directory at the same time.
+ $lock = PhabricatorGlobalLock::newLock(
+ 'drydock-working-copy-cache-update-'.$host_lease->getID());
+ $lock->lock(1000000);
+ try {
+ $cmd = $this->getCommandInterfaceForLease($host_lease);
+
+ $this->log(pht(
+ 'Fetching latest commits for repository at "%s"',
+ $host_lease->getAttribute('path')));
+ $cmd->exec('git fetch origin +refs/heads/*:refs/heads/*');
+ $cmd->exec(
+ 'git fetch origin +refs/tags/phabricator/diff/*:'.
+ 'refs/tags/phabricator/diff/*');
+ $this->log(pht('Fetched latest commits.'));
+
+ $lock->unlock();
+ } catch (Exception $ex) {
+ $lock->unlock();
+ throw $ex;
+ }
+
+ // We don't need to perform any cloning or initialization here, the leases
+ // just count how many users of the working copy cache there are.
+
+ $lease->setAttribute('path', $host_lease->getAttribute('path'));
+ }
+
+ private function getCommandInterfaceForLease(DrydockLease $lease) {
+ if ($lease->getAttribute('platform') === 'windows') {
+ return $lease->getInterface(
+ 'command-'.PhutilCommandString::MODE_WINDOWSCMD);
+ } else {
+ return $lease->getInterface(
+ 'command-'.PhutilCommandString::MODE_BASH);
+ }
+ }
+
+ public function getType() {
+ return 'working-copy-cache';
+ }
+
+ public function getInterface(
+ DrydockResource $resource,
+ DrydockLease $lease,
+ $type) {
+
+ throw new Exception(pht("No interface of type '%s'.", $type));
+ }
+
+ protected function executeReleaseLease(
+ DrydockResource $resource,
+ DrydockLease $lease) {
+
+ // No release logic require for leases.
+ }
+
+ protected function shouldCloseUnleasedResource(
+ DrydockAllocationContext $context,
+ DrydockResource $resource) {
+
+ return false;
+ }
+
+ protected function executeCloseResource(DrydockResource $resource) {
+ $this->log(pht(
+ 'Releasing resource host lease %d',
+ $resource->getAttribute('host.lease')));
+ try {
+ $host_lease = $this->loadLease($resource->getAttribute('host.lease'));
+
+ $host_resource = $host_lease->getResource();
+ $host_blueprint = $host_resource->getBlueprint();
+ $host_blueprint->releaseLease($host_resource, $host_lease);
+
+ $this->log(pht(
+ 'Released resource host lease %d',
+ $resource->getAttribute('host.lease')));
+ } catch (Exception $ex) {
+ $this->log(pht(
+ 'Unable to release resource host lease %d: "%s"',
+ $resource->getAttribute('host.lease'),
+ (string)$ex));
+ }
+ }
+
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 9, 3:17 AM (2 d, 23 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
8796021
Default Alt Text
D13507.id33781.diff (10 KB)
Attached To
Mode
D13507: [drydock/working-copies/v1-caching] Implement working copy cache blueprint
Attached
Detach File
Event Timeline
Log In to Comment