OTP System Gen Server

Материал из Erlang по-русски.

Содержание

gen_server

Автор: Didro

Дата: 29.10.200\6

Версия: 1.0


Название модуля

gen_server

Краткое описание

Шаблон поведения обобщённого сервера

Описание

Базовый модуль, реализующий шаблон поведения сервера в рамках клиент-серверной модели. Реализованный с помощью этого модуля серверный процесс будет обладать стандартным набором интерфейсных функций, включая отладку и мониторинг ошибок. Данный процесс может быть частью OTP-дерева супервизоров. Более подробная информация приведена в OTP Design Principles. Дизайн данного серверного процесса предполагает, что весь специфичный, проблемно-ориентированный код сосредоточен в callback-модуле, который экспортирует набор предопределенных функций. Отображение функций шаблонного модуля на функции callback-модуля показано ниже:

Шаблонный (gen_server) модуль         Callback-модуль
-----------------------------        ---------------
gen_server:start_link         -----> Module:init/1 

gen_server:call
gen_server:multi_call         -----> Module:handle_call/3

gen_server:cast
gen_server:abcast             -----> Module:handle_cast/2

-                             -----> Module:handle_info/2

-                             -----> Module:terminate/2 

-                             -----> Module:code_change/3

Если при выполнении callback-функции возникает ошибка или если callback-функция возвращает некорректное значение, то работа gen_server будет прекращена. Имеется возможность использования модуля sys для отладки gen_server. Процесс gen_server не обрабатывает сигнал exit автоматически, обработка данного сигнала должна быть реализована вами в callback-модуле. Если такая функция не определена, то все функции в данном модуле будут завершаться неудачно, если указанный gen_server не существует или если получен некорректный аргумент. Экспортируемые функции

start_link(Module, Args, Options) -> Result
start_link(ServerName, Module, Args, Options) -> Result 

Типы:

ServerName = {local,Name} | {global,GlobalName}
 Name = atom()
 GlobalName = term()
	
Module = atom()
	
Args = term()
Options = [Option]
	
 Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}
	
  Dbgs = [Dbg]
	
   Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}
	
  SOpts = [term()]
	
Result = {ok,Pid} | ignore | {error,Error}
	
 Pid = pid()
	
 Error = {already_started,Pid} | term()
	

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

Процесс gen_server вызывает функцию Module:init/1 для инициализации сервера. Для синхронизации процедуры запуска сервера, функция start_link/3,4 не возвращает управление до тех пор, пока не завершится выполнение функции Module:init/1. Если ServerName={local,Name}, то gen_server будет локально зарегистрирован под именем Name с помощью вызова функции register/2. Если ServerName={global,GlobalName}, то будет проведена глобальная регистрация gen_server под именем GlobalName с помощью функции global:register_name/2. Если при вызове данной функции (start_link) имя не определено, то gen_server не будет зарегистрирован.

Module – это имя callback-модуля. Args – произвольный терм, передающийся в качестве параметра при вызове функции Module:init/1.

Если определена опция {timeout,Time}, то на инициализацию сервера отводится Time миллисекунд, по истечении которых работа сервера будет прекращена, а функция вернёт {error,timeout}. Если определена опция {debug,Dbgs}, то для каждого элемента в Dbgs будет вызвана соответствующая функция модуля sys. Подробнее смотрите описание модуля sys(3). Если определена опция {spawn_opt,SOpts}, то Sopts будет передан в качестве списка опций (spawn_opt) при вызове соответствующей BIF, которая будет использована для порождения (spawn) процесса gen_server. Подробнее смотрите описание модуля erlang (3).

Если gen_server успешно создан и проинициализирован, то функция вернёт {ok,Pid}, где Pid является идентификатором процесса gen_server. Если выполнение функции Module:init/1 завершается неудачно и причина ошибки (Reason) определена, то функция вернёт {error,Reason}. Если функция Module:init/1 возвращает {stop,Reason} или ignore, то процесс будет завершён и функция вернёт {error,Reason} или ignore соответственно. start(Module, Args, Options) -> Result

start(ServerName, Module, Args, Options) -> Result

