Генерация гео конфига для nginx

Появилась у меня задача быстро сгенерировать конфигурационный файл для гео модуля nginx. Ниже вариант решения.

Немного о сетях.

Internet Protocol или IP (англ. internet protocol — межсетевой протокол) — маршрутизируемый сетевой протокол, протокол сетевого уровня семейства («стека») TCP/IP.  В современной сети Интернет используется IP четвёртой версии, также известный как IPv4. В протоколе IP этой версии каждому узлу сети ставится в соответствие IP-адрес длиной 4 октета (4 байта). При этом компьютеры в подсетях объединяются общими начальными битами адреса. Количество этих бит, общее для данной подсети, называется маской подсети (ранее использовалось деление пространства адресов по классам — A, B, C; класс сети определялся диапазоном значений старшего октета и определял число адресуемых узлов в данной сети, сейчас используется бесклассовая адресация). На вход мы получаем массив из двух элементов: сеть (например 192.168.1.0/31) и идентификатор. © Wikipedia

Требования на входе:

  • Данными могут быть только подсети в правильном cidr формате.
  • Отсортированы в порядке возрастания (при использовании базы данных это не сложно).

Требования на выходе: отсортированный список непересекающихся диапазонов в файле минимального размера. Формат: начальный адрес подсети – конечный адрес идентификатор (192.168.1.1-192.168.1.126 336).

nginx ищет соответствие определенного ip адреса и диапазонов из файла. Возвращает идентификатор.

Для начала загружаем массив сетей из базы:

my $in = $dbh->selectall_arrayref('select net, geo from locations order by net'));

Так же не забываем в начале объявить переменные:

my $last;

И открыть файл для записи.

open TARGET_BIG, ">", $file_name;

Отдаем все функции перебора сетей:

sub main_stack {
  my $IN = shift;
  my $S = [];
  my $item;
  my $LB = 0; # Крайняя левая граница
  for my $item ( @$IN ) {
    unless ( $item->[2] ) {
      my ( $ip, $mask ) = split /\//, $item->[0];
      my $st = str2dw( $ip ) & ( ( 2**$mask - 1 ) << ( 32 - $mask ) );
      $item->[2] = [ $st, $st + 2**( 32-$mask ) - 1 ];
    }
    while ( @$S ) {
      $S->[0][2][0] = $LB;
      my $c = split_ip( $S->[0], $item );
      # нет правой части.
      unless ( $c->[2] ) {
        shift @$S;
      }
      # Эта часть для сохранения в файл
      if ( $c->[0] ) {
        save_range( $c->[0] );
        $LB = $c->[0][2][1] + 1;
      }
      if ( $c->[1] ) {
        unshift @$S, $c->[1];
        last;
      }
    }
    unless ( @$S > 0 ) {
      unshift @$S, $item;
      $LB = $item->[2][0];
    }
  }
  # Ограничиваем слева оставшиеся данные из стэка
  # Дописываем содержимое стэка
  while (my $item = shift @$S) {
    save_range( [ undef, $item->[1], [ $LB, $item->[2][1] ] ] );
    $LB = $item->[2][1] + 1;
  }
  # Досохраняем последний элемент
  save_range( [ undef,0, [0, 0] ] );
}

Эта функция сохраняет диапазон

sub save_range {
  # Если пришел соседний диапазон с тем же id, то просто суммируем
  if ( $last ) {
    if ( $last->[1] eq $_[0]->[1] && $last->[2][1] + 1 == $_[0]->[2][0] ) {
      $last->[2][1] = $_[0]->[2][1];
    }
    print TARGET_BIG dw2str( $last->[2][0] ) . '-' . dw2str( $last->[2][1] ),
      "\t", $last->[1], ";\n" if $last->[1];
  }
  $last = [ undef, $_[0]->[1], [ $_[0]->[2][0], $_[0]->[2][1] ] ];
}

Для разбиения переданного диапазона используем следующий алгоритм

