chapter 04-04

進階模式的資料的存取 (內部模組)

內部模組使用進階模式可以加快存取資料的速度.

分成二種情況說明.

一是對於通用情況下 :

基本模式 (_by_path 結尾的函式) 內部的大致處理步驟 :
A01.  根據路徑找到資料在記憶體的位置.
A02.  使用進階模式函式存取記憶體內的資料.

假設使用基本模式對同一筆資料做取得狀態和數值的處理, 如下 :
01.  取得資料的狀態 (mcm_config_get_entry_self_status_by_path).
02.  取得資料的數值 (mcm_config_get_entry_by_path).

改用進階模式做相同的處理 :
01.  根據路徑找到資料在記憶體的位置.
02.  取得資料狀態 (進階模式).
03.  取得資料數值 (進階模式).

使用基本模式的函式呼叫為 : (01)[A01][A02] -> (02)[A01][A02].
使用進階模式的函式呼叫為 : (01)[A01] -> (02)[A2] -> (03)[A02].
進階模式比基本模式少了一次搜尋 ([A01]) 的動做.

二是對於動態多筆資料情況下 :

mcm_daemon 的資料存放方式是使用紅黑樹 (RB-Tree) 加上雙向鏈結串列 (Double-Link-List), 對於動態多筆資料可以先找到第一筆, 之後使用鏈結串列存取下一筆資料, 減少搜尋 ([A01]) 的次數.

假設使用基本模式對每一筆資料做取得狀態和數值的處理, 如下 :
01.  迴圈處理 (每次增加資料的 index).
02.  使用 index 組合路徑.
03.  取得資料的狀態 (mcm_config_get_entry_self_status_by_path).
04.  取得資料的數值 (mcm_config_get_entry_by_path).
05.  迴圈處理 (結尾).

改用進階模式做相同的處理 :
01.  根據路徑找到第一筆資料在記憶體的位置.
02.  迴圈處理 (每次將資料指標往下一筆資料移動).
03.  取得資料狀態 (進階模式).
04.  取得資料數值 (進階模式).
05.  迴圈處理 (結尾).

假設處理三筆資料 :
使用基本模式的函式呼叫為 :
[i = 1] : (02) -> (03)[A01][A02] -> (04)[A01][A02].
[i = 2] : (02) -> (03)[A01][A02] -> (04)[A01][A02].
[i = 3] : (02) -> (03)[A01][A02] -> (04)[A01][A02].
使用進階模式的函式呼叫為 :
(01)[A01]
[p = head] : (02) -> (03)[A02] -> (04)[A02].
[p = next] : (02) -> (03)[A02] -> (04)[A02].
[p = next] : (02) -> (03)[A02] -> (04)[A02].
進階模式比基本模式減少多次路徑組合和搜尋 ([A01]) 的動作.


變數格式的說明

使用的資料模型範例, 參考 #02-02#.


[struct mcm_service_session_t *this_session]
請求端的連線資訊. [詳細]


[char *mask_path]
取得 group 的資訊的路徑. [詳細]


[char *mix_path]
存取多個 entry 的路徑. [詳細]


[char *full_path]
存取的目標 entry 或 member 的路徑. [詳細]


[char *ik_path]
找到 group 內的目標 entry, 使用在增加 entry 時, 指定要插入在哪個 entry 之前. [詳細]


[struct mcm_config_model_group_t *group_info]
紀錄 group 的資訊的結構, 也就是在 #02-01# 中資料模型中的資料, 如 $(name), $(type), $(max), $(save) 等等. 資料串列的結構成員 :
struct mcm_config_model_group_t *
parent_model_group
指向 parent
struct mcm_config_model_group_t *
next_model_group
指向下一個
例如 :
以 02-02 的資料模型為例 :
device
  system
  vap
    extra
    station
  limit
  client

device :
parent_model_group = NULL
next_model_group = NULL

system :
parent_model_group = device
next_model_group = vap

vap :
parent_model_group = device
next_model_group = limit

extra :
parent_model_group = vap
next_model_group = station

station :
parent_model_group = vap
next_model_group = NULL

limit :
parent_model_group = device
next_model_group = client

client :
parent_model_group = device
next_model_group = NULL



[struct mcm_config_model_member_t *member_info]
紀錄 member 的資訊的結構, 也就是在 #02-01# 中資料模型中的資料, 如 $(name), $(type), $(default) 等等. 資料串列的結構成員 :
struct mcm_config_model_member_t *
next_model_member
指向下一個
例如 :
以 02-02 的資料模型的 system 為例 :
system 內部的 member 有 :
date
ip_addr
uptime
loading

date :
next_model_member = ip_addr

ip_addr :
next_model_member = uptime

uptime :
next_model_member = loading

loading :
next_model_member = NULL



[struct mcm_config_store_t *store_info]
紀錄資料的狀態和數值的結構.
資料串列的結構成員 :
struct mcm_config_store_t *
parent_store
指向 parent
struct mcm_config_store_t *
prev_store
指向上一筆
struct mcm_config_store_t *
next_store
指向下一筆
例如 :
目前有以下資料 :
device.vap.#8 ssid:open-1 channel:10
device.vap.#8.extra hidden:1 tx_power:9
device.vap.#8.station.#5 mac_addr:00:aa:bb:cc:dd:05 rule:15
device.vap.#8.station.#7 mac_addr:00:aa:bb:cc:dd:07 rule:17
device.vap.#15 ssid:radius-2 channel:44
device.vap.#15.extra hidden:0 tx_power:10
device.vap.#15.station.#30 mac_addr:00:aa:bb:cc:dd:ee rule:5
device.vap.#15.station.#33 mac_addr:00:aa:bb:cc:dd:ff rule:6
device.vap.#15.station.#41 mac_addr:00:aa:bb:cc:dd:41 rule:7

device.vap.#8.extra :
parent_store = device.vap.#8
prev_store = NULL
next_store = NULL

device.vap.#8.station.#5 :
parent_store = device.vap.#8
prev_store = NULL
next_store = device.vap.#8.station.#7

device.vap.#8.station.#7 :
parent_store = device.vap.#8
prev_store = device.vap.#8.station.#5
next_store = NULL

device.vap.#15.extra :
parent_store = device.vap.#15
prev_store = NULL
next_store = NULL

device.vap.#15.station.#30 :
parent_store = device.vap.#15
prev_store = NULL
next_store = device.vap.#15.station.#33

device.vap.#15.station.#33 :
parent_store = device.vap.#15
prev_store = device.vap.#15.station.#30
next_store = device.vap.#15.station.#41

device.vap.#15.station.#41 :
parent_store = device.vap.#15
prev_store = device.vap.#15.station.#33
next_store = NULL

device.vap.#8 :
parent_store = device
prev_store = NULL
next_store = device.vap.#15

device.vap.#15 :
parent_store = device
prev_store = device.vap.#8
next_store = NULL

device :
parent_store = NULL
prev_store = NULL
next_store = NULL



路徑處理函式

進階模式需要先使用路徑 (mask_path, mix_path, full_path) 找到資料在記憶體的位址 (member_info, group_info, store_info), 之後使用這些資料結構存取資料.


mcm_config_find_group_by_mask
處理 mask_path 類型的路徑, 找到目標的 group_info.
參數 說明
struct mcm_service_session_t *
this_session
請求端的連線資訊
char *
mask_path
目標的路徑 [詳細]
struct mcm_config_model_group_t **
self_model_group_buf
紀錄 group_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
回傳 說明
>= MCM_RCODE_PASS 成功
 < MCM_RCODE_PASS 錯誤

範例 :
外部程式部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "mcm_lib/mcm_lulib/mcm_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    char *path1;
    struct mcm_lulib_lib_t self_lulib;

    self_lulib.socket_path = "@mintcm";
    self_lulib.call_from = MCM_CFROM_USER;
    self_lulib.session_permission = MCM_SPERMISSION_RO;
    self_lulib.session_stack_size = 0;
    if(mcm_lulib_init(&self_lulib) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_init() fail");
        goto FREE_01;
    }

    // 呼叫內部模組.
    path1 = "mcm_module_mask_path_test";
    DMSG("[run] %s", path1);
    if(mcm_lulib_run(&self_lulib, path1, NULL, 0, NULL, NULL) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_run(%s) fail", path1);
        goto FREE_02;
    }

FREE_02:
    mcm_lulib_exit(&self_lulib);
FREE_01:
    return 0;
}

內部模組部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_control.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_debug.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "../mcm_service_handle_define.h"
#include "../mcm_config_handle_extern.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int mcm_module_mask_path_test(
    struct mcm_service_session_t *this_session)
{
    int fret = MCM_RCODE_MODULE_INTERNAL_ERROR;
    char *path1;
    struct mcm_config_model_group_t *tmp_group;

    // 範例 : 尋找 device.system
    path1 = "device.system";
    DMSG("[mask_path] %s", path1);
    if(mcm_config_find_group_by_mask(this_session, path1, &tmp_group) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_group_by_mask(%s) fail", path1);
        goto FREE_01;
    }

    // 範例 : 尋找 device.vap.*
    path1 = "device.vap.*";
    DMSG("[mask_path] %s", path1);
    if(mcm_config_find_group_by_mask(this_session, path1, &tmp_group) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_group_by_mask(%s) fail", path1);
        goto FREE_01;
    }

    // 範例 : 尋找 device.vap.*.station.*
    path1 = "device.vap.*.station.*";
    DMSG("[mask_path] %s", path1);
    if(mcm_config_find_group_by_mask(this_session, path1, &tmp_group) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_group_by_mask(%s) fail", path1);
        goto FREE_01;
    }

    fret = MCM_RCODE_PASS;
FREE_01:
    return fret;
}

mcm_config_find_entry_by_mix
處理 mix_path 類型的路徑, 找到目標的 group_info, store_info.
參數 說明
struct mcm_service_session_t *
this_session
請求端的連線資訊
char *
mix_path
目標的路徑 [詳細]
[index / key 模式]
struct mcm_config_model_group_t **
self_model_group_buf
紀錄 group_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
struct mcm_config_store_t **
self_store_list_head_buf
紀錄 store_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
mcm_daemon 的資料存放方式是使用紅黑樹加上雙向鏈結串列, 這邊是回傳雙向鏈結串列的頭端節點
struct mcm_config_store_t **
self_store_list_tail_buf
紀錄 store_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
mcm_daemon 的資料存放方式是使用紅黑樹加上雙向鏈結串列, 這邊是回傳雙向鏈結串列的尾端節點
struct mcm_config_store_t **
self_store_tree_buf
紀錄 store_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
mcm_daemon 的資料存放方式是使用紅黑樹加上雙向鏈結串列, 這邊是回傳紅黑樹的樹根節點
struct MCM_DTYPE_EK_TD *
self_count_buf
紀錄資料筆數的緩衝 [詳細]
可為 NULL, 表示不記錄
struct mcm_config_store_t **
parent_store_buf
紀錄 parent 的 store_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
回傳 說明
>= MCM_RCODE_PASS 成功
 < MCM_RCODE_PASS
(MCM_RCODE_CONFIG_NOT_FIND_STORE)
錯誤, 目標 entry 不存在
 < MCM_RCODE_PASS
(other)
錯誤, 其他錯誤

範例 :
外部程式部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "mcm_lib/mcm_lulib/mcm_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    char *path1;
    struct mcm_lulib_lib_t self_lulib;

    self_lulib.socket_path = "@mintcm";
    self_lulib.call_from = MCM_CFROM_USER;
    self_lulib.session_permission = MCM_SPERMISSION_RO;
    self_lulib.session_stack_size = 0;
    if(mcm_lulib_init(&self_lulib) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_init() fail");
        goto FREE_01;
    }

    // 呼叫內部模組.
    path1 = "mcm_module_mix_path_test";
    DMSG("[run] %s", path1);
    if(mcm_lulib_run(&self_lulib, path1, NULL, 0, NULL, NULL) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_run(%s) fail", path1);
        goto FREE_02;
    }

FREE_02:
    mcm_lulib_exit(&self_lulib);
FREE_01:
    return 0;
}

