kleptos ([info]_kleptos_) wrote,
@ 2007-03-13 06:43:00
Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Entry tags:apache, perl, soft, threads, tip

apache2 и треднутый пёрл
Решил я значитсо собрать пёрл с поддержкой тредов.
И чтоб mod_perl при этом работал.
А дистриб - gentoo.
Апач - Apache/2.0.58.
Пёрл - v5.8.8
mod_perl-2.0.2

Добавляю threads к use флагам апача, ithreads к пёрлу, пересобираю апач, пёрл и mod_perl.

На первый взгляд ничего не предвещает беды:

kleptos@localhost ~ $ /usr/sbin/apache2 -V 
Server version: Apache/2.0.58
Server built:   Mar 13 2007 01:15:04
Server’s Module Magic Number: 20020903:12
Server loaded:  APR 0.9.12, APR-UTIL 0.9.12
Compiled using: APR 0.9.12, APR-UTIL 0.9.12
Architecture:   32-bit
Server compiled with....
 -D APACHE_MPM_DIR=“server/mpm/worker”
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D HTTPD_ROOT=“/usr”
 -D SUEXEC_BIN=“/usr/sbin/suexec2”
 -D DEFAULT_SCOREBOARD=“logs/apache_runtime_status”
 -D DEFAULT_ERRORLOG=“logs/error_log”
 -D AP_TYPES_CONFIG_FILE=“/etc/apache2/mime.types”
 -D SERVER_CONFIG_FILE=“/etc/apache2/httpd.conf”
kleptos@localhost ~ $ perl -V | grep ithreads
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define

Но, при старте апача такая картина
localhost downloads # /etc/init.d/apache2 start
 * Apache2 has detected a syntax error in your configuration files:
Syntax error on line 3 of /etc/apache2/modules.d/75_mod_perl.conf:
Cannot load /usr/lib/apache2/modules/mod_perl.so into server: /usr/lib/apache2/modules/mod_perl.so: undefined symbol: Perl_Ipatchlevel_ptr


Уже было собрался писать в [info]ru_linux, но решил предварительно поиграться с ldd.
kleptos@localhost ~ $ ldd /usr/lib/apache2/modules/mod_perl.so 
	linux-gate.so.1 =>  (0xb7f2c000)
	libperl.so.1 => /usr/lib/libperl.so.1 (0xb7da0000)
	libpthread.so.0 => /lib/libpthread.so.0 (0xb7d89000)
	libnsl.so.1 => /lib/libnsl.so.1 (0xb7d70000)
	libdl.so.2 => /lib/libdl.so.2 (0xb7d6c000)
	libm.so.6 => /lib/libm.so.6 (0xb7d44000)
	libcrypt.so.1 => /lib/libcrypt.so.1 (0xb7d15000)
	libutil.so.1 => /lib/libutil.so.1 (0xb7d11000)
	libc.so.6 => /lib/libc.so.6 (0xb7bc7000)
	/lib/ld-linux.so.2 (0x80000000)

Тут я вспомнил, что libperl это вообще-то отдельный компонент и неплохо-бы ему тоже добавить флагов и пересобать.
Добавляю, пересобираю, старную апач - поднимается.
кладу в ~/public_html тестовый скрипт - отдается plaintext, иду править конфиг:
kleptos@localhost ~ $ vim
vim: symbol lookup error: vim: undefined symbol: PL_markstack_ptr

теперь осталось убить всех людей пересобрать всё, что слинковано с libperl и будет мне счастье.


(Post a new comment)


[info]thenexus6
2007-03-13 02:57 am UTC (link)
...но мы любим source-based дистрибутивы не только за это ;)

(Reply to this)(Thread)


[info]_kleptos_
2007-03-13 03:08 am UTC (link)
не думаю, что с бинарниками возни было-бы меньше.
по той простой причине, что для любой софтины embed'ающей пёрл пришлось-бы искать пакет собраный под threaded версию.

(Reply to this)(Parent)(Thread)


[info]thenexus6
2007-03-13 04:50 am UTC (link)
Ну, в debian никакой возни нет, например. Что есть в дистрибутиве - то уж работает и главное, искать ничего не нужно :)

Основная разница в том, что в варианте с бинарниками после наступания на грабли исправляет их один человек и сразу для всех, а в source-based очень часто и наступают все, и занимаются исправлением также все, каждый сам для себя.

(Reply to this)(Parent)(Thread)


[info]_kleptos_
2007-03-13 05:16 am UTC (link)
Здесь оно ебилд-based, поэтому тоже "один для всех".
Другое дело, что мне не извесны способы, которыми emerge может отловить ситуацию вроде вышеописанной необходимости много чего пересобрать.

И именно из-за подобных косяков и бардака я подумываю временами о переезде на bsd.
Хотя ещё остался paludis, замена емержу. Но пока ниасилил.

