17 марта 2010, 16:34 (5367 дней назад, №8787)Непростое добавление IP диапазона
Я уже упоминал в
предыдущем посте о задаче написать редактор IP диапазонов сотовых операторов (кстати, кому интересно - открытая база есть
вот здесь ).
Сама по себе задача тривиальная - в БД есть две таблицы, в одной из которых перечислены (помимо различной вспомогательной информации) начальный и конечный IP диапазона и id сотового оператора, к которому относится этот диапазон. Во второй перечислены операторы с их id.
Однако, есть очень важный ньюанс. Допустим, поступила информация о новом диапазоне - стало известно, что он относится, скажем, к МТС. Конечно можно просто добавить еще одну строчку в базу, но это будет некорректно, т.к. вполне может оказаться, что там уже есть диапазон, с которым новый совпадёт или, того хуже, частично пересечётся. Даже более того - этот старый диапазон мог в прошлом быть отнесен к другому оператору (скажем, по ошибке). Также есть опасность случайно ошибиться цифрой при вводе IP и затереть таким образом половину базы. Все эти нередкие ситуации надо анализировать и обрабатывать.
В итоге я сделал примерно так:
Вызываем на сервере сервис RangeService.addRangePreview, который получает через метод checkRangeIntersect() список всех IP диапазонов, с которыми пересекается добавляемый:
SELECT ... FROM ... WHERE ... AND
(
:ip_start BETWEEN start AND finish
OR
:ip_finish BETWEEN start AND finish
OR
start BETWEEN :ip_start AND :ip_finish
OR
finish BETWEEN :ip_start AND :ip_finish
)
AND NOT
( start = :ip_start AND finish = :ip_finish )
этот, полученный в виде ассоциативного массива, список диапазонов скармливается методу getRangeFutureList() , который смотрит, каким именно образом на каждый из них повлияет добавляемый диапазон.
Вариантов не так много:
- будет создан, поскольку задан как новый и с другими не пересекается
- совпадает с новым, будет обновлён
- полностью поглощается новым, поэтому будет удален
- будет создан (слева), в связи с попаданием нового диапазона внутрь существующего
- будет создан (справа), в связи с попаданием нового диапазона внутрь существующего
- будет удален, в связи с попаданием внутрь него нового диапазона (и созданием вместо него двух новых)
- будет урезан слева, поскольку имеет общую часть с новым диапазоном
- будет урезан справа, поскольку имеет общую часть с новым диапазоном
- будет создан, поскольку задан как новый и с другими не пересекается
- будет создан, поскольку задан как новый
Таким образом, метод getRangeFutureList() возвращает массив операций, которые надо совершить и параметры удаляемых/создаваемых/изменяемых диапазонов.
Массивы пересечений и планируемых изменений возвращаются во Flex клиент, где демонстрируются наглядно в виде диаграммы и таблицы - см. рис. в начале поста. Кстати, полоски сделаны не через graphics.drawRect(), а через new Button(), чтобы можно было легко навесить на каждую полоску toolTip и сделать её кликабельной (для выдачи дополнительной информации по клику).
Далее, если пользователь согласен и нажимает "Accept", вызывается RangeService.addRangeModify и по массиву с изменениями последовательно выполняются необходимые INSERT / DELETE / UPDATE.