Erlang 21 - 4. gen_event Behaviour

4 जीन_वेंट बिहेवियर




erlang

4 जीन_वेंट बिहेवियर

यह खंड gen_event(3) में gen_event(3) मैनुअल पेज के साथ पढ़ा जाना है, जहां सभी इंटरफ़ेस फ़ंक्शंस और कॉलबैक फ़ंक्शन का विस्तार से वर्णन किया गया है।

4.1 इवेंट हैंडलिंग सिद्धांत

ओटीपी में, एक इवेंट मैनेजर एक नामित ऑब्जेक्ट है, जिसके लिए इवेंट भेजे जा सकते हैं। एक घटना हो सकती है, उदाहरण के लिए, एक त्रुटि, एक अलार्म, या कुछ जानकारी जिसे लॉग किया जाना है।

इवेंट मैनेजर में, शून्य, एक या कई ईवेंट हैंडलर लगाए जाते हैं। जब इवेंट मैनेजर को किसी इवेंट के बारे में सूचित किया जाता है, तो इवेंट को सभी इंस्टॉल किए गए इवेंट हैंडलर द्वारा प्रोसेस किया जाता है। उदाहरण के लिए, त्रुटियों से निपटने के लिए एक इवेंट मैनेजर में डिफ़ॉल्ट रूप से एक हैंडलर स्थापित हो सकता है, जो टर्मिनल पर त्रुटि संदेश लिखता है। यदि एक निश्चित अवधि के दौरान त्रुटि संदेश किसी फ़ाइल में भी सहेजे जाने हैं, तो उपयोगकर्ता एक अन्य ईवेंट हैंडलर जोड़ता है जो ऐसा करता है। जब फ़ाइल में लॉग इन करना आवश्यक नहीं है, तो यह ईवेंट हैंडलर हटा दिया जाता है।

एक इवेंट मैनेजर को एक प्रक्रिया के रूप में लागू किया जाता है और प्रत्येक ईवेंट हैंडलर को कॉलबैक मॉड्यूल के रूप में लागू किया जाता है।

इवेंट मैनेजर अनिवार्य रूप से {Module, State} जोड़े की एक सूची रखता है, जहां प्रत्येक Module एक इवेंट हैंडलर है, और State उस इवेंट हैंडलर की आंतरिक स्थिति है।

४.२ उदाहरण

टर्मिनल के लिए ईवेंट हैंडलर लेखन त्रुटि संदेश के लिए कॉलबैक मॉड्यूल निम्नानुसार देख सकते हैं:

-module(terminal_logger).
-behaviour(gen_event).

-export([init/1, handle_event/2, terminate/2]).

init(_Args) ->
    {ok, []}.

handle_event(ErrorMsg, State) ->
    io:format("***Error*** ~p~n", [ErrorMsg]),
    {ok, State}.

terminate(_Args, _State) ->
    ok.

इवेंट हैंडलर को किसी फ़ाइल में त्रुटि संदेश लिखने के लिए कॉलबैक मॉड्यूल निम्नानुसार देख सकते हैं:

-module(file_logger).
-behaviour(gen_event).

-export([init/1, handle_event/2, terminate/2]).

init(File) ->
    {ok, Fd} = file:open(File, read),
    {ok, Fd}.

handle_event(ErrorMsg, Fd) ->
    io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
    {ok, Fd}.

terminate(_Args, Fd) ->
    file:close(Fd).

कोड को अगले खंडों में समझाया गया है।

4.3 एक इवेंट मैनेजर शुरू करना

त्रुटियों से निपटने के लिए एक इवेंट मैनेजर शुरू करने के लिए, जैसा कि पिछले उदाहरण में बताया गया है, निम्नलिखित फ़ंक्शन को कॉल करें:

gen_event:start_link({local, error_man})

यह फ़ंक्शन स्पैन और एक नई प्रक्रिया के लिंक देता है, एक इवेंट मैनेजर।

तर्क, {local, error_man} नाम निर्दिष्ट करता है। इवेंट मैनेजर तब स्थानीय रूप से error_man रूप में पंजीकृत error_man

यदि नाम छोड़ा गया है, तो इवेंट मैनेजर पंजीकृत नहीं है। इसके बजाय इसके पिड का उपयोग किया जाना चाहिए। नाम को {global, Name} रूप में भी दिया जा सकता है, जिस स्थिति में इवेंट मैनेजर global:register_name/2 का उपयोग करके global:register_name/2

gen_event:start_link का उपयोग किया जाना चाहिए, यदि इवेंट मैनेजर किसी सुपरवाइजर द्वारा शुरू किए गए gen_event:start_link ट्री का हिस्सा है। एक अन्य फ़ंक्शन है, gen_event:start , एक स्टैंडअलोन ईवेंट मैनेजर शुरू करने के लिए, जो कि एक इवेंट मैनेजर है जो किसी gen_event:start ट्री का हिस्सा नहीं है।

4.4 इवेंट हैंडलर जोड़ना

निम्न उदाहरण से पता चलता है कि एक इवेंट मैनेजर कैसे शुरू करें और शेल का उपयोग करके एक इवेंट हैंडलर इसमें जोड़ें:

1> gen_event:start({local, error_man}).
{ok,<0.31.0>}
2> gen_event:add_handler(error_man, terminal_logger, []).
ok

यह फ़ंक्शन त्रुटि प्रबंधक के रूप में पंजीकृत ईवेंट मैनेजर को एक संदेश भेजता है, यह इवेंट हैंडलर error_man को जोड़ने के लिए कहता है। इवेंट मैनेजर कॉलबैक फ़ंक्शन add_handler को कॉल करता terminal_logger:init([]) , जहां तर्क [] add_handler का तीसरा तर्क है। init वापस लौटने की उम्मीद है {ok, State} , जहां State ईवेंट हैंडलर की आंतरिक स्थिति है।

init(_Args) ->
    {ok, []}.

यहां, init को किसी इनपुट डेटा की आवश्यकता नहीं है और इसके तर्क की उपेक्षा करता है। terminal_logger , आंतरिक स्थिति का उपयोग नहीं किया जाता है। file_logger , आंतरिक स्टेट का उपयोग ओपन फाइल डिस्क्रिप्टर को बचाने के लिए किया जाता है।

init(File) ->
    {ok, Fd} = file:open(File, read),
    {ok, Fd}.

4.5 घटनाओं के बारे में सूचित करना

3> gen_event:notify(error_man, no_reply).
***Error*** no_reply
ok

error_man इवेंट मैनेजर का नाम है और no_reply ईवेंट है।

घटना को एक संदेश में बनाया गया है और घटना प्रबंधक को भेजा गया है। जब ईवेंट प्राप्त होता है, तो इवेंट मैनेजर प्रत्येक इंस्टॉल किए गए ईवेंट हैंडलर के लिए handle_event(Event, State) को उसी क्रम में कॉल handle_event(Event, State) , जिस क्रम में उन्हें जोड़ा गया था। फ़ंक्शन को टपल {ok,State1} वापस करने की उम्मीद है, जहां स्टेट 1 इवेंट हैंडलर की स्थिति के लिए एक नया मूल्य है।

terminal_logger :

handle_event(ErrorMsg, State) ->
    io:format("***Error*** ~p~n", [ErrorMsg]),
    {ok, State}.

file_logger :

handle_event(ErrorMsg, Fd) ->
    io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
    {ok, Fd}.

4.6 इवेंट हैंडलर हटाना

4> gen_event:delete_handler(error_man, terminal_logger, []).
ok

यह फ़ंक्शन ईवेंट हैंडलर के रूप में पंजीकृत ईवेंट मैनेजर को एक संदेश भेजता है, जो ईवेंट हैंडलर error_man को हटाने के लिए कहता है। इवेंट मैनेजर कॉलबैक फ़ंक्शन delete_handler को कॉल करता terminal_logger:terminate([], State) , जहां तर्क [] delete_handler का तीसरा तर्क है। terminate करना init के विपरीत होना और किसी भी आवश्यक सफाई को करना है। इसके रिटर्न वैल्यू को नजरअंदाज किया जाता है।

terminal_logger , कोई सफाई आवश्यक नहीं है:

terminate(_Args, _State) ->
    ok.

file_logger , init में खोली गई फ़ाइल का विवरण बंद होना चाहिए:

terminate(_Args, Fd) ->
    file:close(Fd).

4.7 रोकना

जब एक इवेंट मैनेजर को रोका जाता है, तो यह प्रत्येक इंस्टॉल किए गए इवेंट हैंडलर को terminate/2 कॉल करके सफाई करने का मौका देता है, उसी तरह जैसे किसी हैंडलर को हटाते समय।

एक पर्यवेक्षण वृक्ष में

यदि इवेंट मैनेजर किसी पर्यवेक्षण ट्री का हिस्सा है, तो स्टॉप फ़ंक्शन की आवश्यकता नहीं है। इवेंट मैनेजर अपने पर्यवेक्षक द्वारा स्वचालित रूप से समाप्त हो जाता है। वास्तव में यह कैसे किया जाता है यह पर्यवेक्षक में निर्धारित shutdown strategy द्वारा परिभाषित किया गया है।

स्टैंडअलोन इवेंट मैनेजर्स

एक इवेंट मैनेजर को कॉल करके भी रोका जा सकता है:

> gen_event:stop(error_man).
ok

4.8 अन्य संदेशों को संभालना

यदि gen_event को ईवेंट के अलावा अन्य संदेश प्राप्त करने में सक्षम होना है, तो कॉलबैक फ़ंक्शन handle_info(Info, StateName, StateData) को उन्हें संभालने के लिए लागू किया जाना चाहिए। अन्य संदेशों के उदाहरण निकास संदेश हैं, यदि gen_event अन्य प्रक्रियाओं (पर्यवेक्षक की तुलना में) और निकास संकेतों को फंसाने से जुड़ा हुआ है।

handle_info({'EXIT', Pid, Reason}, State) ->
    ..code to handle exits here..
    {ok, NewState}.

code_change पद्धति को भी लागू किया जाना चाहिए।

code_change(OldVsn, State, Extra) ->
    ..code to convert state (and more) during code change
    {ok, NewState}