LINUX.ORG.RU

Самодельная блокировка файлов


0

0

Есть простенький cgi-скрипт, который принимает заявки от клиентов и складывает их в папку. Заявкам, соответственно, присваиваются порядковые имена.

Сейчас я выбираю номер для очередной заявки просто: смотрю список файлов в папке и прибавляю единицу.

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

В реальности, думаю, такая ситуация возможна, если интернет-канал сервера будет работать с лагами.

Чтобы решить проблему я вижу два пути.

1. Слегка усложнить систему и хранить заявки не в текстовом виде, а в виде базы MySQL.

2. Запилить самодельную систему блокировок.

Подскажите, реален ли второй вариант? И если да — как можно организовать процесс блокировки подручными средствами?


напиши простенький дэмон с queue, который будет принимать заявки от cgi-скрипта и записывать их соответственно по-очереди. т.о. у тебя будет только один процесс объщающийся с фалами и ни каких run-conditions.

beastie ★★★★★
()
Ответ на: комментарий от beastie

вариант ещё проще: дэмон следящий за поступлениями и возвращающий cgi-скрипту имя файла, куда ему писать.

beastie ★★★★★
()
Ответ на: комментарий от beastie

Хорошая идея. Может быть, так и сделаю.

Но пока не очень хочется плодить лишние работающие программы кроме самого Апача.

Думаю в настоящее время именовать заявки через md5(random).

Ritz
() автор топика
Ответ на: комментарий от friday

Да, годный метод. Очень большой плюс решения — простота.

Минусы:

1. Система непрозрачная для админа, заглянувшего в папку. 2. Надо всё равно выдумывать систему, которая будет присваивать заявкам номера в виде натуральных чисел и удалять дубли.

Ritz
() автор топика

Вроде бы придумал безумный метод.

При создании нового файла:

1. Придумываем себе уникальный id.

2. Берём номер на единицу больше самого большого (по имени) файла в директории.

3. Делаем append в файл locks:
$номер:$id

4. Читаем файл locks и проверяем, не записал ли кто-нибудь туда же этот номер за одну микросекунду до нас. Если мы опоздали, идём в пункт 2.

5. Записываем файл.

Ritz
() автор топика

Меня удивляет настойчивое желание людей изобретать себе грабли, а потом ходить по форумам и спрашивать, какую им ручку на них поставить, чтобы било не так больно. Для таких вещей обычно используется СУБД, её и нужно здесь использовать.

Wizard_ ★★★★★
()
Ответ на: комментарий от Wizard_

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

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

Кстати, мой «велосипед» таки поехал. DDOS-тест на 100 одновременных запросов проходится вполне успешно: создаётся 100 файлов с идущими по порядку именами.

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

Ritz
() автор топика
Ответ на: комментарий от Ritz

можно и DB4, всётаки как не крути, но mysql — это IMO тотальный overkill для практически любой задачи

beastie ★★★★★
()

man 2 flock, man 1 flock.

int fd = open("/var/lock/mycgilock",O_RDONLY);
if (flock(fd,LOCk_EX)==0) {
   do_what_you_want();
   flock(fd,LOCK_UN);
} else {
   printf("Mysterious error %d!\n",errno);
}
close(fd);
Nastishka ★★★★★
()
Ответ на: комментарий от Nastishka

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

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

Nastishka ★★★★★
()

Сделай проверку на то, существует ли уже создаваемый файл. Вот и всё. Тогда создавая заявку оно точно не перезапишет старую.

anonymous
()
Ответ на: комментарий от Ritz

>Ага, спасибо. На первый взгляд, это более правильный метод.

Лучше только именованый семафор в памяти. И всё равно учти совет анонима выше - заставь fopen обламываться, если файл существует.

legolegs ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.