Erlang 21 - 12. Appup Cookbook

12 अप्पुक रसोई की किताब




erlang

12 अप्पुक रसोई की किताब

इस खंड में रनटाइम में किए गए अपग्रेड / डाउनग्रेड के विशिष्ट मामलों के लिए .appup फ़ाइलों के उदाहरण शामिल हैं।

12.1 एक कार्यात्मक मॉड्यूल बदलना

जब एक कार्यात्मक मॉड्यूल को बदल दिया गया है, उदाहरण के लिए, यदि कोई नया फ़ंक्शन जोड़ा गया है या बग को ठीक किया गया है, तो सरल कोड प्रतिस्थापन पर्याप्त है, उदाहरण के लिए:

{"2",
 [{"1", [{load_module, m}]}],
 [{"1", [{load_module, m}]}]
}.

12.2 एक निवास मॉड्यूल बदलना

ओटीपी डिजाइन सिद्धांतों के अनुसार लागू की गई प्रणाली में, सिस्टम प्रक्रियाओं और विशेष प्रक्रियाओं को छोड़कर सभी प्रक्रियाएं व्यवहार supervisor , gen_server , gen_fsm , gen_statem या gen_event । ये STDLIB एप्लिकेशन से संबंधित हैं और सामान्य रूप से अपग्रेड / डाउनग्रेडिंग के लिए एमुलेटर रीस्टार्ट की आवश्यकता होती है।

इस प्रकार ओटीपी special processes के मामले में निवास के मॉड्यूल को बदलने के लिए कोई समर्थन प्रदान नहीं करता special processes

12.3 कॉलबैक मॉड्यूल बदलना

कॉलबैक मॉड्यूल एक कार्यात्मक मॉड्यूल है, और कोड एक्सटेंशन के लिए सरल कोड प्रतिस्थापन पर्याप्त है।

उदाहरण: जब ch3 कोई फ़ंक्शन जोड़ते हैं, जैसा कि Release Handling में उदाहरण में वर्णित है, ch_app.appup इस प्रकार है:

{"2",
 [{"1", [{load_module, ch3}]}],
 [{"1", [{load_module, ch3}]}]
}.

ओटीपी भी व्यवहार प्रक्रियाओं की आंतरिक स्थिति को बदलने का समर्थन करता है, आंतरिक स्थिति को Changing Internal State देखें।

12.4 आंतरिक स्थिति बदलना

इस मामले में, सरल कोड प्रतिस्थापन पर्याप्त नहीं है। कॉलबैक मॉड्यूल के नए संस्करण पर स्विच करने से पहले कॉलबैक फ़ंक्शन code_change का उपयोग करके प्रक्रिया को स्पष्ट रूप से अपने राज्य को बदलना होगा। इस प्रकार, सिंक्रनाइज़ कोड प्रतिस्थापन का उपयोग किया जाता है।

उदाहरण: gen_server Behaviour से gen_server Behaviour ch3 पर विचार करें। आंतरिक स्थिति एक शब्द है जो उपलब्ध चैनलों का प्रतिनिधित्व करती है। मान लें कि आप एक काउंटर N जोड़ना चाहते हैं, जो अब तक alloc अनुरोधों की संख्या का ट्रैक रखता है। इसका मतलब है कि प्रारूप को {Chs,N} बदलना चाहिए।

.appup फ़ाइल निम्नानुसार दिख सकती है:

{"2",
 [{"1", [{update, ch3, {advanced, []}}]}],
 [{"1", [{update, ch3, {advanced, []}}]}]
}.

update निर्देश का तीसरा तत्व एक टपल {advanced,Extra} , जो कहता है कि प्रभावित प्रक्रियाओं को मॉड्यूल के नए संस्करण को लोड करने से पहले एक राज्य परिवर्तन करना है। यह कॉलबैक फ़ंक्शन code_change कॉल करने वाली प्रक्रियाओं ( gen_server(3) में gen_server(3) मैनुअल पेज देखें) द्वारा किया जाता है। शब्द Extra , इस मामले में [] को कार्य के रूप में पारित किया जाता है:

