问题描述
我们正在开发C ++服务器,该服务器将基于基于时间的事件进行处理.例如,如果特定用户配置了必须在特定时间处理的特定任务,则需要从数据库向C ++服务器发送事件或通知以启动任务.定时配置存储在数据库中,C ++服务器不应按一定的时间间隔轮询数据库,但应在配置的定时下从数据库通知事件.
We are developing a C++ server which will process based on time based events. For example if a particular user has configured a particular task that has to be processed at a particular time, then an event or notification needs to be sent to the C++ server from the database, to initiate the task. The timming configuration is stored in the database, and the C++ server shouldnt poll the database at an interval, but event should be notified from the database at the configured timming.
我们正在使用odatabase和odynaset库来连接和访问oracle数据库11g.
We are using odatabase and odynaset libraries to connect and access the oracle database 11g.
恳请您为上述问题提供解决方案.
Kindly request you to provide a solution for the above problem.
推荐答案
一种方法是使用 Oracle的高级队列.为此,您需要设置一个队列(和一个队列表),并编写一个PL/SQL过程来等待队列中的下一条消息.
One approach is to use Oracle's Advanced Queuing. For that purpose you need to set up a queue (and a queue table) and write a PL/SQL procedure that waits for the next message in the queue.
然后,C ++端调用PL/SQL过程,该过程将在下一个事件发生时返回.
The C++ side then calls the PL/SQL procedure, which returns when the next event has occurred.
在Oracle方面,您将需要使用 DBMS_SCHEDULER 或类似的工具创建事件,即在适当的时间将新消息插入队列.
On the Oracle side, you will need to use DBMS_SCHEDULER or a similar facility to create the event, i.e. to insert a new message into the queue at the appropriate time.
它仍然是一种轮询方法.但是,两个事件之间绝对没有活动.
It's still a polling approach. However, there's absolutely no activity between two events.
更新:
这是一些示例代码.
队列的初始设置(消息包含数字和文本值):
Initial setup of the queue (the message contains a numeric and a text value):
grant AQ_ADMINISTRATOR_ROLE to appuser;
grant EXECUTE ON DBMS_AQ to appuser;
grant EXECUTE ON DBMS_AQ to appuser;
CREATE TYPE sample_payload_type AS OBJECT
(
cmd VARCHAR2(20),
id NUMBER
);
BEGIN
DBMS_AQADM.CREATE_QUEUE_TABLE (
queue_table => 'sample_queue_table',
queue_payload_type => 'sample_payload_type',
sort_list => 'ENQ_TIME',
compatible => '10.0'
);
END;
/
BEGIN
DBMS_AQADM.CREATE_QUEUE (
queue_name => 'sample_queue',
queue_table => 'sample_queue_table'
);
DBMS_AQADM.START_QUEUE (
queue_name => 'sample_queue'
);
END;
/
包头:
create or replace package sample_queue_pkg
as
procedure get_next_msg(
i_max_wait number
,o_cmd out varchar2
,o_id out number
);
procedure put_msg(
i_cmd varchar2
,i_id number
);
end sample_queue_pkg;
/
包装体:
create or replace package body sample_queue_pkg
as
procedure get_next_msg(
i_max_wait number
,o_cmd out varchar2
,o_id out number
)
is
dequeue_options dbms_aq.dequeue_options_t;
message_properties dbms_aq.message_properties_t;
message_handle RAW(16);
message sample_payload_type;
NO_MESSAGE_RECEIVED EXCEPTION;
PRAGMA EXCEPTION_INIT(NO_MESSAGE_RECEIVED, -25228);
begin
dequeue_options.wait := i_max_wait;
DBMS_AQ.DEQUEUE (
queue_name => 'appuser.sample_queue',
dequeue_options => dequeue_options,
message_properties => message_properties,
payload => message,
msgid => message_handle
);
o_cmd := message.cmd;
o_id := message.id;
exception
when NO_MESSAGE_RECEIVED then
o_cmd := null;
o_id := null;
end get_next_msg;
procedure put_msg(
i_cmd varchar2
,i_id number
)
is
enqueue_options dbms_aq.enqueue_options_t;
message_properties dbms_aq.message_properties_t;
message_handle RAW(16);
message sample_payload_type;
message_id NUMBER;
begin
message := sample_payload_type(i_cmd, i_id);
DBMS_AQ.ENQUEUE(
queue_name => 'appuser.sample_queue',
enqueue_options => enqueue_options,
message_properties => message_properties,
payload => message,
msgid => message_handle
);
end put_msg;
end sample_queue_pkg;
/
数据库服务器可以使用以下代码发送消息:
The database server can send a message using the following code:
sample_queue_pkg.put_msg('run_task', 8234);
commit;
C ++服务器可以等待消息(并接收它们)调用存储的sample_queue_pkg.get_next_msg
.参数i_max_wait
指定等待下一条消息的最长时间(以秒为单位).您可能想要实现一个循环,等待下一条消息并对其进行处理,直到收到服务器即将退出的信号为止.
The C++ server can wait for message (and receive them) calling the stored sample_queue_pkg.get_next_msg
. The parameter i_max_wait
specifies the maximum time to wait for the next message in seconds. You probably want to implement a loop that waits for the next message and processes it until it receives a signal that the server is about to quit.
这篇关于如何获取数据库通知到C ++应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!