Отправляет email-рассылки с помощью сервиса Sendsay

Совместный доступ к конфигурации

Имеется GUI/CLI программа на Python - Chestnut Dialer. Файл конфигурации
пользователя представляет собой XML-файл, который загружается программой
при запуске. Загруженные данные хранятся в ОЗУ, и изменяются по команде
пользователя. Перед завершением программа сохраняет данные обратно в
этот XML-файл.

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

Нужно чтобы несколько процессов использовали конфигурацию совместно в
режиме Ч/З, с возможностью оповещения остальных процессов о сделанных
другим процессом изменениях в конфигурации.

Кто какие варианты предложит?

У меня пока только на уме отдельный сервер, обслуживающий все
процессы через unix domain socket. Может можно сделать как то получше
(читай проще :) ?

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

Ответить   Konstantin Korikov Sat, 21 May 2005 23:12:12 +0300 (#371582)

 

Ответы:

On Sat, 21 May 2005 23:12:12 +0300, Konstantin Korikov <lostcl***@u*****.fm> said:


[skip]


А может сохранять сразу после изменения? И добавить команду в меню -
перечитать конфиг. Тогда блокировку надо делать только для записи
и на время записи.

ИМХО тут он нафиг не нужен.

Необязательно.

Что лучше подходит для конкретной задачи. Для Unix Domain Sockets
передача датаграмм гарантируется (в отличие от UDP).

Не SysV IPC и не Sub RPC (IMHO). Использовать XML-RPC vs.
сокеты ИМХО дело вкуса.

HTH.

Ответить   Max Vasin Sun, 22 May 2005 00:55:33 +0400 (#371590)

 

В сообщении от 1116712533 секунд после начала Эпохи Unix Вы написали:

Любопытная идея, но будет небольшая потеря в производительности. И
ручное перечитывание конфига будет не очень удобно для пользователей.

А почему не SysV IPC? Очереди сообщений и разделяемая память, насколько
я помню, входят в состав SysV IPC, но вить они широко используются.

Вот только я что-то не нашел в стандартной поставке Python
реализации XML-RPC, которую можно прикрутить к unix domain socket,
только через TCP... Может плохо искал...

Ответить   Konstantin Korikov Sun, 22 May 2005 00:57:23 +0300 (#371613)

 

On Sun, 22 May 2005 00:57:23 +0300, Konstantin Korikov <lostcl***@u*****.fm> said:



А пользователи эту потерю производительности заметят? Вы же не десятки
мегабайт сохранять будете. А вместо ручного перечитывания - помнится
есть такая вещь FAM (File Alteration ...) может на нее стоит посмотреть.

И не найдете. На то он и XML-RPC, что поверх HTTP работает.

Ответить   Max Vasin Sun, 22 May 2005 11:29:38 +0400 (#371710)

 

В сообщении от 1116750578 секунд после начала Эпохи Unix Вы написали:

Зато многократно, и если при изменении каждого отдельного параметра
будет происходить сериализация XML документа, и сохранение его в файл,
то потеря производительности будет заметна. Конечно можно улучшить
ситуацию вызывая некую функцию lock, которая увеличит счетчик
блокировки, тем самым откладывая сохранение файла до того времени как
все параметры будут установлены. Однако, параметры у меня хранятся не в
виде переменных или полей классов, а в виде дерева DOM, доступ к
которому осуществляется посредством интерфейсных классов, объекты
которых хранят ссылки на отдельные ветви этого дерева, так что после
перечитывания конфига обновлять ссылки на эти ветви будет крайне
затруднительно. А представление конфигурации в DOM дает сохранность
параметров, которые в данной версии программы не используются. Например
если старой версии программы дать конфигурационный файл более новой
версии, то она его не испортит, или попортит незначительно.

В общем я попробую сделать сервер, основанный на очередях сообщений из
System V IPC. Это даст еще одну интересную особенность - протокол один,
а реализаций сервера может быть несколько. Например один использует в
качестве хранилища XML-файл, и соответственно зависит от libxml2, второй
использует обычный, так называемый, INI-файл, и зависит от стандартного
модуля ConfigParser. Третий использует GConf, и зависит от библиотек
GNOME, и т.п. Таким образом пользователь при конфигурировании
(`./configure') может выбрать подходящий метод, в зависимости от вкуса и
от тех библиотек, которые он имеет в системе.

Всем спасибо!

Ответить   Konstantin Korikov Sun, 22 May 2005 13:11:47 +0300 (#371809)

 

On Sun, 22 May 2005 13:11:47 +0300, Konstantin Korikov <lostcl***@u*****.fm> said:


Хмм, такую совместимость легко можно обеспечить и при простом
конфигурационном файле. Парсер должен выдавать отображение
ключей на значения (при этом он ничего не знает о том какие
ключи используются программой). Вы же dialer пишите, не переусложняете
ли вы таким механизмом программу? Я кстати не совсем понимаю зачем может
понадобится запуск нескольких процессов dialer'а.

Ответить   Max Vasin Sun, 22 May 2005 15:33:50 +0400 (#371837)

 

В сообщении от 1116765230 секунд после начала Эпохи Unix Вы написали:

Это при чтении файла. А при записи? Как тогда записать ключи и значения
(возможно даже и комментарии), которые содержались в файле при
считывании, но небыли распознаны, и небыли занесены в ОЗУ?

Думаю, много сложного из мира С превращается в легкое и
простое в мире Python. Мощь ООП + набор высокоуровневых инструментов
делают свое дело. Что самое удивительное - все работает быстро. Java
отдыхает!!! :-D

:) Это уже будет не совсем dialer. Точнее, его уже давно можно
использовать для обработки входящих звонков (dialin-сервер), и с
небольшими исправлениями для подключения двух машин по нуль-модемному
кабелю, но в некоторых ситуациях пользователю может понадобится
запустить несколько экземпляров (например: два модема, один dialin,
другой dialout; или модем + нуль-модем; или даже VPN [пока не пробовал,
но думаю и это тоже возможно]), вот тут и мешает текущие состояние дел с
конфигураций. В общем Chestnut Dialer станет универсальным GUI/CLI
frontend'ом к pppd.

Ответить   Konstantin Korikov Sun, 22 May 2005 16:22:52 +0300 (#371871)

 

On Sun, 22 May 2005 16:22:52 +0300, Konstantin Korikov <lostcl***@u*****.fm> said:



Нет при чтении надо распознавать все и хранить и имена ключей и их
значения. Далее при изменении настроек нужно обновлять эту самую
базу настроек. И тогда при записи в файл ничего не потеряется.

Я о сложности архитектуры программы говорил. Ведь тут и CORBA
можно использовать ;-)

Ответить   Max Vasin Sun, 22 May 2005 18:19:08 +0400 (#371888)

 

В сообщении от 1116775148 секунд после начала Эпохи Unix Вы написали:

Вот так я и делаю - храню все ключи и значения в виде дерева DOM (та
самая база настроек, о которой вы говорите). Но дело в том что у меня
не просто ключи/значения, а несколько более сложная структура:

config
ключ1 = значение1
ключN = значениеN
1_ui
ключ1 = значение1
ключN = значениеN
N_ui
ключ1 = значение1
ключN = значениеN
default_account
ключ1 = значение1
ключN = значениеN
account_list
account1
ключ1 = значение1
ключN = значениеN
accountN
ключ1 = значение1
ключN = значениеN

Доступ к этому хозяйству в программе осуществляется примерно таким
образом:

config.ключ1
config.1_ui.ключ1
config.default_account.ключ1
accounts.get_account(1).ключ1

В последнем примере метод get_account() возвращает объект, который имеет
ссылку на определенную ветвь дерева DOM. Такие ссылки могут быть
разбросаны в программе, и обновление их, как я уже говорил будет
затруднительно. А при использовании сервера я просто модифицирую
интерфейсные классы, так чтобы они обращались к серверу для получения и
установки значений.

А почему бы и нет? :) Если это не создаст дополнительные проблемы как
пользователю так и разработчику. Если бы поддержка CORBA шла в
стандартной поставке Python (что очень важно, так как пользователи
совсем не горят желанием качать дополнительные библиотеки) и этот
механизм работал бы быстро, и не требовал много системных ресурсов, то я
с радостью использовал бы CORBA. А так я использую программные гнезда,
что не создаст проблем ни пользователю, ни разработчику (т.е. мне).
Когда я работаю над архитектурой я стараюсь найти золотую середину между
простотой, расширяемостью, взаимозаменяемостью и производительностью.
Вообще это даже касается не только архитектуры, но и отдельного куска
кода.

Ответить   Konstantin Korikov Sun, 22 May 2005 19:38:33 +0300 (#371944)

 

В сообщении от 1116756707 секунд после начала Эпохи Unix Вы написали:

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

Ответить   Konstantin Korikov Sun, 22 May 2005 14:39:48 +0300 (#371854)

 

В сообщении от 1116761988 секунд после начала Эпохи Unix Я написал:

Хм... Оказывается датаграммныные гнезда в домене Unix работают только в
одном направлении. Сервер запросы получает, а ответить не может, так как
функция recvfrom возвратила пустой адрес клиента. Я что-то путаю, или
действительно при такой конфигурации возможна передача только в одном
направлении? Придется создавать еще по одному гнезду для каждого клиета?
Или нужно использовать поточное соединение?...

Ответить   Konstantin Korikov Sun, 22 May 2005 20:18:58 +0300 (#371958)

 

Konstantin Korikov пишет:

Процессы запускаются разными пользователями? Если у каждого пользователя
будет свой профиль в $HOME, то это несолько разрядит обстановку.

По одному процессу на каждого активного пользователя. Если нужно
распаралеливание для одного пользователя то использовать нити (thread) с
блокировкой доступа к конфигурации через mutex.

Если запросы обслуживаются быстро, то необязательно. В listen() можно
указать число процессов ждущих подключения. При этом грамотная обработка
ошибок connect() в клиенте будет лучьше чем многопотоковость в сервере.
IMHO.

Лучьше TCP. UDP используются в основном для всяческих широковещательных
опросов где не страшна потеря информации. Что касается других IPC то
напрашивается вариант с shared memory, но опять же с доступом через mutex.

Ответить   Sun, 22 May 2005 00:04:51 +0300 (#371599)

 

В сообщении от 1116709491 секунд после начала Эпохи Unix Вы написали:

В том то и дело что одним.

Не очень подходит этот вариант, так как разные процессы могут
использоваться с разными интерфейсами пользователя. Например может быть
запущен один GUI, основанный GTK, другой - на QT, а третий вообще как
wvdial без GUI с выводом на консоль.

Не думаю что внутри ядра что-то потеряется...

Разделяемая помять не подойдет, вернее ее использование в Python
равносильно использованию отрытого файла, я вить не могу помещать
внутренние структуры интерпретатора в определенные адреса памяти. Но все
равно, спасибо что откликнулись.

Ответить   Konstantin Korikov Sun, 22 May 2005 01:14:26 +0300 (#371619)

 

On Sun, 22 May 2005 00:04:51 +0300, "Yuri N. Glibovetz" <inetst***@g*****.com>
said:

Для Unix domain sockets UDP не используется и передача датаграмм
гарантируется.

Ответить   Max Vasin Sun, 22 May 2005 11:33:10 +0400 (#371713)

 

В сообщении от 1116709491 секунд после начала Эпохи Unix Вы написали:

Т.е. для каждого запроса клиенту нужно создавать новое гнездо (socket),
а потом вызвать функцию connect? Что-то я тут совсем запутался в этих
гнездах. Нужно поискать доку... Когда заканчивается запрос в клиенте?
Когда он перестал посылать данные (send), принял ответ (recv), и закрыл
гнездо (close)? А если использовать постоянно send, recv, send, recv,
... (вместо socket, connect, send, recv, close, socket, connect, send,
recv, close, ...) то что это будет? Или такой подход нигде не
используется?

Ответить   Konstantin Korikov Mon, 23 May 2005 00:09:24 +0300 (#372032)

 

On Sat, 21 May 2005 23:12:12 +0300
Konstantin Korikov <lostcl***@u*****.fm> wrote:

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

Ответить   Matvey Sun, 22 May 2005 00:22:11 +0300 (#371608)

 

В сообщении от 1116710531 секунд после начала Эпохи Unix Вы написали:

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

Нет, лучше по mtime, так как atime у меня отключен в /etc/fstab. :)
Еще я слышал о каких мониторах, следящими за изменениями в файлах, но
это уже будут нежелательные зависимости.

Ответить   Konstantin Korikov Sun, 22 May 2005 01:32:35 +0300 (#371618)

 

Здравствуйте, Konstantin.

Вы писали 21 мая 2005 г., 23:12:12:

можно попробовать посылать всем прецессам какй-то сигнал, по которому
они перечитают конфиги

Ответить   Sun, 22 May 2005 12:01:56 +0300 (#371768)