-module(ch3).
...
-export([code_change/3]).
...
code_change({down, _Vsn}, {Chs, N}, _Extra) ->
    {ok, Chs};
code_change(_Vsn, Chs, _Extra) ->
    {ok, {Chs, 0}}.

पहला तर्क यह है कि अगर डाउनग्रेड है, या Vsn तो Vsn है। Vsn शब्द को मॉड्यूल के 'मूल' संस्करण से लिया गया है, अर्थात, जिस संस्करण से आप अपग्रेड कर रहे हैं, या जिसे अपग्रेड करना है।

संस्करण को मॉड्यूल विशेषता vsn द्वारा परिभाषित किया गया है, यदि कोई हो। ch3 में ऐसी कोई विशेषता नहीं है, इसलिए इस मामले में संस्करण बीम फ़ाइल का चेकसम (एक विशाल पूर्णांक) है, एक निर्बाध मूल्य है, जिसे अनदेखा किया जाता है।

ch3 अन्य कॉलबैक फ़ंक्शन को भी संशोधित किया जाना चाहिए और शायद एक नया इंटरफ़ेस फ़ंक्शन जोड़ा जाना चाहिए, लेकिन यह यहां नहीं दिखाया गया है।

12.5 मॉड्यूल निर्भरता

मान लें कि एक मॉड्यूल इंटरफ़ेस फ़ंक्शन को जोड़कर बढ़ाया जाता है, उदाहरण के लिए Release Handling , जहां एक फ़ंक्शन available/0 को ch3 जोड़ा जाता है।

यदि इस फ़ंक्शन में एक कॉल जोड़ा जाता है, तो मॉड्यूल m1 में कहें, रिलीज़ अपग्रेड के दौरान एक रनटाइम त्रुटि हो सकती है यदि m1 का नया संस्करण पहले लोड किया गया है और ch3:available/0 का नया संस्करण लोड होने से पहले ch3:available/0 कॉल करता है।

इस प्रकार, ch3 को m1 से पहले अपग्रेड केस में लोड किया जाना चाहिए, और डाउनग्रेड केस में। m1 को ch3 पर निर्भर माना जाता है। एक निर्देशन हैंडलिंग निर्देश में, यह DepMods तत्व द्वारा व्यक्त किया गया है:

{load_module, Module, DepMods}
{update, Module, {advanced, Extra}, DepMods}

DepMods मॉड्यूल की एक सूची है, जिस पर Module निर्भर है।

उदाहरण: अनुप्रयोग myapp में मॉड्यूल m1 "1" से "2" में अपग्रेड करते समय ch3 पर निर्भर है, या "2" से "1" में अपग्रेड हो रहा है:

myapp.appup:

{"2",
 [{"1", [{load_module, m1, [ch3]}]}],
 [{"1", [{load_module, m1, [ch3]}]}]
}.

ch_app.appup:

{"2",
 [{"1", [{load_module, ch3}]}],
 [{"1", [{load_module, ch3}]}]
}.

यदि इसके बजाय m1 और ch3 एक ही अनुप्रयोग से संबंधित हैं, तो .appup फ़ाइल निम्नानुसार देख सकती है:

{"2",
 [{"1",
   [{load_module, ch3},
    {load_module, m1, [ch3]}]}],
 [{"1",
   [{load_module, ch3},
    {load_module, m1, [ch3]}]}]
}.

m1 अपग्रेड करते समय ch3 पर भी निर्भर है। systools अप और डाउनग्रेडिंग के बीच के अंतर को जानता है और एक सही relup , जहां अपग्रेड करते समय ch3 को m1 से पहले लोड किया जाता है, लेकिन डाउनग्रेड करते समय m1 को ch3 से पहले लोड किया जाता है।

12.6 एक विशेष प्रक्रिया के लिए कोड बदलना

इस मामले में, सरल कोड प्रतिस्थापन पर्याप्त नहीं है। जब एक विशेष प्रक्रिया के लिए निवास मॉड्यूल का एक नया संस्करण लोड किया जाता है, तो प्रक्रिया को नए कोड पर स्विच करने के लिए अपने लूप फ़ंक्शन के लिए पूरी तरह से योग्य कॉल करना चाहिए। इस प्रकार, सिंक्रनाइज़ कोड प्रतिस्थापन का उपयोग किया जाना चाहिए।