Типы: ServerName = {local,Name} | {global,GlobalName}

Name = atom()

GlobalName = term()

Module = atom()

Args = term()

Options = [Option]

Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}

Dbgs = [Dbg]

Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}

SOpts = [term()]

Result = {ok,Pid} | ignore | {error,Error}

Pid = pid()

Error = {already_started,Pid} | term()

call(ServerRef, Request) -> Reply

call(ServerRef, Request, Timeout) -> Reply

Типы: ServerRef = Name | {Name,Node} | {global,GlobalName} | pid() Node = atom() GlobalName = term()Request = term()Timeout = int()>0 | infinityReply = term()

  • Идентификатор процесса, pid Name, если gen_server зарегистрирован локально *{Name,Node}, если gen_server зарегистрирован локально на другом узле(Node) *{global,GlobalName}, если gen_server зарегистрирован глобально. *клиент присоединён к gen_server и *клиент намерен завершить работу(is trapping exits) и *gen_server завершает свою работу в процессе обработки запроса,

multi_call(Name, Request) -> Result

multi_call(Nodes, Name, Request) -> Result

multi_call(Nodes, Name, Request, Timeout) -> Result

Типы: Nodes = [Node]

Node = atom()

Name = atom()

Request = term()

Timeout = int()>=0 | infinity

Result = {Replies,BadNodes}

Replies = [{Node,Reply}]

Reply = term()

BadNodes = [Node]

cast(ServerRef, Request) -> ok

Типы: ServerRef = Name | {Name,Node} | {global,GlobalName} | pid()

Node = atom()

GlobalName = term()

Request = term()

abcast(Name, Request) -> abcast

abcast(Nodes, Name, Request) -> abcast

Типы: Nodes = [Node]

Node = atom()

Name = atom()

Request = term()

reply(Client, Reply) -> true

Типы: Client – см. ниже

Reply = term()

enter_loop(Module, Options, State)

enter_loop(Module, Options, State, ServerName)

enter_loop(Module, Options, State, Timeout)

enter_loop(Module, Options, State, ServerName, Timeout)

Типы: Module = atom()

Options = [Option]

Option = {debug,Dbgs}

Dbgs = [Dbg]

Dbg = trace | log | statistics

| {log_to_file,FileName} | {install,{Func,FuncState}}

State = term()

ServerName = {local,Name} | {global,GlobalName}

Name = atom()

GlobalName = term()

Timeout = int() | infinity

Экспортируемые функции Module:init(Args) -> Result

Типы: Args = term()

Result = {ok,State} | {ok,State,Timeout}

| {stop,Reason} | ignore

State = term()

Timeout = int()>=0 | infinity

Reason = term()

Module:handle_call(Request, From, State) -> Result

Типы: Request = term()

From = {pid(),Tag}

State = term()

Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout}

| {noreply,NewState} | {noreply,NewState,Timeout}

| {stop,Reason,Reply,NewState} | {stop,Reason,NewState}

Reply = term()

NewState = term()

Timeout = int()>=0 | infinity

Reason = term()

Module:handle_cast(Request, State) -> Result

Типы: Request = term()

State = term()

Result = {noreply,NewState} | {noreply,NewState,Timeout}

| {stop,Reason,NewState}

NewState = term()

Timeout = int()>=0 | infinity

Reason = term()

Module:handle_info(Info, State) -> Result

Типы: Info = timeout | term()

State = term()

Result = {noreply,NewState} | {noreply,NewState,Timeout}

| {stop,Reason,NewState}

NewState = term()

Timeout = int()>=0 | infinity

Reason = normal | term()

Module:terminate(Reason, State)

Типы: Reason = normal | shutdown | term()

State = term()

  • gen_server has been set to trap exit signals (у процесса gen_serer должен быть установлен флаг обработки сигнала exit) и *стратегия завершения работы определена в спецификации потомков данного супервизора как целочисленное значение таймаута, а не как brutal_kill.

Module:code_change(OldVsn, State, Extra) -> {ok, NewState}

Типы: OldVsn = Vsn | {down, Vsn}

Vsn = term()

State = NewState = term()

Extra = term()