sub split_ip {
  my $c = [];
  if ( $_[1]->[2][0] > $_[0]->[2][1] ) {
    $c->[0] = [ undef, $_[0]->[1], $_[0]->[2] ];
  } else {
    $c->[0] = [ undef, $_[0]->[1], [ $_[0]->[2][0], $_[1]->[2][0] - 1 ] ]
      if $_[1]->[2][0] > $_[0]->[2][0];
    $c->[1] = [ undef, $_[1]->[1], $_[1]->[2] ];
    $c->[2] = [ undef, $_[0]->[1], [ $_[1]->[2][1] + 1, $_[0]->[2][1] ] ]
      if $_[1]->[2][1] < $_[0]->[2][1];
  }
  return $c;
}

Вспомогательные функции конвертирования ip

sub str2dw {
  return unpack 'N',pack( 'C4',split /\./, shift );
}

sub dw2str {
  return join '.', unpack 'C4', pack 'N',shift;
}

На вход подаю 10 000 000 диапазонов. Скрипт отрабатывает около 5 минут. Из них полтары минуты данные загружаются из базы. Количество занимаемой памяти зависит от количества переданных сетей, сам алгоритм практически не использует память.

Работа в Макдоналдсе.

Работа в Макдоналдсе для многих – это ацкий труд за маленькие деньги.

Когда я был студентом и еще не планировал работать, в нашем городе начали строить Макдоналдс. На фоне остальных предприятий это заведение внушало доверие и мы с другом взяли анкетки. Думали устроиться на лето подработать.

До обучения нас предупредили, что работа не легкая, что отдохнуть будет некогда. Уже на второй или третий день обучения половина новичков не вышла. А я проработал там полтора года. А друг и того больше. Он дослужился до ассистента.

Что же особенного в Макдоналдсе?

Режим и правильно построенный бизнес. Для многих предприятий Макдоналдс можно ставить в пример, как идеально работающую структуру. Этот бизнес отточен годами и максимально оптимизирован. Там все реально работают и реально приносят пользу компании.

Для работника это в первую очередь возможность улучшить собственную дисциплину и научиться общаться. Работая в Макдоналдсе я ужасно уставал. Все время приходилось стоять на ногах и укладываться в нормативы по времени заправки сэндвичей (я работал на кухне).

Цепочка, которую проходит продукт достаточно длинная. Каждый в ней делает свое дело. Это практически идеальный конвейер. Для обычного работника не надо быть сильно умным или быстрым. Обычных способностей достаточно. Не берут туда лишь совсем неадекватных.

Понятно, мало кто работает там долго. Эта работа для студентов и совсем молодых и энергичных. Она совершенно не подойдет тем кто привык лежать на диване, ждать чуда и общаться через интернет. Но если ты такой, то Макдоналдс может сделать из тебя более адекватное существо.

Многие боятся, что их увидят знакомые. Ну в Москве можно выбрать Макдоналдс в другом районе. А если ты так зависим от мнения окружающих и такой понтовый, то зачем тебе в Макдоналдс? Эта идея вообще не для тебя. Иди сразу директором в майкрософт или открывай свой бизнес.

А для обычного студента это нормальная подработка. Тем более, график гибкий. Да и многие богатые люди начинали свою карьеру в Макдоналдс.

Кстати там еще и кормят и еда там хорошая. Критикуют только конкуренты и слабаки, которые не могут остановиться или спортом заняться, потом жиреют как свиньи и во всем винят Макдоналдс.

Кто в семье главный?

Давно уже задался вопросом: «Кто в семье главный?». Ответ традиционно: «мужик». Но вот недавно появился новый вопрос: «А какие обязанности у главного?».

За несколько лет самостоятельной жизни я привык к работе по дому, к зарабатыванию денег и даже кота завел. Но с котом меня надолго не хватило, поэтому живет (я надеюсь на это) пока у сестры. Так же я встречал различных людей с различными интересами и с разными взглядами на жизнь, семью и на превосходство в семье. Скажете: «Вот удивил… Все разные.»

А вот и не во всем. В итоге можно разделить семейные пары на несколько категорий:

  1. Глава семьи мужик.
  2. Глава семьи жена.
  3. Оба принимают решения.
  4. Оба пассивные.