ध्यान दें

उपयोगकर्ता-निर्धारित निवास मॉड्यूल (नों) का नाम विशेष प्रक्रिया के लिए बाल विनिर्देश के Modules भाग में सूचीबद्ध होना चाहिए। अन्यथा रिलीज़ हैंडलर प्रक्रिया नहीं ढूँढ सकता।

उदाहरण: sys and proc_lib में उदाहरण ch4 पर विचार करें। जब एक पर्यवेक्षक द्वारा शुरू किया जाता है, तो बच्चा विनिर्देश निम्नानुसार देख सकता है:

{ch4, {ch4, start_link, []},
 permanent, brutal_kill, worker, [ch4]}

यदि ch4 अनुप्रयोग sp_app का हिस्सा है और इस अनुप्रयोग के संस्करण "1" से "2" में अपग्रेड करते समय मॉड्यूल का एक नया संस्करण लोड किया जाना है, तो sp_app.appup निम्नानुसार देख सकता है:

{"2",
 [{"1", [{update, ch4, {advanced, []}}]}],
 [{"1", [{update, ch4, {advanced, []}}]}]
}.

update निर्देश में टपल {advanced,Extra} होना चाहिए। निर्देश कॉलबैक फ़ंक्शन system_code_change/4 विशेष प्रक्रिया को कॉल करता है, एक फ़ंक्शन जिसे उपयोगकर्ता को लागू करना चाहिए। Extra शब्द, इस मामले में [] को system_code_change/4 रूप में पारित किया जाता है:

-module(ch4).
...
-export([system_code_change/4]).
...

system_code_change(Chs, _Module, _OldVsn, _Extra) ->
    {ok, Chs}.
  • पहला तर्क आंतरिक स्थिति है, फ़ंक्शन sys:handle_system_msg(Request, From, Parent, Module, Deb, State) से पास किया गया है sys:handle_system_msg(Request, From, Parent, Module, Deb, State) , और विशेष प्रक्रिया द्वारा बुलाया जाता है जब एक सिस्टम संदेश प्राप्त होता है। ch4 , आंतरिक स्थिति उपलब्ध चैनल Chs का समुच्चय है।
  • दूसरा तर्क मॉड्यूल ( ch4 ) का नाम है।
  • तीसरा तर्क है Vsn या {down,Vsn} , जैसा कि gen_server:code_change/3 लिए वर्णित है gen_server:code_change/3 Changing Internal State में gen_server:code_change/3

इस मामले में, सभी तर्क लेकिन पहले नजरअंदाज कर दिए जाते हैं और फ़ंक्शन केवल आंतरिक स्थिति को फिर से लौटाता है। यह पर्याप्त है यदि कोड केवल बढ़ाया गया है। यदि इसके बजाय आंतरिक स्थिति को बदल दिया जाता है (आंतरिक स्थिति में परिवर्तन के समान), तो यह इस फ़ंक्शन में किया जाता है और {ok,Chs2} वापस आ जाता है।

12.7 पर्यवेक्षक बदलना

पर्यवेक्षक व्यवहार आंतरिक स्थिति को बदलने का समर्थन करता है, अर्थात, पुनरारंभ की रणनीति और अधिकतम पुनरारंभ आवृत्ति गुणों को बदल रहा है, साथ ही मौजूदा बाल विनिर्देशों को भी बदल रहा है।

बाल प्रक्रियाओं को जोड़ा या हटाया जा सकता है, लेकिन यह स्वचालित रूप से नियंत्रित नहीं किया जाता है। निर्देश .appup फ़ाइल द्वारा दिए जाने चाहिए।

बदलते गुण

चूंकि पर्यवेक्षक को अपनी आंतरिक स्थिति को बदलना है, इसलिए सिंक्रनाइज़ कोड प्रतिस्थापन की आवश्यकता है। हालाँकि, एक विशेष update निर्देश का उपयोग किया जाना चाहिए।