(Reply to this)(Parent)(Thread)


[info]comnimh
2007-03-13 12:33 pm UTC (link)
Ключ --newuse ?

(Reply to this)(Parent)(Thread)


[info]_kleptos_
2007-03-13 01:10 pm UTC (link)
нет, как был у вима юзфлаг perl, так и остался, а то, что бинарная совместимость потеряна emerge не знает.
в комплекте с пёрлом идёт perl-cleaner - решающий такие прболеммы в лоб, переставляющий все модули пёрла после обновления, переставляющйи все пакеты с активным юзфлагом perl, итд.
примерно то-же есть для python и ruby.

(Reply to this)(Parent)


[info]about_zero
2007-03-13 12:47 pm UTC (link)
А если не секрет, то чем тебя привлекает BSD? Насколько я помню, такого рода зависимости (сборка различных частей с различными флагами) там тоже не разруливаются.

(Reply to this)(Parent)(Thread)


[info]_kleptos_
2007-03-13 01:16 pm UTC (link)
Это раз
Два - в бздях по отзывам знакомых бздунов бардака меньше.
В третьих я хочу поиграться с гибридным ядром драгонфлая, именно он являеться локомотивом моего интереса к бздям.


Я вот что хотел спросить, опять про sql.

Хочу фишечку сделать, есть некоторое множество сущностей. Какие-то сущности могут со временем исчезать, новые добавляться. Сущности могут менять свойсва.
Хочеться всё это положить с версионированием в rdbm что-бы потом можно было делать анализ изменений и принимать на основе этого элементарные аналитические решения, чаще всего стучать мне.
Я упорно гуглил, но ничего путного не нашёл. Наверное слов правильных не знаю. В какую сторону копать?

(Reply to this)(Parent)(Thread)


[info]about_zero
2007-03-13 01:47 pm UTC (link)
А набор свойств для сущности постоянен? В принципе, для гибкого описания сущностей, которые к тому же могут менять набор свойств для конкретной сущности, пытаются применять EAV модель. Entity-Attribute-Value. Она же модель имени Тенцера :) Характеризуется тормознутостью даже на средних объемах данных. В принципе, к ней же можно прицепить и версионность. Дьявол как всегда кроется в деталях :)
Вот статья на эту тему, а вот бурное обсуждение достоинств и недостатков. А вот про версионирование записей. А в общем - если будет более четкая постановка задачи, можно будет обсудить, как это красивее всего реализовать :)

(Reply to this)(Parent)(Thread)


[info]_kleptos_
2007-03-13 02:08 pm UTC (link)
Набор свойств постоянный практически, есть ещё один тип сущностей - контейнеров со своим специфическим набором свойсв, но это как я понимаю обычный инер джойн.

Собсно никаого rocket science, но я сегодня откровенно пасую.

Насколько тормознута eav?

(Reply to this)(Parent)(Thread)


[info]about_zero
2007-03-13 02:25 pm UTC (link)
Точной цифры не назову, т.к. зависит от конкретной реализации и от запросов. Грубая оценка - на порядок. Причем по моим прикидкам, тормоза прямо пропорциональны размеру базы.
Ну тогда не вижу проблем. Обычные таблички с версионированием записей. Судя по всему будет достаточно банальной таблицы аудита. В примитивной реализации для каждой таблицы с сущностью создается точно такая же + поля кто, когда.
create table tEntity(id int primary key not null, attr1 varchar(100), ...)

create table hEntity(
  when datetime default get_date(), 
  who varchar(30) defualt user_name(),
  action tinyint, -- 0 - update, 1 - delete
  id int not null,
  attr1 varchar(100),
  ...
  primary key (when, id) -- возможны варианты...
)

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

Насчет организации таблиц для сущностей. тут можно пойти по нескольким путям...
- На каждую сущность создается отдельная таблица, если в контейнере нужно хранить сущности разных типов, то как вариант заводится еще одна таблица с одним полем id autoincrement, и все сущности и контейнеры своим PK ссылаются на нее...
- Для всех сущностей выносим общую составляющую в одну таблицу, а для специфичных атрибутов делаем таблицы-расширения.

(Reply to this)(Parent)(Thread)


[info]_kleptos_
2007-03-13 04:42 pm UTC (link)
в моём случае версионирование это не столько необходимость логов, сколько возможность посмотреть "а как оно было вчера", "а третьего дню", "а что изменилось".
ладно, разберусь.

(Reply to this)(Parent)


[info]_kleptos_
2007-03-13 06:28 pm UTC (link)
тэкс, попробую спросить.

CREATE foo (item_id INTEGER, bar INTEGER, baz INTEGER, rev INTEGER, PRIMARY KEY(item_id, rev));

item_id свыше данный уникальный индефикатор сущности, bar и baz - всякие параметры, rev - номер ревизии, при каждом обновлении данных инрементиться.

