2010-01-06 26 views
13

Tôi đang viết mô-đun ejabberd để lọc gói. Tôi cần lấy tên máy chủ để lấy một số cấu hình bằng cách sử dụng gen_mod:get_module_opt().Cách tạo biến toàn cục trong Erlang

Tôi có 4 chức năng quan trọng:

  1. start(Host, _Opt): Đây là một chức năng ejabberd để nạp mô-đun của tôi. Tôi nhận được nguyên tử Host tại đây
  2. filter_packet({From, To, XML}): Đây là móc lọc gói của tôi. Tôi không thể chuyển các tham số tùy chỉnh cho hàm này, vì nó là một móc trong ejabberd.
  3. get_translation(XmlData): filter_packet() gọi get_translation() trong một vòng lặp
  4. fetch_translation(XmlData): gọi đệ quy từ get_translation(). Đây là nơi tôi đang gọi gen_mod:get_module_opt() và do đó cần Host.

Câu hỏi của tôi là, làm thế nào tôi có thể mất Host từ start() và đặt nó trong một biến toàn cầu, do đó fetch_translation có thể truy cập vào nó?

Trả lời

9

"Cách dễ nhất" là tạo bảng có tên là đặt cược và đặt vào đó.

start(Host, _Opt) -> 
    ets:new(my_table, [named_table, protected, set, {keypos, 1}]), 
    ets:insert(my_table, {host, Host}), 
    ... 

fetch_translation(XmlData) -> 
    [{_, Host}] = ets:lookup(my_table, host), 
    ... 

Lưu ý rằng đây là giải pháp "chung". Ejabberd có thể cung cấp phương tiện cho những gì bạn muốn, nhưng tôi không thể giúp bạn với điều đó.

+0

Thx zed. Mô-đun biên dịch ok nhưng đưa ra lỗi 'badarg' cho 'ets: new (my_table, [named_table, protected, set, {keypos, 1}]),' – Adil

+0

Nếu bảng 'my_table' tồn tại, bạn sẽ nhận được badarg . Bạn cần phải kiểm tra xem bảng đã tồn tại chưa, hoặc bọc nó trong một khối try-catch – Zed

+0

Tôi không tạo 'my_table' ở bất kỳ đâu, ngoại trừ như đã nêu ở trên. – Adil

1

Bạn có thể bắt đầu quá trình lọc thư mới và đăng ký bằng cách sử dụng erlang:register/2, sau đó định tuyến tất cả các yêu cầu filter_packet/1 thông qua nó (một nút cổ chai tiềm năng).

-define(?SERVER, msg_filter). 

start(Host, Opt) -> 
    {ok, Pid} = spawn(?MODULE, filter_loop, [Host, Opt]), 
    register(?SERVER, Pid). 

filter_loop(Host, Opt) -> 
    receive 
     {Pid, filter_packet, {_From, _To, XML}} -> 
      Trans = get_translation(XML, Host), 
      Pid ! {?SERVER, translation, Trans}, 
      filter_loop(Host, Opt) 
    end. 

filter_packet(Pack) -> 
    ?SERVER ! {self(), filter_packet, Pack} 
    receive 
     {?SERVER, translation, Trans} -> 
      % wrap translation 
      UpdatedPacket 
    end. 
1

Giả sử bạn lọc các gói đến, sau đó Tới # jid.lserver có thể là máy chủ của bạn.

+0

Xin chào andi5. Bạn có thể giải thích "To # jid.lserver" có nghĩa là gì không. Làm thế nào tôi có thể thiết lập/nhận được nó? – Adil

+0

Đây chỉ là phỏng đoán tốt nhất, nhưng tôi cho rằng To là một biến liên kết với bản ghi loại jid (xem định nghĩa bản ghi trong src/jlib.hrl, ở dưới cùng). Để # jid.lserver có nghĩa là bạn muốn truy cập vào trường lserver của bản ghi, trong đó lserver là phiên bản thấp hơn của miền của jid. Nếu bạn gặp sự cố trong trình bao, hãy chạy lệnh rd (jid, {user, [...]}). – andi5

1

đoán cho mô tả của bạn hơn bạn đang ở trong một triển khai ejabberd đơn miền (không máy ảo),

yo có thể nhận được các miền XMPP địa phương sử dụng các Myname vĩ mô? (Xem ejabberd.hrl cho định nghĩa).

9

Nghe có vẻ là quá mức cần thiết nhưng bạn có thể xem xét việc triển khai gen_server rất cơ bản. Nó chứa một trạng thái có sẵn cho các callbacks của nó và dữ liệu có thể được giữ ở đó. Đối với trường hợp của bạn, bạn có thể viết một module tương tự như thế này:

-module(your_module_name). 

-behaviour(gen_server). 
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). 

-export([start/2, filter_loop/1]). 

start(Host, Opt) -> 
    %% start the named gen server 
    gen_server:start({local, ?MODULE}, ?MODULE, Host, []). 

filter_packet({From, To, XML}) -> 
    %% do your thing 
    gen_server:call(?MODULE, {fetch_translation, XmlData}). 

%% this will be called by gen_server:start - just pass the Host 
init(Host) -> 
    {ok, Host}. 

handle_call({fetch_translation, XmlData}, _From, Host) -> 
    %% do your thing 
    {reply, ok, Host}. 

%% you can ignore the rest - they are needed to be present 
handle_cast(_Msg, State) -> 
    {noreply, State}. 
handle_info(_Info, State) -> 
    {noreply, State}. 
code_change(_OldVsn, State, _Extra) -> 
    {ok, State}. 
1

Bạn định nghĩa biến toàn cục của bạn trên mô-đun đầu của bạn ... như dưới đây

-define (Your Variable, "your host name here"). 

ví dụ.

-define (RelayHost, "smtp.gmail.com"). 

và bạn có thể sử dụng biến Toàn cầu này trong tất cả các phương pháp trong mô-đun của mình.

io:fwrite("Global Value ~p", [?RelayHost]). 

-AjAy

+4

-define không xác định biến. Nó định nghĩa các hằng số biên dịch thời gian. –

+0

Sau đó, làm thế nào để xác định biến toàn cầu? thanks –

+0

Không thể xác định biến toàn cầu. –