सबसे पहले, कॉलबैक मॉड्यूल का नया संस्करण लोड किया जाना चाहिए, दोनों उन्नयन और डाउनग्रेड के मामले में। फिर init/1 के नए रिटर्न मान की जाँच की जा सकती है और आंतरिक स्थिति को उसी के अनुसार बदला जा सकता है।

निम्नलिखित upgrade अनुदेश पर्यवेक्षकों के लिए उपयोग किया जाता है:

{update, Module, supervisor}

उदाहरण: ch_sup ( Supervisor Behaviour ) के पुनरारंभ की रणनीति को बदलने के लिए one_for_one से one_for_all , कॉलबैक फ़ंक्शन init/1 को ch_sup.erl में ch_sup.erl :

-module(ch_sup).
...

init(_Args) ->
    {ok, {#{strategy => one_for_all, ...}, ...}}.

फ़ाइल ch_app.appup :

{"2",
 [{"1", [{update, ch_sup, supervisor}]}],
 [{"1", [{update, ch_sup, supervisor}]}]
}.

बदलते बाल विनिर्देश

निर्देश, और इस प्रकार .appup फ़ाइल, जब एक मौजूदा बच्चे के विनिर्देशन को बदलते हैं, तो पहले के वर्णित गुणों को बदलते समय जैसा होता है:

{"2",
 [{"1", [{update, ch_sup, supervisor}]}],
 [{"1", [{update, ch_sup, supervisor}]}]
}.

परिवर्तन मौजूदा बाल प्रक्रियाओं को प्रभावित नहीं करते हैं। उदाहरण के लिए, प्रारंभ फ़ंक्शन को बदलना केवल निर्दिष्ट करता है कि बच्चे की प्रक्रिया को कैसे फिर से शुरू किया जाना है, अगर बाद में आवश्यक हो।

बाल विनिर्देश की आईडी को नहीं बदला जा सकता है।

चाइल्ड स्पेसिफिकेशन के Modules फील्ड को बदलने से रिलीज़ हैंडलिंग प्रोसेस पर ही असर पड़ सकता है, क्योंकि इस फील्ड का इस्तेमाल यह पहचानने के लिए किया जाता है कि सिंक्रोनाइज़्ड कोड रिप्लेसमेंट करते समय कौन से प्रोसेस प्रभावित होते हैं।

बाल प्रक्रियाओं को जोड़ना और हटाना

जैसा कि पहले कहा गया है, बदलते बाल विनिर्देश मौजूदा बाल प्रक्रियाओं को प्रभावित नहीं करते हैं। नई बाल विशिष्टताओं को स्वचालित रूप से जोड़ा जाता है, लेकिन हटाया नहीं जाता है। बाल प्रक्रियाएं स्वचालित रूप से शुरू या समाप्त नहीं होती हैं, इसे apply निर्देशों का उपयोग करके किया जाना चाहिए।

उदाहरण: मान लें कि ch_app में "1" से "2" को अपग्रेड करते समय एक नया चाइल्ड प्रोसेस m1 जोड़ा जाना है। इसका मतलब है कि m1 2 को "2" से "1" में अपग्रेड करते समय हटा दिया जाना है:

{"2",
 [{"1",
   [{update, ch_sup, supervisor},
    {apply, {supervisor, restart_child, [ch_sup, m1]}}
   ]}],
 [{"1",
   [{apply, {supervisor, terminate_child, [ch_sup, m1]}},
    {apply, {supervisor, delete_child, [ch_sup, m1]}},
    {update, ch_sup, supervisor}
   ]}]
}.

निर्देशों का क्रम महत्वपूर्ण है।

काम करने के लिए स्क्रिप्ट के लिए पर्यवेक्षक को ch_sup के रूप में पंजीकृत होना चाहिए। यदि पर्यवेक्षक पंजीकृत नहीं है, तो इसे सीधे स्क्रिप्ट से एक्सेस नहीं किया जा सकता है। एक सहायता फ़ंक्शन के बजाय, जो पर्यवेक्षक की supervisor:restart_child पाता है और पर्यवेक्षक को कॉल supervisor:restart_child , और इसी तरह, लिखा जाना चाहिए। यह फ़ंक्शन तब स्क्रिप्ट से apply निर्देश का उपयोग करके बुलाया जाना है।

यदि मॉड्यूल m1 को ch_app संस्करण "2" में ch_app , तो इसे अपग्रेड करते समय लोड किया जाना चाहिए और डाउनग्रेड करते समय हटा दिया जाना चाहिए:

{"2",
 [{"1",
   [{add_module, m1},
    {update, ch_sup, supervisor},
    {apply, {supervisor, restart_child, [ch_sup, m1]}}
   ]}],
 [{"1",
   [{apply, {supervisor, terminate_child, [ch_sup, m1]}},
    {apply, {supervisor, delete_child, [ch_sup, m1]}},
    {update, ch_sup, supervisor},
    {delete_module, m1}
   ]}]
}.

जैसा कि पहले कहा गया है, निर्देशों का क्रम महत्वपूर्ण है। अपग्रेड करते समय, m1 को लोड किया जाना चाहिए, और नई चाइल्ड प्रक्रिया शुरू होने से पहले सुपरवाइज़र चाइल्ड स्पेसिफिकेशन बदल गया। अपग्रेड करते समय, बच्चे के विनिर्देशन को बदलने और मॉड्यूल को हटाने से पहले बच्चे की प्रक्रिया को समाप्त किया जाना चाहिए।

12.8 किसी मॉड्यूल को जोड़ना या हटाना

उदाहरण: ch_app एक नया कार्यात्मक मॉड्यूल m जोड़ा गया है:

{"2",
 [{"1", [{add_module, m}]}],
 [{"1", [{delete_module, m}]}]

12.9 किसी प्रक्रिया को शुरू या समाप्त करना

ओटीपी डिज़ाइन सिद्धांतों के अनुसार संरचित प्रणाली में, कोई भी प्रक्रिया एक पर्यवेक्षक से संबंधित एक बच्चे की प्रक्रिया होगी, पर्यवेक्षक को बदलने में Adding and Deleting Child Processes को Adding and Deleting Child Processes देखें।

12.10 किसी एप्लिकेशन को जोड़ना या निकालना

एप्लिकेशन जोड़ते या हटाते समय, कोई .appup फ़ाइल की आवश्यकता नहीं होती है। relup जनरेट करते समय .rel फाइलें तुलना की add_application और add_application और remove_application निर्देश अपने आप जुड़ जाते हैं।

12.11 एक अनुप्रयोग को पुनरारंभ करना

किसी अनुप्रयोग को पुनरारंभ करना तब उपयोगी होता है जब प्रक्रियाओं को फिर से शुरू किए बिना एक बदलाव बहुत जटिल होता है, उदाहरण के लिए, यदि पर्यवेक्षक पदानुक्रम का पुनर्गठन किया गया है।

उदाहरण: जब ch_sup चाइल्ड m1 ch_sup , जैसा कि पर्यवेक्षक को बदलने में Adding and Deleting Child Processes को Adding and Deleting Child Processes , पर्यवेक्षक को अपडेट करने का एक विकल्प पूरे आवेदन को पुनः आरंभ करना है:

{"2",
 [{"1", [{restart_application, ch_app}]}],
 [{"1", [{restart_application, ch_app}]}]
}.

12.12 एक एप्लीकेशन स्पेसिफिकेशन बदलना

रिलीज़ को स्थापित करते समय, relup स्क्रिप्ट का मूल्यांकन करने से पहले एप्लिकेशन विनिर्देश स्वचालित रूप से अपडेट हो जाते हैं। इस प्रकार, कोई निर्देश .appup फ़ाइल में आवश्यक नहीं हैं:

{"2",
 [{"1", []}],
 [{"1", []}]
}.

12.13 एप्लिकेशन कॉन्फ़िगरेशन बदलना

.app फ़ाइल में env कुंजी को अपडेट करके एक एप्लिकेशन कॉन्फ़िगरेशन को बदलना एक एप्लिकेशन विनिर्देश को बदलने का एक उदाहरण है, पिछले अनुभाग को देखें।

वैकल्पिक रूप से, एप्लिकेशन कॉन्फ़िगरेशन पैरामीटर को sys.config में जोड़ा या अपडेट किया जा सकता है।

12.14 परिवर्तन शामिल अनुप्रयोग

एप्लिकेशन को जोड़ने, हटाने और पुनः आरंभ करने के लिए रिलीज़ हैंडलिंग निर्देश केवल प्राथमिक अनुप्रयोगों पर लागू होते हैं। शामिल अनुप्रयोगों के लिए कोई संगत निर्देश नहीं हैं। हालाँकि, चूंकि एक सम्मिलित अनुप्रयोग वास्तव में एक सर्वोच्च पर्यवेक्षक के साथ एक पर्यवेक्षण का पेड़ है, जिसमें शामिल अनुप्रयोग में पर्यवेक्षक के लिए एक बच्चे की प्रक्रिया के रूप में शुरू किया गया था, एक relup फ़ाइल मैन्युअल रूप से बनाई जा सकती है।

उदाहरण: मान लें कि एक रिलीज़ है जिसमें एक एप्लिकेशन prim_app , जिसके पर्यवेक्षण ट्री में एक पर्यवेक्षक prim_sup है।

रिलीज के एक नए संस्करण में, आवेदन ch_app को ch_app में शामिल किया prim_app । यही है, इसके सर्वोच्च पर्यवेक्षक ch_sup को बाल प्रक्रिया के रूप में ch_sup पर शुरू किया prim_sup

वर्कफ़्लो इस प्रकार है:

चरण 1) prim_sup के लिए कोड संपादित करें:

init(...) ->
    {ok, {...supervisor flags...,
          [...,
           {ch_sup, {ch_sup,start_link,[]},
            permanent,infinity,supervisor,[ch_sup]},
           ...]}}.

चरण 2) prim_app लिए .app फ़ाइल संपादित करें:

{application, prim_app,
 [...,
  {vsn, "2"},
  ...,
  {included_applications, [ch_app]},
  ...
 ]}.

चरण 3) .rel सहित एक नई .rel फ़ाइल बनाएँ:

