Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -module(fsmA). % Логика обработки заявок в системе А
- -export([timeout/2, action/4, state/4]).
- % Структура data, задающая полное состояние обработчика заявки в системе А.
- % (не включает формальное состояния КА).
- % Здесь хранится число попытко опроса и ответы от систем B и C
- -record(data, {id, retries_B, retries_C, retries_D1, retries_D2, retries_END,
- reply_B, reply_C, reply_D, reply_END}).
- % Параметры работы обработчика заявок системы А.
- -define(TIMEOUT_B, 1*1000).
- -define(TIMEOUT_C, 1*1000). %
- -define(TIMEOUT_D1, 1*1000). %
- -define(TIMEOUT_D2, 2*1000). %
- -define(TIMEOUT_END, 1*1000). %
- -define(RETRIES_B, 8). % таймаут ответа от B
- -define(RETRIES_C, 8). % таймаут ответа от B
- -define(RETRIES_D1, 4). % таймаут ответа от C
- -define(RETRIES_D2, 4).
- -define(RETRIES_END, 8). % таймаут ответа от D
- %
- % Описание автомата
- %
- % Функция state может возвращать либо только очередное состояние, либо
- % пару из названия состояния и изменённого полного состояния.
- % Например, выражение Data#data{reply_C = Answer} создаёт из структуры
- % Data типа data новую структуру, где будет измемено поле reply_C.
- % Функция action так же может вернуть либо просто ok/finish, либо пару
- % из них и нового состояния заявки.
- % Таймауты
- %
- % Пока ещё нет ни одного ответа, запустить два таймера.
- % Если один из них запущен, то он не будет измёнен.
- timeout(wait, _) ->
- [{?TIMEOUT_B, timeout_B}];
- % Пока ещё нет ответа от А. Если таймер timeout_B
- % запущен, он не будет изменён.
- timeout(wait_B, _) ->
- [{?TIMEOUT_C, timeout_C}];
- % Пока ещё нет ответа от B. Если таймер timeout_C
- % запущен, он не будет изменён.
- timeout(wait_C, _) ->
- [{?TIMEOUT_D1, timeout_D1}];
- timeout(wait_D,_) ->
- [{?TIMEOUT_D2, timeout_D2}];
- timeout(wait_END, _) ->
- [{?TIMEOUT_END, timeout_END}];
- % В иных случаях все таймеры останавливаются.
- timeout(_, _) -> [].
- % Функция перехода.
- %
- % Переход из начального состояния в состояние ожидания ответов.
- state(init, start, _, _) ->
- wait;
- % Приход ответа от системы B. Нам интересен этот ответ в двух возможных состояниях.
- state(wait, ack_B, Data, Answer) ->
- {wait_C, Data#data{reply_B = Answer}};
- % Приход ответа от системы С.
- state(wait_B, ack_C, Data, Answer) ->
- {wait_C, Data#data{reply_C = Answer}};
- % Приход ответа от системы D
- state(wait_D, ack_D, Data, Answer) ->
- {wait_END, data#data{reply_D = Answer}};
- % Приход негативного ответа (не важно, от кого).
- state(wait, nack_B, Data, Answer) ->
- {wait_C, Data#data{reply_B = Answer}};
- state(wait_B, nack_C, Data, Answer) ->
- {wait_D, Data#data{reply_C = Answer}};
- state(wait_D, ack_D, Data, Answer) ->
- {wait_END, Data#data{reply_D = Answer}};
- % Повторы попыток опроса системы B.
- state(wait, timeout_B, #data{retries_B = N}, _) when (N < ?RETRIES_B) ->
- wait;
- state(wait, timeout_B, _, _) ->
- cancel;
- state(wait_B, timeout_B, #data{retries_B = N}, _) when (N < ?RETRIES_B) ->
- wait_B;
- state(wait_B, timeout_B, _, _) ->
- cancel;
- % Повторы попыток опроса системы C.
- state(wait, timeout_C, #data{retries_C = N}, _) when (N < ?RETRIES_C) ->
- wait;
- state(wait, timeout_C, _, _) ->
- cancel;
- state(wait_C, timeout_C, #data{retries_C = N}, _) when (N < ?RETRIES_C) ->
- wait_C;
- state(wait_C, timeout_C, _, _) ->
- cancel;
- % Для остальных случаев функция перехода не определена,
- % автомат никуда не двигается.
- state(State, Message, Data, _) ->
- io:format("~s: state [~w]: ignoring message [~w]~n",
- [Data#data.id, State, Message]),
- undefined.
- % Действия при изменении состояния (выход).
- % Его опиcание связывается с новым состоянием,
- % а не исходным -- здесь это удобнее.
- %
- % Инициализация состояния.
- action(init, _, {Id}, _) ->
- io:format("~s: started~n",
- [Id]),
- {ok, #data{id = Id, retries_B = 0, retries_C = 0,
- reply_B = undefined, reply_C = undefined}};
- % При первом входе в состояние ожидания
- % опрашиваются обе системы.
- action(wait, start, Data, _) ->
- io:format("~s: poll B & C~n", [Data#data.id]),
- % Посылаем сообщения.
- system_B ! {self(), request},
- system_C ! {self(), request},
- {ok , Data#data{retries_B = 1, retries_C = 1}};
- %~ {ok, Data#data{retries = N}};
- % Таймаут опроса системы B.
- action(wait, timeout_B, Data, _) ->
- N = Data#data.retries_B + 1,
- io:format("~s: poll B, ~w~n", [Data#data.id, N]),
- system_B ! {self(), request},
- {ok, Data#data{retries_B = N}};
- action(wait_B, timeout_B, Data, _) ->
- N = Data#data.retries_B + 1,
- io:format("~s: poll B, ~w~n", [Data#data.id, N]),
- system_B ! {self(), request},
- {ok, Data#data{retries_B = N}};
- % Таймаут опроса системы С.
- action(wait, timeout_C, Data, _) ->
- N = Data#data.retries_C + 1,
- io:format("~s: poll C, ~w~n", [Data#data.id, N]),
- system_C ! {self(), request},
- {ok, Data#data{retries_C = N}};
- action(wait_C, timeout_C, Data, _) ->
- N = Data#data.retries_C + 1,
- io:format("~s: poll C, ~w~n", [Data#data.id, N]),
- system_C ! {self(), request},
- {ok, Data#data{retries_C = N}};
- % Завершение работы
- action(cancel, _, Data, _) ->
- io:format("~s: canceling~n", [Data#data.id]),
- finish;
- action(done, _, Data, _) ->
- io:format("~s: success, answers: ~s, ~s~n", [Data#data.id,
- Data#data.reply_B, Data#data.reply_C]),
- finish;
- % Ничего не делать в остальных случаях
- action(State, _, Data, _) ->
- io:format("~s: no action in [~w]~n", [Data#data.id, State]),
- ok.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement