blob: dd8e9a4b548ecce2682918de635e8603639486b5 [file] [log] [blame]
<!doctype html>
<html class="docs-version-1.1.0" lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-beta.14">
<link rel="alternate" type="application/rss+xml" href="/blog/rss.xml" title="Apache Linkis Blog RSS Feed">
<link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" title="Apache Linkis Blog Atom Feed">
<link rel="search" type="application/opensearchdescription+xml" title="Apache Linkis" href="/opensearch.xml"><title data-react-helmet="true">Analysis of engin BML | Apache Linkis</title><meta data-react-helmet="true" name="twitter:card" content="summary_large_image"><meta data-react-helmet="true" property="og:url" content="https://linkis.incubator.apache.org/docs/1.1.0/architecture/public_enhancement_services/bml/engine_bml_dissect"><meta data-react-helmet="true" name="docsearch:language" content="en"><meta data-react-helmet="true" name="docsearch:version" content="1.1.0"><meta data-react-helmet="true" name="docsearch:docusaurus_tag" content="docs-default-1.1.0"><meta data-react-helmet="true" property="og:title" content="Analysis of engin BML | Apache Linkis"><meta data-react-helmet="true" name="description" content="Introduction: This article takes the engine-related material management process as the entry point, and combines the underlying data model and source code to analyze the implementation details of the engine material management function in detail, hoping to help you better understand the BML (material library) service. Architecture."><meta data-react-helmet="true" property="og:description" content="Introduction: This article takes the engine-related material management process as the entry point, and combines the underlying data model and source code to analyze the implementation details of the engine material management function in detail, hoping to help you better understand the BML (material library) service. Architecture."><link data-react-helmet="true" rel="shortcut icon" href="/img/favicon.ico"><link data-react-helmet="true" rel="canonical" href="https://linkis.incubator.apache.org/docs/1.1.0/architecture/public_enhancement_services/bml/engine_bml_dissect"><link data-react-helmet="true" rel="alternate" href="https://linkis.incubator.apache.org/docs/1.1.0/architecture/public_enhancement_services/bml/engine_bml_dissect" hreflang="en"><link data-react-helmet="true" rel="alternate" href="https://linkis.incubator.apache.org/zh-CN/docs/1.1.0/architecture/public_enhancement_services/bml/engine_bml_dissect" hreflang="zh-CN"><link data-react-helmet="true" rel="alternate" href="https://linkis.incubator.apache.org/docs/1.1.0/architecture/public_enhancement_services/bml/engine_bml_dissect" hreflang="x-default"><link data-react-helmet="true" rel="preconnect" href="https://AE29KQB3IA-dsn.algolia.net" crossorigin="anonymous"><link rel="stylesheet" href="/assets/css/styles.92d87943.css">
<link rel="preload" href="/assets/js/runtime~main.a4c60f50.js" as="script">
<link rel="preload" href="/assets/js/main.42471b13.js" as="script">
</head>
<body>
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<div><a href="#" class="skipToContent_OuoZ">Skip to main content</a></div><nav class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Navigation bar toggle" class="navbar__toggle clean-btn" type="button" tabindex="0"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><img src="/img/logo.png" alt="Apache Linkis Logo" class="themedImage_TMUO themedImage--light_4Vu1 navbar__logo"><img src="/img/logo.png" alt="Apache Linkis Logo" class="themedImage_TMUO themedImage--dark_uzRr navbar__logo"><b class="navbar__title">Apache Linkis(Incubating)</b></a><a class="navbar__item navbar__link" href="/">Home</a><a class="navbar__item navbar__link" href="/faq/main">FAQ</a><a class="navbar__item navbar__link" href="/download/main">Download</a><a class="navbar__item navbar__link" href="/community/how-to-subscribe">Community</a><a class="navbar__item navbar__link" href="/blog">Blog</a><a class="navbar__item navbar__link" href="/team">Team</a><a class="navbar__item navbar__link" href="/user">Users</a><div class="navbar__item dropdown dropdown--hoverable"><a class="navbar__link">ASF</a><ul class="dropdown__menu"><li><a href="https://www.apache.org/" target="_blank" rel="noopener noreferrer" class="dropdown__link">Foundation</a></li><li><a href="https://www.apache.org/licenses/" target="_blank" rel="noopener noreferrer" class="dropdown__link">License</a></li><li><a href="https://www.apache.org/events/current-event" target="_blank" rel="noopener noreferrer" class="dropdown__link">Events</a></li><li><a href="https://www.apache.org/security/" target="_blank" rel="noopener noreferrer" class="dropdown__link">Security</a></li><li><a href="https://www.apache.org/foundation/sponsorship.html" target="_blank" rel="noopener noreferrer" class="dropdown__link">Sponsorship</a></li><li><a href="https://www.apache.org/foundation/policies/privacy.html" target="_blank" rel="noopener noreferrer" class="dropdown__link">Privacy</a></li><li><a href="https://www.apache.org/foundation/thanks.html" target="_blank" rel="noopener noreferrer" class="dropdown__link">Thanks</a></li></ul></div></div><div class="navbar__items navbar__items--right"><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a class="navbar__link">Doc</a><ul class="dropdown__menu"><li><a class="dropdown__link" href="/docs/1.1.3/introduction">Next(1.1.3)</a></li><li><a class="dropdown__link" href="/docs/latest/introduction">1.1.2</a></li><li><a class="dropdown__link" href="/docs/1.1.1/introduction">1.1.1</a></li><li><a class="dropdown__link" href="/docs/1.1.0/introduction">1.1.0</a></li><li><a class="dropdown__link" href="/docs/1.0.3/introduction">1.0.3</a></li><li><a class="dropdown__link" href="/docs/1.0.2/introduction">1.0.2</a></li><li><a class="dropdown__link" href="/docs/0.11.0/introduction">0.11.0</a></li><li><a class="dropdown__link" href="/versions">All Version</a></li></ul></div><a href="https://github.com/apache/incubator-linkis" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link header-github-link" aria-label="GitHub"></a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a href="#" class="navbar__link"><span><svg t="1631348384596" class="iconLanguage_EbrZ" viewBox="0 0 1024 1024" version="1.1" p-id="557" width="20" height="20"><path d="M547.797333 638.208l-104.405333-103.168 1.237333-1.28a720.170667 720.170667 0 0 0 152.490667-268.373333h120.448V183.082667h-287.744V100.906667H347.605333v82.218666H59.818667V265.386667h459.178666a648.234667 648.234667 0 0 1-130.304 219.946666 643.242667 643.242667 0 0 1-94.976-137.728H211.541333a722.048 722.048 0 0 0 122.453334 187.434667l-209.194667 206.378667 58.368 58.368 205.525333-205.525334 127.872 127.829334 31.232-83.84m231.424-208.426667h-82.218666l-184.96 493.312h82.218666l46.037334-123.306667h195.242666l46.464 123.306667h82.218667l-185.002667-493.312m-107.690666 287.744l66.56-178.005333 66.602666 178.005333z" fill="currentColor" p-id="558"></path></svg><span>English</span></span></a><ul class="dropdown__menu"><li><a href="/docs/1.1.0/architecture/public_enhancement_services/bml/engine_bml_dissect" target="_self" rel="noopener noreferrer" class="dropdown__link dropdown__link--active" style="text-transform:capitalize">English</a></li><li><a href="/zh-CN/docs/1.1.0/architecture/public_enhancement_services/bml/engine_bml_dissect" target="_self" rel="noopener noreferrer" class="dropdown__link" style="text-transform:capitalize">简体中文</a></li></ul></div><div class="searchBox_Bc3W"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div class="main-wrapper docs-wrapper docs-doc-page"><div class="docPage_lDyR"><button class="clean-btn backToTopButton_i9tI" type="button"><svg viewBox="0 0 24 24" width="28"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" fill="currentColor"></path></svg></button><aside class="docSidebarContainer_0YBq"><div class="sidebar_a3j0"><nav class="menu thin-scrollbar menu_cyFh menuWithAnnouncementBar_+O1J"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" href="/docs/1.1.0/introduction">Introduction</a></li><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" href="/docs/1.1.0/release">Version Overview</a></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">Deployment</a></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">User Guide</a></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">Engine Usage</a></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">API Docs</a></li><li class="theme-doc-sidebar-item-category menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#">Architecture</a><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" tabindex="0" href="/docs/1.1.0/architecture/overview">Overview</a></li><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" tabindex="0" href="/docs/1.1.0/architecture/difference_between_1.0_and_0.x">Difference Between 1.0 And 0.x</a></li><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" tabindex="0" href="/docs/1.1.0/architecture/job_submission_preparation_and_execution_process">Job Submission</a></li><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" tabindex="0" href="/docs/1.1.0/architecture/add_an_engine_conn">Add an EngineConn</a></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Commons</a></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Computation Governance Services</a></li><li class="theme-doc-sidebar-item-category menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#" tabindex="0">Public Enhancement Services</a><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" tabindex="0" href="/docs/1.1.0/architecture/public_enhancement_services/overview">Overview</a></li><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" tabindex="0" href="/docs/1.1.0/architecture/public_enhancement_services/public_service">Public Service</a></li><li class="theme-doc-sidebar-item-category menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#" tabindex="0">BML</a><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" tabindex="0" href="/docs/1.1.0/architecture/public_enhancement_services/bml/overview">Overview</a></li><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/docs/1.1.0/architecture/public_enhancement_services/bml/engine_bml_dissect">Analysis of engin BML</a></li></ul></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Context Service</a></li><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" tabindex="0" href="/docs/1.1.0/architecture/public_enhancement_services/datasource_manager">Data Source Management Service Architecture</a></li><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" tabindex="0" href="/docs/1.1.0/architecture/public_enhancement_services/metadata_manager">Data Source Management Service Architecture</a></li></ul></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Microservice Governance Services</a></li></ul></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">Development Doc</a></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">Upgrade Guide</a></li><li class="theme-doc-sidebar-item-category menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">Tuning And Troubleshooting</a></li></ul></nav></div></aside><main class="docMainContainer_r8cw"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_zHA2"><div class="theme-doc-version-banner alert alert--warning margin-bottom--md" role="alert"><div>This is documentation for <!-- -->Apache Linkis<!-- --> <b>1.1.0</b>, which is no longer actively maintained.</div><div class="margin-top--md">For up-to-date documentation, see the <b><a href="/docs/latest/architecture/public_enhancement_services/bml/engine_bml_dissect">latest version</a></b> (<!-- -->1.1.2<!-- -->).</div></div><div class="docItemContainer_oiyr"><article><span class="theme-doc-version-badge badge badge--secondary">Version: <!-- -->1.1.0</span><div class="tocCollapsible_aw-L theme-doc-toc-mobile tocMobile_Tx6Y"><button type="button" class="clean-btn tocCollapsibleButton_zr6a">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>Analysis of engin BML</h1></header><blockquote><p>Introduction: This article takes the engine-related material management process as the entry point, and combines the underlying data model and source code to analyze the implementation details of the engine material management function in detail, hoping to help you better understand the BML (material library) service. Architecture.</p></blockquote><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithStickyNavbar_y2LR" id="1-bml-material-library-service"></a>1. BML material library service<a class="hash-link" href="#1-bml-material-library-service" title="Direct link to heading">#</a></h2><p>The BML material library is a functional module under the PublicEnhancementService (PS) in Linkis, the public enhancement service framework.</p><p><img alt="PS-BML" src="/assets/images/PS-BML-26e164ccf574205d878a74ac12ede26f.png"></p><p>In the Linkis architecture system, the concept of <code>material</code> refers to various file data that are stored and hosted in a unified manner, including script code, resource files, third-party jars, related class libraries and configuration files required when the engine starts, as well as keytab files for security authentication, etc.</p><p>In short, any data that exists in the file state can be centrally hosted in the material library, and then downloaded and used in the respective required scenarios.</p><p>The material service is stateless and can be deployed in multiple instances to achieve high service availability. Each instance provides independent services to the outside world without interfering with each other. All material metadata and version information are shared in the database, and the underlying material data can be accessed. Store in HDFS or local (shared) file system, and support the implementation of file storage-related interfaces, extending other file storage systems, etc.</p><p>The material service provides precise permission control. For the material of the engine resource type, it can be shared and accessed by all users; for some material data containing sensitive information, only limited users can read it.</p><p>The material file adopts the method of appending, which can combine multiple versions of resource files into one large file to avoid generating too many small HDFS files. Too many small HDFS files will reduce the overall performance of HDFS.</p><p>The material service provides lifecycle management of operation tasks such as file upload, update, and download. At the same time, there are two forms of using the material service, the rest interface and the SDK. Users can choose according to their own needs.</p><p>The BML architecture diagram is as follows:</p><p><img alt="BML Architecture" src="/assets/images/bml-jiagou-e9f9a6bff360ddf889f783728abe207f.png"></p><p>For the above overview of the BML architecture, please refer to the official website document: <a href="https://linkis.apache.org/zh-CN/docs/latest/architecture/public_enhancement_services/bml" target="_blank" rel="noopener noreferrer">https://linkis.apache.org/zh-CN/docs/latest/architecture/public_enhancement_services/bml</a></p><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithStickyNavbar_y2LR" id="2-bml-material-library-service-underlying-table-model"></a>2. BML material library service underlying table model<a class="hash-link" href="#2-bml-material-library-service-underlying-table-model" title="Direct link to heading">#</a></h2><p>Before deeply understanding the process details of BML material management, it is necessary to sort out the database table model that the underlying BML material management service relies on.</p><p><img alt="BML-Model" src="/assets/images/BML-Model-403b61ca41b8c76b065e4dc58558a110.png"></p><p>Combined with Linkis&#x27; linkis_ddl.sql file and the engine material upload and update process described below, you can understand the meaning of fields in bml resources related tables and the field relationship between tables.</p><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithStickyNavbar_y2LR" id="3-usage-scenarios-of-bml-material-library-service"></a>3. Usage scenarios of BML material library service<a class="hash-link" href="#3-usage-scenarios-of-bml-material-library-service" title="Direct link to heading">#</a></h2><p>Currently in Linkis, the usage scenarios of the BML material library service include:</p><ul><li>Engine material files, including files in conf and lib required for engine startup</li><li>Stored scripts, such as the scripts in the Scripts linked by the workflow task node are stored in the BML material library</li><li>Workflow content version management in DSS</li><li>Management of resource files required when tasks are running</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithStickyNavbar_y2LR" id="4-analysis-of-engine-material-management-process"></a>4. Analysis of engine material management process<a class="hash-link" href="#4-analysis-of-engine-material-management-process" title="Direct link to heading">#</a></h2><p><code>Engine material</code> is a subset of the Linkis material concept, and its role is to provide the latest version of jar package resources and configuration files for the engine to start. This section mainly starts from the engine material management function, and analyzes the flow details of engine material data in BML.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithStickyNavbar_y2LR" id="41-engine-material-description"></a>4.1 Engine Material Description<a class="hash-link" href="#41-engine-material-description" title="Direct link to heading">#</a></h3><p>After the Linkis installation package is deployed normally, you can see all the engine material directories under the <code>LINKIS_INSTALL_HOME/lib/linkis-engineconn-plugins</code> directory. Taking the jdbc engine as an example, the structure of the engine material directory is as follows:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI shell"><pre tabindex="0" class="prism-code language-shell codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">jdbc</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── dist</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── v4</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── conf</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── conf.zip</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── lib</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── lib.zip</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── plugin</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> └── </span><span class="token number">4</span><span class="token plain"></span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> └── linkis-engineplugin-jdbc-1.1.2.jar</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>Material catalog composition:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI shell"><pre tabindex="0" class="prism-code language-shell codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">jdbc/dist/version/conf.zip</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">jdbc/dist/version/lib.zip</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block">
</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">jdbc/plugin/version number </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">remove </span><span class="token function" style="color:rgb(80, 250, 123)">v</span><span class="token plain"> and leave the number</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">/linkis-engineplugin-engine name-1.1.x.jar</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>conf.zip and lib.zip will be hosted in the material management service as engine materials. After each local modification to the material conf or lib, a new version number will be generated for the corresponding material, and the material file data will be re-uploaded. When the engine starts, the material data of the latest version number will be obtained, lib and conf will be loaded, and the java process of the engine will be started.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithStickyNavbar_y2LR" id="42-engine-material-upload-and-update-process"></a>4.2 Engine material upload and update process<a class="hash-link" href="#42-engine-material-upload-and-update-process" title="Direct link to heading">#</a></h3><p>When Linkis is deployed and started for the first time, the engine material (lib.zip and conf.zip) will be triggered to upload to the material library for the first time; when the jar package under the engine lib or the engine configuration file in conf is modified, the engine material needs to be triggered. The refresh mechanism ensures that the latest material file can be loaded when the engine is started.</p><p>Taking the current version of Linkis 1.1.x as an example, there are two ways to trigger the engine material refresh:</p><p>Restart the engineplugin service with the command <code>sh sbin/linkis-daemon.sh restart cg-engineplugin</code></p><p>Interface to refresh by requesting engine material</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI shell"><pre tabindex="0" class="prism-code language-shell codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># refresh all engine materials</span><span class="token plain"></span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">curl</span><span class="token plain"> --cookie </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;linkis_user_session_ticket_id_v1=kN4HCk555Aw04udC1Npi4ttKa3duaCOv2HLiVea4FcQ=&quot;</span><span class="token plain"> http://127.0.0.1:9001/api/rest_j/v1/engineplugin/refreshAll</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Specify the engine type and version to refresh the item</span><span class="token plain"></span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">curl</span><span class="token plain"> --cookie </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;linkis_user_session_ticket_id_v1=kN4HCk555Aw04udC1Npi4ttKa3duaCOv2HLiVea4FcQ=&quot;</span><span class="token plain"> http://127.0.0.1:9001/api/rest_j/v1/engineplugin/refresh?ecType</span><span class="token operator">=</span><span class="token plain">jdbc</span><span class="token operator">&amp;</span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">version</span><span class="token operator">=</span><span class="token number">4</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>The underlying implementation mechanism of the two types of engine material refresh methods is the same, both call the refreshAll() or refresh() method in the <code>EngineConnResourceService</code> class.</p><p>In the init() method in the default implementation class <code>DefaultEngineConnResourceService</code> of the abstract class <code>EngineConnResourceService</code>, the parameter wds.linkis.engineconn.dist.load.enable (default is true) is used to control whether to start the engineplugin service every time. Execute refreshAll(false) to check whether all engine materials have been updated (where faslse represents asynchronous acquisition of execution results).</p><blockquote><p>The init() method is modified by the annotation @PostConstruct. After the DefaultEngineConnResourceService is loaded, it is executed before the object is used, and it is executed only once.</p></blockquote><p>Manually call the interface of engineplugin/refresh, that is, manually execute the refreshAll or refresh method in the <code>EngineConnResourceService</code> class.</p><p>So the logic of engine material detection and update is in the refreshAll and refresh methods in <code>DefaultEngineConnResourceService</code>.</p><p>The core logic of refreshAll() is:</p><p>1) Obtain the installation directory of the engine through the parameter wds.linkis.engineconn.home, the default is:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">getEngineConnsHome = Configuration.getLinkisHome() + &quot;/lib/linkis-engineconn-plugins&quot;;</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>2) Traverse the engine directory</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">getEngineConnTypeListFromDisk: Array[String] = new File(getEngineConnsHome).listFiles().map(_.getName)</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>3) The <code>EngineConnBmlResourceGenerator</code> interface provides the validity detection of the underlying files or directories of each engine (version). The corresponding implementation exists in the abstract class <code>AbstractEngineConnBmlResourceGenerator</code>.</p><p>4) The <code>DefaultEngineConnBmlResourceGenerator</code> class is mainly used to generate <code>EngineConnLocalizeResource</code>. EngineConnLocalizeResource is the encapsulation of the material resource file metadata and InputStream. In the subsequent logic, EngineConnLocalizeResource will be used as a material parameter to participate in the material upload process.</p><p>The code details of the three files EngineConnBmlResourceGenerator, AbstractEngineConnBmlResourceGenerator, and DefaultEngineConnBmlResourceGenerator will not be described in detail. You can use the following UML class diagram to get a general understanding of its inheritance mechanism, and combine the specific implementation in the method to understand the function of this part.</p><p><img alt="BML" src="/assets/images/bml_uml-56c34abf348911755ed652f1467b057f.png"></p><p>Go back to the refreshAll method in the <code>DefaultEngineConnResourceService</code> class, and continue to look at the core process of the refreshTask thread:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">engineConnBmlResourceGenerator.getEngineConnTypeListFromDisk foreach { engineConnType =&gt; </span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Utils.tryCatch {</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> engineConnBmlResourceGenerator.generate(engineConnType).foreach { </span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> case (version, localize) =&gt;</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> logger.info(s&quot; Try to initialize ${engineConnType}EngineConn-$version.&quot;)</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> refresh(localize, engineConnType, version)</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> } </span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ......</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>Scan the installation directory of the engine to get a list of each engine material directory. After the legality check of each engine material directory structure is passed, you can get the corresponding <code>EngineConnLocalizeResource</code>, and then call refresh(localize: Array<!-- -->[EngineConnLocalizeResource]<!-- --> , engineConnType: String, version: String) to complete the upload of subsequent materials.</p><p>Inside the refresh() method, the main processes are as follows:</p><p>Obtain the material list data corresponding to engineConnType and version from the table <code>linkis_cg_engine_conn_plugin_bml_resources</code>, and assign it to the variable engineConnBmlResources.</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">val engineConnBmlResources = asScalaBuffer(engineConnBmlResourceDao.getAllEngineConnBmlResource(engineConnType, version))</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p><img alt="ec data" src="/assets/images/ec-data-1b00bb52948fdbf982e0627f895050bd.png"></p><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithStickyNavbar_y2LR" id="421-engine-material-upload-process"></a>4.2.1 Engine material upload process<a class="hash-link" href="#421-engine-material-upload-process" title="Direct link to heading">#</a></h4><p><strong>Engine material upload process sequence diagram</strong></p><p><img alt="Engine material upload process sequence diagram" src="/assets/images/bml-shixu-2b25e67af7b3ea021fba5d4cb608443c.png"></p><p>If there is no matching data in the table <code>linkis_cg_engine_conn_plugin_bml_resources</code>, you need to use the data in EngineConnLocalizeResource to construct an EngineConnBmlResource object and save it to the <code>linkis_cg_engine_conn_plugin_bml_resources</code> table. Before saving this data, you need to upload the material file, that is, execute <code>uploadToBml</code> (localizeResource)` method.</p><p>Inside the uploadToBml(localizeResource) method, the interface for requesting material upload is constructed by constructing bmlClient. which is:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">private val bmlClient = BmlClientFactory.createBmlClient()</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bmlClient.uploadResource(Utils.getJvmUser, localizeResource.fileName, localizeResource.getFileInputStream)</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>In BML Server, the location of the material upload interface is in the uploadResource interface method in the BmlRestfulApi class. The main process is:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">ResourceTask resourceTask = taskService.createUploadTask(files, user, properties);</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>Every time a material is uploaded, a ResourceTask will be constructed to complete the file upload process, and the execution record of the file upload task will be recorded. Inside the createUploadTask method, the main operations are as follows:</p><p>1) Generate a globally unique resource_id for the uploaded resource file, String resourceId = UUID.randomUUID().toString();</p><p>2) Build a ResourceTask record and store it in the table <code>linkis_ps_bml_resources_task</code>, as well as a series of subsequent Task state modifications.</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">ResourceTask resourceTask = ResourceTask.createUploadTask(resourceId, user, properties);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">taskDao.insert(resourceTask);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block">
</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">taskDao.updateState(resourceTask.getId(), TaskState.RUNNING.getValue(), new Date());</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>3) The actual writing of material files into the material library is completed by the upload method in the ResourceServiceImpl class. Inside the upload method, a set of byte streams corresponding to <code>List&lt;MultipartFile&gt; files</code> will be persisted to the material library file storage In the system; store the properties data of the material file in the resource record table (linkis_ps_bml_resources) and the resource version record table (linkis_ps_bml_resources_version).</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">MultipartFile p = files[0]</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">String resourceId = (String) properties.get(&quot;resourceId&quot;);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">String fileName =new String(p.getOriginalFilename().getBytes(Constant.ISO_ENCODE),</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Constant.UTF8_ENCODE);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">fileName = resourceId;</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">String path = resourceHelper.generatePath(user, fileName, properties);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// generatePath currently supports Local and HDFS paths, and the composition rules of paths are determined by LocalResourceHelper or HdfsResourceHelper</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// implementation of the generatePath method in</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">StringBuilder sb = new StringBuilder();</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">long size = resourceHelper.upload(path, user, inputStream, sb, true);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// The file size calculation and the file byte stream writing to the file are implemented by the upload method in LocalResourceHelper or HdfsResourceHelper</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Resource resource = Resource.createNewResource(resourceId, user, fileName, properties);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// Insert a record into the resource table linkis_ps_bml_resources</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">long id = resourceDao.uploadResource(resource);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// Add a new record to the resource version table linkis_ps_bml_resources_version, the version number at this time is instant.FIRST_VERSION</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// In addition to recording the metadata information of this version, the most important thing is to record the storage location of the file of this version, including the file path, starting location, and ending location.</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">String clientIp = (String) properties.get(&quot;clientIp&quot;);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ResourceVersion resourceVersion = ResourceVersion.createNewResourceVersion(</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> resourceId, path, md5String, clientIp, size, Constant.FIRST_VERSION, 1);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">versionDao.insertNewVersion(resourceVersion);</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>After the above process is successfully executed, the material data is truly completed, and then the UploadResult is returned to the client, and the status of this ResourceTask is marked as completed. Exception information.</p><p><img alt="resource-task" src="/assets/images/resource-task-647983b1bf2037641593684ba10aba67.png"></p><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithStickyNavbar_y2LR" id="422-engine-material-update-process"></a>4.2.2 Engine material update process<a class="hash-link" href="#422-engine-material-update-process" title="Direct link to heading">#</a></h4><p><strong>Engine material update process sequence diagram</strong></p><p><img alt="Engine material update process sequence diagram" src="/assets/images/engine-bml-update-shixu-1c931e45fc107845e84799838cb47706.png"></p><p>If the table <code>linkis_cg_engine_conn_plugin_bml_resources</code> matches the local material data, you need to use the data in EngineConnLocalizeResource to construct an EngineConnBmlResource object, and update the metadata information such as the version number, file size, modification time, etc. of the original material file in the <code>linkis_cg_engine_conn_plugin_bml_resources</code> table. Before updating, you need to complete the update and upload operation of the material file, that is, execute the <code>uploadToBml(localizeResource, engineConnBmlResource.getBmlResourceId)</code> method.</p><p>Inside the uploadToBml(localizeResource, resourceId) method, an interface for requesting material resource update by constructing bmlClient. which is:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">private val bmlClient = BmlClientFactory.createBmlClient()</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bmlClient.updateResource(Utils.getJvmUser, resourceId, localizeResource.fileName, localizeResource.getFileInputStream)</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>In BML Server, the interface for material update is located in the updateVersion interface method in the BmlRestfulApi class. The main process is as follows:</p><p>Complete the validity detection of resourceId, that is, check whether the incoming resourceId exists in the linkis_ps_bml_resources table. If the resourceId does not exist, an exception will be thrown to the client, and the material update operation at the interface level will fail.</p><p>Therefore, the corresponding relationship of the resource data in the tables <code>linkis_cg_engine_conn_plugin_bml_resources</code> and <code>linkis_ps_bml_resources</code> needs to be complete, otherwise an error will occur that the material file cannot be updated.</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">resourceService.checkResourceId(resourceId)</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>If resourceId exists in the linkis_ps_bml_resources table, it will continue to execute:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">StringUtils.isEmpty(versionService.getNewestVersion(resourceId))</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>The getNewestVersion method is to obtain the maximum version number of the resourceId in the table <code>linkis_ps_bml_resources_version</code>. If the maximum version corresponding to the resourceId is empty, the material will also fail to update, so the integrity of the corresponding relationship of the data here also needs to be strictly guaranteed.</p><p>After the above two checks are passed, a ResourceUpdateTask will be created to complete the final file writing and record update saving.</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">ResourceTask resourceTask = null;</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">synchronized (resourceId.intern()) {</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> resourceTask = taskService.createUpdateTask(resourceId, user, file, properties);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>Inside the createUpdateTask method, the main functions implemented are:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">// Generate a new version for the material resource</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">String lastVersion = getResourceLastVersion(resourceId);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">String newVersion = generateNewVersion(lastVersion);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// Then the construction of ResourceTask, and state maintenance</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ResourceTask resourceTask = ResourceTask.createUpdateTask(resourceId, newVersion, user, system, properties);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// The logic of material update upload is completed by the versionService.updateVersion method</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">versionService.updateVersion(resourceTask.getResourceId(), user, file, properties);</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>Inside the versionService.updateVersion method, the main functions implemented are:</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI scala"><pre tabindex="0" class="prism-code language-scala codeBlock_rtdJ thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#F8F8F2"><span class="token plain">ResourceHelper resourceHelper = ResourceHelperFactory.getResourceHelper();</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">InputStream inputStream = file.getInputStream();</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// Get the path of the resource</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">String newVersion = params.get(&quot;newVersion&quot;).toString();</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">String path = versionDao.getResourcePath(resourceId) + &quot;_&quot; + newVersion;</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// The acquisition logic of getResourcePath is to limit one from the original path, and then splice newVersion with _</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// select resource from linkis_ps_bml_resources_version WHERE resource_id = #{resourceId} limit 1</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// upload resources to hdfs or local</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">StringBuilder stringBuilder = new StringBuilder();</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">long size = resourceHelper.upload(path, user, inputStream, stringBuilder, OVER_WRITE);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">// Finally insert a new resource version record in the linkis_ps_bml_resources_version table</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ResourceVersion resourceVersion = ResourceVersion.createNewResourceVersion(resourceId, path, md5String, clientIp, size, newVersion, 1);</span></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">versionDao.insertNewVersion(resourceVersion);</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div></div><footer class="theme-doc-footer docusaurus-mt-lg"><div class="theme-doc-footer-edit-meta-row row"><div class="col"><a href="https://github.com/apache/incubator-linkis-website/edit/dev/versioned_docs/version-1.1.0/architecture/public_enhancement_services/bml/engine_bml_dissect.md" target="_blank" rel="noreferrer noopener" class="theme-edit-this-page"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_mS5F" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col lastUpdated_mt2f"></div></div></footer></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/docs/1.1.0/architecture/public_enhancement_services/bml/overview"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« <!-- -->Overview</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/docs/1.1.0/architecture/public_enhancement_services/context_service/overview"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Overview<!-- --> »</div></a></div></nav></div></div><div class="col col--3"><div class="tableOfContents_vrFS thin-scrollbar"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#1-bml-material-library-service" class="table-of-contents__link">1. BML material library service</a></li><li><a href="#2-bml-material-library-service-underlying-table-model" class="table-of-contents__link">2. BML material library service underlying table model</a></li><li><a href="#3-usage-scenarios-of-bml-material-library-service" class="table-of-contents__link">3. Usage scenarios of BML material library service</a></li><li><a href="#4-analysis-of-engine-material-management-process" class="table-of-contents__link">4. Analysis of engine material management process</a><ul><li><a href="#41-engine-material-description" class="table-of-contents__link">4.1 Engine Material Description</a></li><li><a href="#42-engine-material-upload-and-update-process" class="table-of-contents__link">4.2 Engine material upload and update process</a></li></ul></li></ul></div></div></div></div></main></div></div><footer class="footer"><div class="container"><div class="row footer__links"><div class="col footer__col"><div class="footer__title">Linkis</div><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/docs/latest/introduction">Document</a></li><li class="footer__item"><a class="footer__link-item" href="/faq/main">FAQ</a></li><li class="footer__item"><a href="https://github.com/apache/incubator-linkis/releases" target="_blank" rel="noopener noreferrer" class="footer__link-item"><span>Releases<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_wgqa"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a></li></ul></div><div class="col footer__col"><div class="footer__title">Community</div><ul class="footer__items"><li class="footer__item"><a href="https://github.com/apache/incubator-linkis" target="_blank" rel="noopener noreferrer" class="footer__link-item"><span>GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_wgqa"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a></li><li class="footer__item"><a href="https://github.com/apache/incubator-linkis/issues" target="_blank" rel="noopener noreferrer" class="footer__link-item"><span>Issue Tracker<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_wgqa"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a></li><li class="footer__item"><a href="https://github.com/apache/incubator-linkis/pulls" target="_blank" rel="noopener noreferrer" class="footer__link-item"><span>Pull Requests<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_wgqa"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a></li></ul></div><div class="col footer__col"><div class="footer__title">Subscribe Mailing List</div><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/community/how-to-subscribe">How to Subscribe</a></li><li class="footer__item"><a href="mailto:dev-subscribe@linkis.apache.org" target="_blank" rel="noopener noreferrer" class="footer__link-item"><span>Subscribe Mail<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_wgqa"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a></li><li class="footer__item"><a href="https://lists.apache.org/list.html?dev@linkis.apache.org" target="_blank" rel="noopener noreferrer" class="footer__link-item"><span>Mail Archive<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_wgqa"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a></li></ul></div></div><div class="footer__bottom text--center"><div class="footer__copyright"><div><img style="height:50px" alt="Apache Software Foundation" src="/img/incubator-logo.svg"><p style="color: #999999; padding: 0 20px 30px;font-weight:400;text-align:left">Apache Linkis is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.</p><p></p>
<p style="padding: 0 20px 30px;color: #999999;font-weight: 400;"> Copyright © 2022 The Apache Software Foundation. Licensed under the Apache License, Version 2.0. Apache Linkis, Apache Incubator, Apache, the Apache feather logo, the Apache Linkis logo and the Apache Incubator project logo are trademarks of The Apache Software Foundation.</p>
<div></div></div></div></div></div></footer></div>
<script src="/assets/js/runtime~main.a4c60f50.js"></script>
<script src="/assets/js/main.42471b13.js"></script>
</body>
</html>