Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F96536608
DrydockSlotLock.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Fri, Dec 27, 18:47
Size
4 KB
Mime Type
text/x-php
Expires
Sun, Dec 29, 18:47 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
23200813
Attached To
rPH Phabricator
DrydockSlotLock.php
View Options
<?php
/**
* Simple optimistic locks for Drydock resources and leases.
*
* Most blueprints only need very simple locks: for example, a host blueprint
* might not want to create multiple resources representing the same physical
* machine. These optimistic "slot locks" provide a flexible way to do this
* sort of simple locking.
*
* @task info Getting Lock Information
* @task lock Acquiring and Releasing Locks
*/
final
class
DrydockSlotLock
extends
DrydockDAO
{
protected
$ownerPHID
;
protected
$lockIndex
;
protected
$lockKey
;
protected
function
getConfiguration
()
{
return
array
(
self
::
CONFIG_TIMESTAMPS
=>
false
,
self
::
CONFIG_COLUMN_SCHEMA
=>
array
(
'lockIndex'
=>
'bytes12'
,
'lockKey'
=>
'text'
,
),
self
::
CONFIG_KEY_SCHEMA
=>
array
(
'key_lock'
=>
array
(
'columns'
=>
array
(
'lockIndex'
),
'unique'
=>
true
,
),
'key_owner'
=>
array
(
'columns'
=>
array
(
'ownerPHID'
),
),
),
)
+
parent
::
getConfiguration
();
}
/* -( Getting Lock Information )------------------------------------------- */
/**
* Load all locks held by a particular owner.
*
* @param phid Owner PHID.
* @return list<DrydockSlotLock> All held locks.
* @task info
*/
public
static
function
loadLocks
(
$owner_phid
)
{
return
id
(
new
DrydockSlotLock
())->
loadAllWhere
(
'ownerPHID = %s'
,
$owner_phid
);
}
/**
* Test if a lock is currently free.
*
* @param string Lock key to test.
* @return bool True if the lock is currently free.
* @task info
*/
public
static
function
isLockFree
(
$lock
)
{
return
self
::
areLocksFree
(
array
(
$lock
));
}
/**
* Test if a list of locks are all currently free.
*
* @param list<string> List of lock keys to test.
* @return bool True if all locks are currently free.
* @task info
*/
public
static
function
areLocksFree
(
array
$locks
)
{
$lock_map
=
self
::
loadHeldLocks
(
$locks
);
return
!
$lock_map
;
}
/**
* Load named locks.
*
* @param list<string> List of lock keys to load.
* @return list<DrydockSlotLock> List of held locks.
* @task info
*/
public
static
function
loadHeldLocks
(
array
$locks
)
{
if
(!
$locks
)
{
return
array
();
}
$table
=
new
DrydockSlotLock
();
$conn_r
=
$table
->
establishConnection
(
'r'
);
$indexes
=
array
();
foreach
(
$locks
as
$lock
)
{
$indexes
[]
=
PhabricatorHash
::
digestForIndex
(
$lock
);
}
return
id
(
new
DrydockSlotLock
())->
loadAllWhere
(
'lockIndex IN (%Ls)'
,
$indexes
);
}
/* -( Acquiring and Releasing Locks )-------------------------------------- */
/**
* Acquire a set of slot locks.
*
* This method either acquires all the locks or throws an exception (usually
* because one or more locks are held).
*
* @param phid Lock owner PHID.
* @param list<string> List of locks to acquire.
* @return void
* @task locks
*/
public
static
function
acquireLocks
(
$owner_phid
,
array
$locks
)
{
if
(!
$locks
)
{
return
;
}
$table
=
new
DrydockSlotLock
();
$conn_w
=
$table
->
establishConnection
(
'w'
);
$sql
=
array
();
foreach
(
$locks
as
$lock
)
{
$sql
[]
=
qsprintf
(
$conn_w
,
'(%s, %s, %s)'
,
$owner_phid
,
PhabricatorHash
::
digestForIndex
(
$lock
),
$lock
);
}
try
{
queryfx
(
$conn_w
,
'INSERT INTO %T (ownerPHID, lockIndex, lockKey) VALUES %LQ'
,
$table
->
getTableName
(),
$sql
);
}
catch
(
AphrontDuplicateKeyQueryException
$ex
)
{
// Try to improve the readability of the exception. We might miss on
// this query if the lock has already been released, but most of the
// time we should be able to figure out which locks are already held.
$held
=
self
::
loadHeldLocks
(
$locks
);
$held
=
mpull
(
$held
,
'getOwnerPHID'
,
'getLockKey'
);
throw
new
DrydockSlotLockException
(
$held
);
}
}
/**
* Release all locks held by an owner.
*
* @param phid Lock owner PHID.
* @return void
* @task locks
*/
public
static
function
releaseLocks
(
$owner_phid
)
{
$table
=
new
DrydockSlotLock
();
$conn_w
=
$table
->
establishConnection
(
'w'
);
queryfx
(
$conn_w
,
'DELETE FROM %T WHERE ownerPHID = %s'
,
$table
->
getTableName
(),
$owner_phid
);
}
}
Event Timeline
Log In to Comment