тоесть например.
item_idbarbazrev
133111
222221
388571
133112
228222
228223
444443


хочу получить получить ответ на вопрос, "что изменилось между ревизиями".
что пропало, что добавилось, что поменялось.

и ещё.
так как наличие таких элементарных вопросов в обещм-то симптоматично, что стоит почитать для излечения?

(Reply to this)(Parent)(Thread)

как-то вот так...
[info]about_zero
2007-03-13 07:26 pm UTC (link)
Так, навскидку получим. @current_rev - номер текущей ревизии
- Новые данные (которых не было в старой ревизии)
select f.* from foo f 
where not exists(
  select 1 from foo f2 
  where f2.item_id = f.item_id and f2.rev < @current_rev)

- Удаленные данные (не существуют в текущей ревизии)
select f.* from foo f 
where not exists(
  select 1 from foo f2 
  where f2.item_id = f.item_id and f2.rev = @current_rev)

- Измененные даные (по отношению к предыдущей ревизии)
тут немного сложнее. Можно просто вывести строчку, если хоть что-то поменялось, или же если мы знаем, что проверяем - bar or baz. А вот как сделать запрос с переменным числом колонок - так слету и не придумаю...

Но обычно хранить исторические данные рядом с актуальными нехорошая идея. Хотя зависит от задач, возможно в твоем случае это не так.

А работа с таблицей как производится? берем последнюю ревизию, +1, и вставляем актуальные данные, сколько наберем?

Сейчас попробую представить, как можно элегантнее выйти из ситуации, если это возможно... А то уж очень неэкономно к месту на диске твое решение относится :) Хотя опять-таки, тут все зависит от условий задачи, какие требования накладываются к скорости вставки/скорости выборки, обычно зависимость между ними обратно пропорциональная.

Насчет почитать - сложный вопрос, просто умные книжки именно про SQL как язык запросов прошли мимо меня... Хотя списки я видел, надо будет покопаться в закромах, побеседовать с людьми.

(Reply to this)(Parent)(Thread)

Re: как-то вот так...
[info]_kleptos_
2007-03-13 07:47 pm UTC (link)
Не обязательно про sql как язык запросов.
Я вот эту задачу пытался челез инер джойны решить, наверное я что-то не понимаю и пора чего-то в консерватории поменять.

Обьёмы данных мизерные. Задача именно отлавливать изменение данных от ревизии к ревизии. И временами делать overview изменений за несколько ревизий.

А какой более экономичный/элегантный вариант возможен?

Насчёт вопроса с работой не понял, но попробую ответить.
Прик каждом обновлении запихиваеться весь набор данных, с инкрементнутым revision_id.

Я не стал заморачиваться с избытычными расходами на неизменившиеся от ревизии к ревизии сущности из-за общего небольшого обьёма данных и что-бы не усложнять лишний раз.
Хотя если есть решение одновременно упрощаюшее и убирающее избыточность - буду только рад.

Примерно так.

Тоесть таск - хранить историю изменения сущностей, привязанную к временной сетке. И смотреть что нового при очередной актуализации случилось, временами посматривая на несколько периодов обновления назад.

(Reply to this)(Parent)(Thread)

Re: как-то вот так...
[info]about_zero
2007-03-14 06:13 am UTC (link)
Ясно. Ну в этом случае твой вариант вполне жизнеспособен. Единственная сложность - с измененнными атрибутами сущности. А так все выглядит ок.
Сложность не в отлове таких записей, а в их красиовм показе, типа
item_id, 'baz', 'old value', 'new value'
причем такая строчка должна быть только в том случае, если значение действительно поменялось. Как сделать такое одним запросом, я не знаю. Такое вполне реализуемо, но решение зависит от конкретного сервера. Как я понимаю MySQL?
Если же устроит просто вывод записей, у которых с ревизии на ревизию хоть что-то поменялось, то это реализуется просто...
Насчет inner join - показывай свой вариант, будем разбираться, что и где неправильно.

(Reply to this)(Parent)(Thread)

Re: как-то вот так...
[info]_kleptos_
2007-03-18 11:43 pm UTC (link)
В общем погоняв тестовые даннные, обнаружил, что был неправ.
чЧсть данных (~20%) вообще не измениться никогда, ну разве что будут удалены при очередном апдейте. Другие могут оставаться неизменными достоточно долго, а потом будут удалены и вместо них добавлены новые - либо константные, либо постоянно изменяющиеся.

В общем избыточность по первичным прикидкам - 50%-70%, многовато.

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

(Reply to this)(Parent)(Thread)

