Page MenuHomePhabricator

D19388.id46372.diff
No OneTemporary

D19388.id46372.diff

diff --git a/resources/sql/autopatches/20180418.alamanc.interface.unique.php b/resources/sql/autopatches/20180418.alamanc.interface.unique.php
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180418.alamanc.interface.unique.php
@@ -0,0 +1,73 @@
+<?php
+
+$table = new AlmanacInterface();
+$conn = $table->establishConnection('w');
+
+queryfx(
+ $conn,
+ 'LOCK TABLES %T WRITE',
+ $table->getTableName());
+
+$seen = array();
+foreach (new LiskMigrationIterator($table) as $interface) {
+ $device = $interface->getDevicePHID();
+ $network = $interface->getNetworkPHID();
+ $address = $interface->getAddress();
+ $port = $interface->getPort();
+ $key = "{$device}/{$network}/{$address}/{$port}";
+
+ // If this is the first copy of this row we've seen, mark it as seen and
+ // move on.
+ if (empty($seen[$key])) {
+ $seen[$key] = $interface->getID();
+ continue;
+ }
+
+ // Find the interface that already has this key.
+ $survivor = id(new AlmanacInterfaceQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withIDs(array($seen[$key]))
+ ->executeOne();
+
+ // Find any bindings that reference the interface to be destroyed.
+ $bindings = id(new AlmanacBindingQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withInterfacePHIDs(array($interface->getPHID()))
+ ->execute();
+
+ // Repoint bindings to the survivor.
+ foreach ($bindings as $binding) {
+ // Check if there's already a binding for the survivor.
+ $existing = id(new AlmanacBindingQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withInterfacePHIDs(array($survivor->getPHID()))
+ ->withDevicePHIDs(array($binding->getDevicePHID()))
+ ->withServicePHIDs(array($binding->getServicePHID()))
+ ->execute();
+
+ if (!$existing) {
+ // Reattach this binding to the survivor.
+ $binding->attachInterface($survivor);
+ $binding->setInterfacePHID($survivor->getPHID());
+ $binding->save();
+ } else {
+ // Binding to survivor already exists. Remove this now-redundant binding.
+ id(new PhabricatorDestructionEngine())
+ ->destroyObject($binding);
+ }
+ }
+
+ // Now we can destroy the interface.
+ id(new PhabricatorDestructionEngine())
+ ->destroyObject($interface);
+}
+
+queryfx(
+ $conn,
+ 'ALTER TABLE %T ADD UNIQUE KEY `key_unique` '.
+ '(devicePHID, networkPHID, address, port)',
+ $table->getTableName());
+
+queryfx(
+ $conn,
+ 'UNLOCK TABLES');
diff --git a/src/applications/almanac/storage/AlmanacInterface.php b/src/applications/almanac/storage/AlmanacInterface.php
--- a/src/applications/almanac/storage/AlmanacInterface.php
+++ b/src/applications/almanac/storage/AlmanacInterface.php
@@ -35,6 +35,10 @@
'key_device' => array(
'columns' => array('devicePHID'),
),
+ 'key_unique' => array(
+ 'columns' => array('devicePHID', 'networkPHID', 'address', 'port'),
+ 'unique' => true,
+ ),
),
) + parent::getConfiguration();
}

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 13, 6:49 AM (5 d, 2 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6758177
Default Alt Text
D19388.id46372.diff (2 KB)

Event Timeline