Представители первой группы – наиболее успешные. Причем в них глава семьи в прямом смысле – глава. Но их я встречал меньше всего.

Во вторую группу я отношу и тех кто сознательно определился, что жена главная и тех кто думает, что муж главный, а заправляет жена. «Я сказал мы едем на футбол, значит на футбол! Дорогой а может к маме. Я сказал к маме, значит к маме!». В этой группе все достаточно стабильно. Нет особых терок, все живут на стабильную зарплату и нет ничего интересного.

Третья группа нежизнеспособна. Две головы – это уже амфисбена какая-то. Как показали мои наблюдения, управлять вообще может только один человек, иначе получается каша, где каждый тянет дело на себя и согласия нет. Такие семьи долго не просуществовали.

Четвертая группа для меня загадка. Я знаю что такие есть, но лично не знаком.

В целом, если один – дурак, то ему лучше не быть у власти. Но именно такие люди и думают, что они главные. Хотя по сути решения принять нормального не могут. Большинство мужиков от природы более решительны. И больше рискуют. Женщины же менее склонны к риску и более эмоциональны. В идеале мужик должен принимать решение, а женщина быть сдерживающим фактором. Так как важное решение в порыве эмоций как и при избытке адреналина невозможно принять.

Но мир меняется и женщины рвутся к власти. И рвутся не потому что хотят этой власти (ИМХО), а потому что мужики лежат на диванах и не хотят ничего делать. Только твердят о своей важности. Выпить пива, бухнуть водки, посмотреть футбол – все это бесспорно важно, иначе в чем смысл жизни? А откуда это? Воспитали так. Посмотрите на современных женщин… Не тех кто у власти, а на обычных. Я часто вижу как женщина матом объясняет пятилетнему ребенку, что он не прав и при этом пиво глушит и сигарету изо рта не выпускает. Как вы думаете, сын такой женщины будет реально что-то из себя представлять и уважительно относится к женщинам?

Как правило, почти каждый из нас смотря сказку о плохом и хорошем, где хорошее побеждает, ассоциирует себя с этим хорошим. И здесь, я думаю, все вспомнили случаи из метро, на улице, у подъездов, но никто не увидел в перечисленных выше персонажах себя.

Так что же должен делать глава семьи? Принимать решения. Управлять. Брать ответственность. Совершенствовать семью. Не тот глава семьи, кто применяет физическую силу или требует жрать, секса, шубку, отдых, футбол, пива, водки или кофе в постель. А тот кто способен сохранить в семье хорошие отношения, воспитать нормальных детей и не злиться на жизнь и на другиз за зря прожитую по своей же вине жизнь.

Я создатель мира…

Отнюдь… Я не создатель мира и не претендую на эту должность. Да и с религией я не связан. А вот создавать различные вещи мне всегда было интересно. Уже в детстве больше склонялся к созданию, чем к потреблению. Когда мне покупали игрушки, я предпочитал их разобрать и попробовать собрать (не всегда удачно), в то время, когда мои сверсники в них играли. Я всегда любил конструкторы, головоломки и папин гараж. Там было много инструментов, различные материалы (листы ДВП, стали, деревянные заготовки), станки. Я все свободное время старался находиться в гараже. Потом я вырос и пошел в школу. В школьные времена я клеил замки и делал игрушечную мебель. Когда мне показали впервые кроссворд, я попробовал его разгадать, а потом решил составлять кроссворды.

В старших классах все друзья помешались на компьютерных играх и на компьютерах. И я тоже. Только я не очень любил играть, мне больше нравилось программирование. В дальнейшем была совершена безуспешная попытка написать свою компьютерную игру. И в конечном итоге я стал разработчиком. Каждый новый сайт, в котором я принимал участие оценивается все дороже и работает стабильнее предшественников. Я не гуру в программировании и вообще в разработке сайтов, да и врядли я им когда либо стану. Но свои маленькие миры я успешно создаю.

В этом блоге буду записывать основные события, произошедшие в моей жизни, а так же добавлять всякую всячину, которая мне покажется интересной.

PS Если кто-то предположит, что я нарушаю чьи-то авторские права, пишите. Договоримся.