Re: как-то вот так...
[info]about_zero
2007-03-19 04:26 pm UTC (link)
Ну я бы наверное тогда сделал как. Есть таблица с последней актуальной ревизией. И есть таблица изменений до этой ревизии. Структура аналогична основной таблице, но + еще два поля - номер ревизии и что сделали с записью. Возможно + дата (это если потребуется вывести на определенный момент времени).
Рассмотрим ситуацию. у нас есть таблица foo
item_id bar baz
1 1 1
2 1 2
3 1 3
и таблица истории hfoo (action - тип действия, 1/2/3 insert/update/delete)
rev action item_id bar baz
1 1 1 3
2 2 1 1

Теперь к нам прилетают изменения. (Номер ревизии оставим глобальным для удобства). Сначала мы их вливаем во временную табличку foo_temp
Теперь делаем следующее
insert into hfoo(rev, action, item_id, bar, baz)
select @rev, 1, f.item_id, f.bar, f.baz
from foo_temp f
where not exists(select 1 from foo f2 where f.item_id = f2.item_id)
Это мы прописали записи, которых раньше не было.
insert into hfoo(rev, action, item_id, bar, baz)
select @rev, 1, f.item_id, f.bar, f.baz
from foo f
where not exists(select 1 from foo_temp f2 where f.item_id = f2.item_id)
Это наоборот удаленные записи.
insert into hfoo(rev, action, item_id, bar, baz)
select @rev, 1, f.item_id, f.bar, f.baz
from foo_temp f
where exists(select 1 from foo f2 where f.item_id = f2.item_id and (f.bar <> f2.bar or f.baz <> f2.baz))
А это измененные...
Теперь очищаем foo и переливаем туда все данные из foo_temp
И имеем актуальные данные + история изменений.

(Reply to this)(Parent)


[info]codesign
2007-03-26 09:45 am UTC (link)
пересобирал с флагами ND?

(Reply to this)(Thread)


[info]_kleptos_
2007-03-26 09:54 am UTC (link)
что за флаг такой?
пересобрал всё встраивающее в себя пёрл.

(Reply to this)(Parent)(Thread)


[info]codesign
2007-03-26 10:06 am UTC (link)
--newuse (-N short option)
      Tells emerge to include installed packages where USE flags have
      changed since installation.

--deep (-D short option)
      When used in conjunction with --update, this flag forces emerge
      to consider the entire dependency tree of packages, instead of
      checking only the immediate dependencies of the packages.  As an
      example, this catches updates in libraries that are not directly
      listed in the dependencies of a package.

Т.е. обновляем все, что зависит от изменившихся юзов, проверяя зависимости "до самого корня" :)
(если добавили в юзы ithreads, то libperl сама потянется)

(Reply to this)(Parent)(Thread)

таки да, немного помогает.
[info]_kleptos_
2007-03-26 10:21 am UTC (link)
localhost kleptos # USE="-ithreads" emerge -1avtD perl

These are the packages that would be merged, in reverse order:

Calculating dependencies... done!
[nomerge      ] sys-devel/libperl-5.8.8-r1  USE="berkdb gdbm ithreads -debug" 
[nomerge      ]  dev-lang/perl-5.8.8-r2  USE="berkdb gdbm -build -debug -doc -ithreads* -perlsuid" 
[ebuild     U ]   perl-core/PodParser-1.35 [1.32] 96 kB 
[nomerge      ]   perl-core/Test-Harness-2.64  
[ebuild   R   ]    dev-lang/perl-5.8.8-r2  USE="berkdb gdbm -build -debug -doc -ithreads* -perlsuid" 0 kB 

Total: 2 packages (1 upgrade, 1 reinstall), Size of downloads: 96 kB

Would you like to merge these packages? [Yes/No]

но vim за собой не потащило.

(Reply to this)(Parent)(Thread)

Re: таки да, немного помогает.
[info]codesign
2007-03-26 10:41 am UTC (link)
а -N?

т.е. в принципе там возможны ситуации, когда что-то не пересоберется (когда зависимости хреновенько прописаны) или когда баги в зависимостях (недавно вот наткнулся с апачем. новый apr не поставили в зависимость.)

vim - хз как она зависит от перла. возможно его и не надо пересобирать.
хотя по моему perl-cleaner его переставляет.

(Reply to this)(Parent)(Thread)

Re: таки да, немного помогает.
[info]_kleptos_
2007-03-26 10:48 am UTC (link)
сорри, туплю спросонья.
perl тащит за собой libperl, но не более.
ни у кого, кто эмбедит пёрл нет ithreads юзфлага.
поэтому я не думаю, что можно как-то отловить бинарную несовместимость.
даже revdep-rebuild не спасёт.

(Reply to this)(Parent)


[info]_kleptos_
2007-03-26 10:22 am UTC (link)
вот чёрт, ступил.
sys-devel/libperl - то не реинсталиться, значит точно толку нет.

(Reply to this)(Parent)


Create an Account
Forgot your login?
Login w/ OpenID
English • Español • Deutsch • Русский…