{release,
 ...,
 [...,
  {prim_app, "2"},
  {ch_app, "1"}]}.

शामिल आवेदन दो तरह से शुरू किया जा सकता है। इसका वर्णन अगले दो खंडों में किया गया है।

एप्लिकेशन को पुनरारंभ करें

चरण 4 क) सम्मिलित एप्लिकेशन को शुरू करने का एक तरीका पूरे prim_app एप्लिकेशन को पुनरारंभ करना है। आम तौर पर, restart_application लिए .appup फ़ाइल में restart_application निर्देश का उपयोग किया जाएगा।

हालाँकि, यदि यह किया जाता है और एक relup फ़ाइल जेनरेट होती है, तो न केवल इसमें prim_app को फिर से शुरू करने (यानी हटाने और जोड़ने) के लिए निर्देश होंगे, इसमें ch_app शुरू करने के लिए निर्देश भी ch_app (और इसे रोकने के लिए, डाउनग्रेड होने की स्थिति में) । ऐसा इसलिए है क्योंकि ch_app नई .rel फ़ाइल में शामिल है, लेकिन पुराने में नहीं।

इसके बजाय, एक सही relup फ़ाइल मैन्युअल रूप से बनाई जा सकती है, या तो खरोंच से या उत्पन्न संस्करण को संपादित करके। आवेदन को लोड / अनलोड करने के लिए ch_app शुरू करने / रोकने के ch_app को प्रतिस्थापित किया जाता है:

{"B",
 [{"A",
   [],
   [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
    {load_object_code,{prim_app,"2",[prim_app,prim_sup]}},
    point_of_no_return,
    {apply,{application,stop,[prim_app]}},
    {remove,{prim_app,brutal_purge,brutal_purge}},
    {remove,{prim_sup,brutal_purge,brutal_purge}},
    {purge,[prim_app,prim_sup]},
    {load,{prim_app,brutal_purge,brutal_purge}},
    {load,{prim_sup,brutal_purge,brutal_purge}},
    {load,{ch_sup,brutal_purge,brutal_purge}},
    {load,{ch3,brutal_purge,brutal_purge}},
    {apply,{application,load,[ch_app]}},
    {apply,{application,start,[prim_app,permanent]}}]}],
 [{"A",
   [],
   [{load_object_code,{prim_app,"1",[prim_app,prim_sup]}},
    point_of_no_return,
    {apply,{application,stop,[prim_app]}},
    {apply,{application,unload,[ch_app]}},
    {remove,{ch_sup,brutal_purge,brutal_purge}},
    {remove,{ch3,brutal_purge,brutal_purge}},
    {purge,[ch_sup,ch3]},
    {remove,{prim_app,brutal_purge,brutal_purge}},
    {remove,{prim_sup,brutal_purge,brutal_purge}},
    {purge,[prim_app,prim_sup]},
    {load,{prim_app,brutal_purge,brutal_purge}},
    {load,{prim_sup,brutal_purge,brutal_purge}},
    {apply,{application,start,[prim_app,permanent]}}]}]
}.