內部模組部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_control.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_debug.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "../mcm_service_handle_define.h"
#include "../mcm_config_handle_extern.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int mcm_module_mix_path_test(
    struct mcm_service_session_t *this_session)
{
    int fret = MCM_RCODE_MODULE_INTERNAL_ERROR;
    char *path1;
    struct mcm_config_model_group_t *tmp_group;
    struct mcm_config_store_t *tmp_store_list_head, *tmp_store_list_tail, *tmp_store_tree,
        *parent_store;
    MCM_DTYPE_EK_TD tmp_store_count;

    // 範例 : 尋找 device
    path1 = "device";
    DMSG("[mix_path] %s", path1);
    if(mcm_config_find_entry_by_mix(this_session, path1, &tmp_group, &tmp_store_list_head,
                                    &tmp_store_list_tail, &tmp_store_count, &tmp_store_tree,
                                    NULL) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_mix(%s) fail", path1);
        goto FREE_01;
    }

    // 範例 : 尋找 device.vap.*
    path1 = "device.vap.*";
    DMSG("[mix_path] %s", path1);
    if(mcm_config_find_entry_by_mix(this_session, path1, &tmp_group, &tmp_store_list_head,
                                    &tmp_store_list_tail, &tmp_store_count, &tmp_store_tree,
                                    &parent_store) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_mix(%s) fail", path1);
        goto FREE_01;
    }

    // 範例 : 尋找 device.vap.@1.station.*
    path1 = "device.vap.@1.station.*";
    DMSG("[mix_path] %s", path1);
    if(mcm_config_find_entry_by_mix(this_session, path1, &tmp_group, &tmp_store_list_head,
                                    &tmp_store_list_tail, &tmp_store_count, &tmp_store_tree,
                                    &parent_store) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_mix(%s) fail", path1);
        goto FREE_01;
    }

    fret = MCM_RCODE_PASS;
FREE_01:
    return fret;
}

mcm_config_find_alone_by_full
處理 full_path (member) 類型的路徑, 找到目標的 group_info, member_info, store_info.
參數 說明
struct mcm_service_session_t *
this_session
請求端的連線資訊
char *
full_path
目標的路徑 [詳細]
[member 格式][index / key 模式]
struct mcm_config_model_group_t **
self_model_group_buf
紀錄 group_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
struct mcm_config_model_member_t **
self_model_member_buf
紀錄 member_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
struct mcm_config_store_t **
self_store_buf
紀錄 store_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
回傳 說明
>= MCM_RCODE_PASS 成功
 < MCM_RCODE_PASS
(MCM_RCODE_CONFIG_NOT_FIND_STORE)
錯誤, 目標 entry 不存在
 < MCM_RCODE_PASS
(other)
錯誤, 其他錯誤

範例 :
外部程式部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "mcm_lib/mcm_lulib/mcm_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    char *path1;
    struct mcm_lulib_lib_t self_lulib;

    self_lulib.socket_path = "@mintcm";
    self_lulib.call_from = MCM_CFROM_USER;
    self_lulib.session_permission = MCM_SPERMISSION_RO;
    self_lulib.session_stack_size = 0;
    if(mcm_lulib_init(&self_lulib) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_init() fail");
        goto FREE_01;
    }

    // 呼叫內部模組.
    path1 = "mcm_module_alone_full_path";
    DMSG("[run] %s", path1);
    if(mcm_lulib_run(&self_lulib, path1, NULL, 0, NULL, NULL) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_run(%s) fail", path1);
        goto FREE_02;
    }

FREE_02:
    mcm_lulib_exit(&self_lulib);
FREE_01:
    return 0;
}

內部模組部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_control.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_debug.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "../mcm_service_handle_define.h"
#include "../mcm_config_handle_extern.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int mcm_module_alone_full_path(
    struct mcm_service_session_t *this_session)
{
    int fret = MCM_RCODE_MODULE_INTERNAL_ERROR;
    char *path1;
    struct mcm_config_model_group_t *tmp_group;
    struct mcm_config_model_member_t *tmp_member;
    struct mcm_config_store_t *tmp_store;

    // 範例 : 尋找 device.descript
    path1 = "device.descript";
    DMSG("[alone_full_path] %s", path1);
    if(mcm_config_find_alone_by_full(this_session, path1, &tmp_group, &tmp_member, &tmp_store)
                                     < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_alone_by_full(%s) fail", path1);
        goto FREE_01;
    }

    // 範例 : 尋找 device.vap.@1.channel
    path1 = "device.vap.@1.channel";
    DMSG("[alone_full_path] %s", path1);
    if(mcm_config_find_alone_by_full(this_session, path1, &tmp_group, &tmp_member, &tmp_store)
                                     < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_alone_by_full(%s) fail", path1);
        goto FREE_01;
    }

    // 範例 : 尋找 device.vap.#15.station.@1.rule
    path1 = "device.vap.#15.station.@1.rule";
    DMSG("[alone_full_path] %s", path1);
    if(mcm_config_find_alone_by_full(this_session, path1, &tmp_group, &tmp_member, &tmp_store)
                                     < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_alone_by_full(%s) fail", path1);
        goto FREE_01;
    }

    fret = MCM_RCODE_PASS;
FREE_01:
    return fret;
}

mcm_config_find_entry_by_full
處理 full_path (entry) 類型的路徑, 找到目標的 group_info, store_info.
參數 說明
struct mcm_service_session_t *
this_session
請求端的連線資訊
char *
full_path
目標的路徑 [詳細]
[entry 格式][index / key 模式]
struct mcm_config_model_group_t **
self_model_group_buf
紀錄 group_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
struct mcm_config_store_t **
self_store_buf
紀錄 store_info 的緩衝 [詳細]
可為 NULL, 表示不記錄
回傳 說明
>= MCM_RCODE_PASS 成功
 < MCM_RCODE_PASS
(MCM_RCODE_CONFIG_NOT_FIND_STORE)
錯誤, 目標 entry 不存在
 < MCM_RCODE_PASS
(other)
錯誤, 其他錯誤

範例 :
外部程式部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "mcm_lib/mcm_lulib/mcm_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    char *path1;
    struct mcm_lulib_lib_t self_lulib;

    self_lulib.socket_path = "@mintcm";
    self_lulib.call_from = MCM_CFROM_USER;
    self_lulib.session_permission = MCM_SPERMISSION_RO;
    self_lulib.session_stack_size = 0;
    if(mcm_lulib_init(&self_lulib) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_init() fail");
        goto FREE_01;
    }

    // 呼叫內部模組.
    path1 = "mcm_module_entry_full_path";
    DMSG("[run] %s", path1);
    if(mcm_lulib_run(&self_lulib, path1, NULL, 0, NULL, NULL) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_run(%s) fail", path1);
        goto FREE_02;
    }

FREE_02:
    mcm_lulib_exit(&self_lulib);
FREE_01:
    return 0;
}

內部模組部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_control.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_debug.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "../mcm_service_handle_define.h"
#include "../mcm_config_handle_extern.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int mcm_module_entry_full_path(
    struct mcm_service_session_t *this_session)
{
    int fret = MCM_RCODE_MODULE_INTERNAL_ERROR;
    char *path1;
    struct mcm_config_model_group_t *tmp_group;
    struct mcm_config_store_t *tmp_store;

    // 範例 : 尋找 device
    path1 = "device";
    DMSG("[entry_full_path] %s", path1);
    if(mcm_config_find_entry_by_full(this_session, path1, &tmp_group, &tmp_store)
                                     < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_full(%s) fail", path1);
        goto FREE_01;
    }

    // 範例 : 尋找 device.vap.#23
    path1 = "device.vap.#23";
    DMSG("[entry_full_path] %s", path1);
    if(mcm_config_find_entry_by_full(this_session, path1, &tmp_group, &tmp_store)
                                     < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_full(%s) fail", path1);
        goto FREE_01;
    }

    // 範例 : 尋找 device.vap.@2.station.#30
    path1 = "device.vap.@2.station.#30";
    DMSG("[entry_full_path] %s", path1);
    if(mcm_config_find_entry_by_full(this_session, path1, &tmp_group, &tmp_store)
                                     < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_full(%s) fail", path1);
        goto FREE_01;
    }

    fret = MCM_RCODE_PASS;
FREE_01:
    return fret;
}

