erlang functional

Как я файлы между узлами Erlang пересылал

Dmitry Vasiliev 22:43, 2010 1 19

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

Воспитанный на совсем других языках, изначально я смекнул следующее - Erlang у нас "из коробки" поддерживает передачу сообщений, соответственно нужно на узле с архивом открыть его как файл, потихоньку читать и сообщениями каждый кусочек пересылать на второй узел. На втором узле нужно все это дело потихоньку записывать в новый файл, который по окончании пересылки остается только разархивировать.

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

На этом этапе я прикинул, что раз есть такая штука как протокол ввода/вывода, то все задуманное мной "хозяйство" уже должно быть где-то реализовано. Ага, и реализовано оно не где-нибудь, а начиная с модуля file. Красота. Удаленный ввод/вывод для ленивых - на одном узле файл открываем, пересылаем дескриптор, а читаем его уже на другом узле.

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

Дальше удалось обнаружить, что erl_tar:extract/2 оказывается в качестве имени может и дескриптор файла принимать - {file, Fd}. Т.е. на удаленном узле файл открываем, передаем дескриптор и дальше erl_tar:extract и вуаля. К сожалению, в реальном мире не всегда все так "шоколадно" получается - даже локальный файл открытый без опции raw (т.е. с тем самым сервером ввода/вывода) разархивируется erl_tar:extract во много раз медленнее чем файл открытый как обычный файловый дескриптор (c опцией raw).

Но в итоге, думаю, мне все же удалось обнаружить нужный компромисс. Разгадка, как оказалось, скрывается в функции file:copy/2, которой тоже, кроме просто имени, можно передать и дескриптор файла. Таким образом, заполучив дескриптор удаленного файла его можно скопировать локально вот, примерно, так:

{ok, BytesCopied} = file:copy(RemoteFd, {LocalFileName, [binary, raw]})

Да, действительно - делать распределенные приложения с Erlang может быть до неприличия просто, "учебный" код порой может занимать всего несколько строк.

Comments All comments

Comment by bialix on 08:56, 2010 1 20

bialix's Gravatar

Сила встроенных функций и библиотек! Аналогично как в Питоне.

Comment by Dmitry Vasiliev on 12:09, 2010 1 20

Dmitry Vasiliev's Gravatar

Да, прежде чем писать что-то свое, стоит покопаться в документации.

Add comment

Name:
Email: (Never will be published.)
Web site:
Comment: (Paragraphs divided by empty lines, line breaks and links will be automatically formatted.)