पर्यवेक्षक परिवर्तन

चरण 4 बी) शामिल एप्लिकेशन को शुरू करने (या डाउनग्रेड के मामले में रोकना ) का एक अन्य तरीका सभी ch_app कोड और उसके एप्लिकेशन विनिर्देश को लोड / अनलोड करने के निर्देश के साथ prim_sup / से बच्चे की प्रक्रियाओं को जोड़ने और हटाने के लिए निर्देश का संयोजन है।

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

{"B",
 [{"A",
   [],
   [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
    {load_object_code,{prim_app,"2",[prim_sup]}},
    point_of_no_return,
    {load,{ch_sup,brutal_purge,brutal_purge}},
    {load,{ch3,brutal_purge,brutal_purge}},
    {apply,{application,load,[ch_app]}},
    {suspend,[prim_sup]},
    {load,{prim_sup,brutal_purge,brutal_purge}},
    {code_change,up,[{prim_sup,[]}]},
    {resume,[prim_sup]},
    {apply,{supervisor,restart_child,[prim_sup,ch_sup]}}]}],
 [{"A",
   [],
   [{load_object_code,{prim_app,"1",[prim_sup]}},
    point_of_no_return,
    {apply,{supervisor,terminate_child,[prim_sup,ch_sup]}},
    {apply,{supervisor,delete_child,[prim_sup,ch_sup]}},
    {suspend,[prim_sup]},
    {load,{prim_sup,brutal_purge,brutal_purge}},
    {code_change,down,[{prim_sup,[]}]},
    {resume,[prim_sup]},
    {remove,{ch_sup,brutal_purge,brutal_purge}},
    {remove,{ch3,brutal_purge,brutal_purge}},
    {purge,[ch_sup,ch3]},
    {apply,{application,unload,[ch_app]}}]}]
}.

12.15 नॉन-एरलांग कोड बदलना

उदाहरण के लिए, अर्लंग की तुलना में किसी अन्य प्रोग्रामिंग भाषा में लिखे गए प्रोग्राम के लिए कोड बदलना, एक पोर्ट प्रोग्राम है, जो अनुप्रयोग-निर्भर है और OTP इसके लिए कोई विशेष समर्थन प्रदान नहीं करता है।

उदाहरण: जब पोर्ट प्रोग्राम के लिए कोड बदलते हैं, तो मान लें कि पोर्ट को नियंत्रित करने वाली Erlang प्रक्रिया एक gen_server portc और यह कि कॉलबैक फ़ंक्शन init/1 में पोर्ट को खोला गया है:

init(...) ->
    ...,
    PortPrg = filename:join(code:priv_dir(App), "portc"),
    Port = open_port({spawn,PortPrg}, [...]),
    ...,
    {ok, #state{port=Port, ...}}.

यदि पोर्ट प्रोग्राम को अपडेट किया जाना है, तो gen_server के लिए कोड को code_change फ़ंक्शन के साथ बढ़ाया जा सकता है, जो पुराने पोर्ट को बंद कर देता है और एक नया पोर्ट खोलता है। (यदि आवश्यक हो, तो gen_server पहले डेटा का अनुरोध कर सकता है जिसे पोर्ट प्रोग्राम से बचाया जाना चाहिए और इस डेटा को नए पोर्ट में पास करना चाहिए):

code_change(_OldVsn, State, port) ->
    State#state.port ! close,
    receive
        {Port,close} ->
            true
    end,
    PortPrg = filename:join(code:priv_dir(App), "portc"),
    Port = open_port({spawn,PortPrg}, [...]),
    {ok, #state{port=Port, ...}}.

एप्लिकेशन संस्करण संख्या को .app फ़ाइल में अपडेट करें और एक .appup फ़ाइल लिखें:

["2",
 [{"1", [{update, portc, {advanced,port}}]}],
 [{"1", [{update, portc, {advanced,port}}]}]
].

सुनिश्चित करें कि priv निर्देशिका, जहाँ C प्रोग्राम स्थित है, नए रिलीज़ पैकेज में शामिल है:

1> systools:make_tar("my_release", [{dirs,[priv]}]).
...

12.16 एमुलेटर रिस्टार्ट और अपग्रेड

दो उन्नयन निर्देश एमुलेटर को पुनः आरंभ करते हैं:

  • restart_new_emulator

    ईआरटीएस, कर्नेल, एसटीडीआईएलबी या एसएएसएल के अपग्रेड होने पर इरादा। यह स्वचालित रूप से जोड़ दिया जाता है जब relup फ़ाइल systools:make_relup/3,4 द्वारा systools:make_relup/3,4 । इसे अन्य सभी अपग्रेड निर्देशों से पहले निष्पादित किया जाता है। इस निर्देश के बारे में अधिक जानकारी के लिए, Release Handling Instructions में पुनरारंभ_new_emulator (निम्न-स्तर) देखें।

  • restart_emulator

    अन्य सभी उन्नयन निर्देशों को निष्पादित करने के बाद एमुलेटर की पुनरारंभ की आवश्यकता होने पर उपयोग किया जाता है। इस निर्देश के बारे में अधिक जानकारी के लिए, Release Handling Instructions में पुनः आरंभ करें_मुलेटर (निम्न-स्तर) देखें।

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

{"B",
 [{"A",
   [],
   [restart_emulator]}],
 [{"A",
   [],
   [restart_emulator]}]
}.

इस स्थिति में, रिलीज़ पैकिंग और रिलीज़ पैकेज के स्वत: पैकिंग और अनपैकिंग के साथ रिलीज़ हैंडलर फ्रेमवर्क, .appup फ़ाइलों को निर्दिष्ट किए बिना उपयोग किया जा सकता है।

12.17 एम ओटीपी आर 15 से एम्यूलेटर अपग्रेड

OTP R15 से, एक एम्यूलेटर अपग्रेड को लोडिंग कोड से पहले कोर एप्लिकेशन (कर्नेल, एसटीडीआईएलआईबी, और एसएएसएल) के नए संस्करणों के साथ एमुलेटर को पुनरारंभ करके और अन्य एप्लिकेशन के लिए अपग्रेड इंस्ट्रक्शन चलाकर किया जाता है। इस काम के लिए, OTP R15 या बाद से अपग्रेड करने की रिलीज़ शामिल होनी चाहिए।

उस स्थिति के लिए जहां से अपग्रेड करने के लिए रिलीज़ में पहले वाला एमुलेटर संस्करण शामिल है, systools:make_relup एक बैकवर्ड कम्पेटिबल रिलअप फ़ाइल बनाता है। इसका मतलब है कि एमुलेटर के पुनरारंभ होने से पहले सभी अपग्रेड निर्देशों को निष्पादित किया जाता है। नया एप्लिकेशन कोड इसलिए पुराने एमुलेटर में लोड किया गया है। यदि नया कोड नए एमुलेटर के साथ संकलित किया गया है, तो ऐसे मामले हो सकते हैं जहां बीम प्रारूप बदल गया है और बीम फाइलें लोड नहीं की जा सकती हैं। इस समस्या को दूर करने के लिए, पुराने एमुलेटर के साथ नया कोड संकलित करें।