mcm_config_find_entry_by_ik
使用目標的 group_info 和 parent_store, 找到目標的 store_info.
在增加 entry 時如果要指定插入到目標 entry 之前, 可以使用此函式找到目標 entry.
參數 說明
struct mcm_service_session_t *
this_session
請求端的連線資訊
struct mcm_config_model_group_t *
this_model_group
目標的 group_info [詳細]
struct mcm_config_store_t *
parent_store
目標的 parent 的 store_info [詳細]
char *
ik_path
目標的路徑 [詳細]
[index 模式] / [key 模式]
struct mcm_config_store_t **
self_store_buf
紀錄 store_info 的緩衝 [詳細]
回傳 說明
>= MCM_RCODE_PASS 成功
 < MCM_RCODE_PASS
(MCM_RCODE_CONFIG_NOT_FIND_STORE)
錯誤, 目標 entry 不存在
 < MCM_RCODE_PASS
(other)
錯誤, 其他錯誤

注意事項 :
01.  如果 ik_path 是 NULL 或 "" (空字串), self_store_buf 會得到 NULL, 並回傳 MCM_RCODE_PASS.
02.  如果 ik_path 有值但是目標不存在, self_store_buf 會得到 NULL, 並回傳 MCM_RCODE_CONFIG_NOT_FIND_STORE.

範例 :
外部程式部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "mcm_lib/mcm_lulib/mcm_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    char *path1;
    struct mcm_lulib_lib_t self_lulib;

    self_lulib.socket_path = "@mintcm";
    self_lulib.call_from = MCM_CFROM_USER;
    self_lulib.session_permission = MCM_SPERMISSION_RO;
    self_lulib.session_stack_size = 0;
    if(mcm_lulib_init(&self_lulib) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_init() fail");
        goto FREE_01;
    }

    // 呼叫內部模組.
    path1 = "mcm_module_entry_ik_path";
    DMSG("[run] %s", path1);
    if(mcm_lulib_run(&self_lulib, path1, NULL, 0, NULL, NULL) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_run(%s) fail", path1);
        goto FREE_02;
    }

FREE_02:
    mcm_lulib_exit(&self_lulib);
FREE_01:
    return 0;
}

內部模組部分

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_control.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_debug.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "../mcm_service_handle_define.h"
#include "../mcm_config_handle_extern.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int mcm_module_entry_ik_path(
    struct mcm_service_session_t *this_session)
{
    int fret = MCM_RCODE_MODULE_INTERNAL_ERROR;
    char *path1;
    struct mcm_config_model_group_t *tmp_group;
    struct mcm_config_store_t *parent_store, *tmp_store;

    // 01. 範例 : 尋找 device.vap.#23

    // 01a. 先尋找 device.vap.*
    path1 = "device.vap.*";
    DMSG("[mix_path] %s", path1);
    if(mcm_config_find_entry_by_mix(this_session, path1, &tmp_group, NULL, NULL, NULL, NULL,
                                    &parent_store) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_mix(%s) fail", path1);
        goto FREE_01;
    }

    // 01b. 找到 "#23".
    path1 = "#23";
    DMSG("[ik_path] %s", path1);
    if(mcm_config_find_entry_by_ik(this_session, tmp_group, parent_store, path1, &tmp_store)
                                   < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_ik(%s) fail", path1);
        goto FREE_01;
    }

    // 02. 範例 : 尋找 device.vap.@2.station.#33, 接著尋找 station.#30

    // 02a. 先尋找 device.vap.@2.station.#30
    path1 = "device.vap.@2.station.#30";
    DMSG("[entry_full_path] %s", path1);
    if(mcm_config_find_entry_by_full(this_session, path1, &tmp_group, &tmp_store)
                                     < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_full(%s) fail", path1);
        goto FREE_01;
    }

    // 02b. 指向 device.vap.@2
    parent_store = tmp_store->parent_store;

    // 02c. 找到 station.#30
    path1 = "#30";
    DMSG("[ik_path] %s", path1);
    if(mcm_config_find_entry_by_ik(this_session, tmp_group, parent_store, path1, &tmp_store)
                                   < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_find_entry_by_ik(%s) fail", path1);
        goto FREE_01;
    }

    fret = MCM_RCODE_PASS;
FREE_01:
    return fret;
}