Page MenuHomePhabricator

D19388.id46379.diff
No OneTemporary

D19388.id46379.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,85 @@
+<?php
+
+$interface_table = new AlmanacInterface();
+$binding_table = new AlmanacBinding();
+$interface_conn = $interface_table->establishConnection('w');
+
+queryfx(
+ $interface_conn,
+ 'LOCK TABLES %T WRITE, %T WRITE',
+ $interface_table->getTableName(),
+ $binding_table->getTableName());
+
+$seen = array();
+foreach (new LiskMigrationIterator($interface_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;
+ }
+
+ $survivor = queryfx_one(
+ $interface_conn,
+ 'SELECT * FROM %T WHERE id = %d',
+ $interface_table->getTableName(),
+ $interface->getID());
+
+ $bindings = queryfx_all(
+ $interface_conn,
+ 'SELECT * FROM %T WHERE interfacePHID = %s',
+ $binding_table->getTableName(),
+ $interface->getPHID());
+
+ // Repoint bindings to the survivor.
+ foreach ($bindings as $binding) {
+ // Check if there's already a binding to the survivor.
+ $existing = queryfx_one(
+ $interface_conn,
+ 'SELECT * FROM %T WHERE interfacePHID = %s and devicePHID = %s and '.
+ 'servicePHID = %s',
+ $binding_table->getTableName(),
+ $survivor['phid'],
+ $binding['devicePHID'],
+ $binding['servicePHID']);
+
+ if (!$existing) {
+ // Reattach this binding to the survivor.
+ queryfx(
+ $interface_conn,
+ 'UPDATE %T SET interfacePHID = %s WHERE id = %d',
+ $binding_table->getTableName(),
+ $survivor['phid'],
+ $binding['id']);
+ } else {
+ // Binding to survivor already exists. Remove this now-redundant binding.
+ queryfx(
+ $interface_conn,
+ 'DELETE FROM %T WHERE id = %d',
+ $binding_table->getTableName(),
+ $binding['id']);
+ }
+ }
+
+ queryfx(
+ $interface_conn,
+ 'DELETE FROM %T WHERE id = %d',
+ $interface_table->getTableName(),
+ $interface->getID());
+}
+
+queryfx(
+ $interface_conn,
+ 'ALTER TABLE %T ADD UNIQUE KEY `key_unique` '.
+ '(devicePHID, networkPHID, address, port)',
+ $interface_table->getTableName());
+
+queryfx(
+ $interface_conn,
+ 'UNLOCK TABLES');
diff --git a/src/applications/almanac/editor/AlmanacInterfaceEditor.php b/src/applications/almanac/editor/AlmanacInterfaceEditor.php
--- a/src/applications/almanac/editor/AlmanacInterfaceEditor.php
+++ b/src/applications/almanac/editor/AlmanacInterfaceEditor.php
@@ -15,4 +15,22 @@
return pht('%s created %s.', $author, $object);
}
+ protected function didCatchDuplicateKeyException(
+ PhabricatorLiskDAO $object,
+ array $xactions,
+ Exception $ex) {
+
+ $errors = array();
+
+ $errors[] = new PhabricatorApplicationTransactionValidationError(
+ null,
+ pht('Invalid'),
+ pht(
+ 'Interfaces must have a unique combination of network, device, '.
+ 'address, and port.'),
+ null);
+
+ throw new PhabricatorApplicationTransactionValidationException($errors);
+ }
+
}
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
Sun, Oct 27, 5:04 PM (3 w, 15 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6752434
Default Alt Text
D19388.id46379.diff (3 KB)

Event Timeline