⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 otl4_subscriber.htm

📁 ISO_C++:C++_OTL开发文档
💻 HTM
字号:
<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
  <meta http-equiv="Content-Type"
 content="text/html; charset=iso-8859-1">
  <meta name="Author" content="Sergei Kuchin">
  <meta name="GENERATOR"
 content="Mozilla/4.77 [en] (Win95; U) [Netscape]">
  <meta name="KeyWords"
 content="OTL, Oracle, ODBC, DB2, CLI, database API, C++, Template Library">
  <title>OTL 4.0, OTL subscriber interface</title>
</head>
<body>
<center>
<h1>OTL 4.0, OTL subscriber interface<br>
</h1>
</center>
This class is Oracle 10gR2 (or higher) specific, and optional. It can
be
enabled by defining #define <a
 href="otl3_compile.htm#OTL_ORA_SUBSCRIBE">OTL_ORA_SUBSCRIBE</a>.
otl_subscriber uses the <a
 href="http://www.oracle.com/technology/oramag/oracle/06-mar/o26odpnet.html">Oracle
Database Change Notification Interface,</a> which
allows the user to get Change Notifications on database tables of
interest. The class implements basic functions like subscribe /
unsubscribe, plus pure virtual functions that need to be overriden in a
derived class. The pure virtual functions are actually a callback
mechanism for delivering change notifications back to the user. See
also example <a href="otl4_ex585.htm">585</a> for more detail.<br>
<br>
<p>Potentially, the otl_subscriber class may throw the following <a
 href="otl3_exc_list.htm#32032">OTL
defined exception</a>.
</p>
<pre><font size="+2">class otl_subscriber {<br>public:</font></pre>
<ul>
  <li> <a name="CONSTRUCTOR"></a>General constructor. It accepts a
pointer to an otl_connect object. When the constructor is called, the
otl_connect object doesn't necessarily have to be connected to the
database. It needs to be connected by the time of the first <a
 href="#SUBSCRIBE">subscribe</a>() call.<br>
  </li>
</ul>
<pre>&nbsp;&nbsp;&nbsp;&nbsp; otl_subscriber(<a
 href="otl3_connect_class.htm">otl_connect</a>* adb);<br></pre>
<ul>
  <li><a name="DESTRUCTOR"></a>Destructor. Closes all active
subscriptions automatically.<br>
  </li>
</ul>
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; virtual
~otl_subscriber();<br>
</span>
<ul>
  <li><a name="SUBSCRIBE"></a>Subscribe to Change Notifications /
activate Change Notification Interface<br>
  </li>
</ul>
<span style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp; void subscribe(const char *name=0, // optional
subscription name<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int port=0, // Application listening TCP port number to receive<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// subscription notifications (optional). When it's left<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// as defualt, the OCI layer gets the next available port.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int timeout=1800 // Subscription expiration time, seconds (optional, <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// default value is 1800 sec, 0 means "never expires").<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// When subscription expires, <a href="#OnDeRegistration">OnDeRegistration</a>()
is called.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
);</span><span style="font-family: monospace;"></span><br>
<ul>
  <li> <a name="UNSUBSCRIBE"></a>Unsubscribe / deactivate Change
Notification Interface<br>
  </li>
</ul>
<pre>&nbsp;&nbsp;&nbsp;&nbsp; void unsubscribe();</pre>
<ul>
  <li> <a name="ASSOCIATE_TABLE"></a>Associate a table / view of
interest with the current subscription. In other words, add a table /
view name to the list of tables / views which we want to get change
notifications on. There may be more than one table / view in the list<br>
  </li>
</ul>
<pre>     void associate_table(const char *table_name);<br></pre>
<ul>
  <li> <a name="ASSOCIATE_QUERY"></a>Associate a query of
interest with the current subscription. In other words, add a query to
the list of queries which we want to get change
notifications on. There may be more than one query in the list. This
function is a more generic version of the <a href="#ASSOCIATE_TABLE">associate_table</a>()
function.
When the query gets executed, all the underlying objects of the query
get identified. The query format should be as follows:<br>
&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: monospace;">SELECT
:arg&lt;int&gt; FROM...the rest of the query...<br>
    <br>
:arg&lt;int&gt;</span> is needed in order to postpone the execution of
the query, when the query gets opened in an otl_stream inside the
funcion:<br>
    <br>
&nbsp;&nbsp; &nbsp;&nbsp; <span style="font-family: monospace;">otl_stream
s(1,stmt,*db);</span><br>
&nbsp;&nbsp; &nbsp;&nbsp; ...<br>
    <span style="font-family: monospace;">&nbsp;&nbsp; s&lt;&lt;0;</span><br>
&nbsp; &nbsp; &nbsp; ...<br>
    <br>
Here's the function signature:<br>
  </li>
</ul>
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span
 style="font-family: monospace;">void associate_query(const char
*query_stmt);</span><br>
<pre><font size="+2">protected:<br></font>
</pre>
<span style="font-family: monospace;">// Pure virtual functions //
callbacks to be implemented in a derived class<br>
<br>
&nbsp; <a name="OnException"></a>virtual void OnException(<a
 href="otl3_exception_class.htm">otl_exception</a>&amp; e) = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // "On otl_exception" callback. When OTL
throws otl_exception, <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // this function is called.<br>
<br>
&nbsp; <a name="OnDeRegistration"></a>virtual void
OnDeRegistration(void) = 0;<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// "On deregistration" callback. This function gets called <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // when the current subscription
expires. Inside this function,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // repeated calls to <a
 href="#SUBSCRIBE">subscribe</a>(), <a href="#ASSOCIATE_TABLE">associate_table</a>(),
<a href="#ASSOCIATE_QUERY">associate_query</a>() <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // are allowed.<br>
</span><br>
<span style="font-family: monospace;">&nbsp; // --- DB-wide&nbsp;
events:<br>
&nbsp; <a name="OnStartup"></a>virtual void OnStartup(void) = 0;<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// "On Oracle Instance startup" callback. This function gets called <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // on the Oracle Instance startup</span><span
 style="font-family: monospace;"><br>
<br>
&nbsp; <a name="OnInstanceShutdown"></a>virtual void
OnInstanceShutdown(void) = 0;<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// "On Oracle Instance shutdown" callback. This function gets called <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // when the Oracle Instance which the
client <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // program is connected to shuts down.<br>
</span><br>
<span style="font-family: monospace;">&nbsp; <a
 name="OnAnyInstanceShutdown"></a>virtual void
OnAnyInstanceShutdown(void) = 0;<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// "On Any Oracle Instance shutdown" callback. This function gets
called <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // when Any Oracle Instance in the RAC
which the client <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // program is connected to shuts down.<br>
</span><br>
<span style="font-family: monospace;">&nbsp; // --- Table-wide events:<br>
&nbsp; <a name="OnTableInvalidate"></a>virtual void
OnTableInvalidate(text *table_name) = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // "On table invalidate" callback.
This function gets called<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // when the table gets invalidated.<br>
<br>
&nbsp; <a name="OnTableAlter"></a>virtual void OnTableAlter(text
*table_name, bool all_rows=false) = 0;<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// "On table alter" callback. This function gets called<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // when the table gets ALTERed. <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // If all_rows is true then the
whole table has been affected&nbsp; <br>
</span><br>
<span style="font-family: monospace;">&nbsp; <a name="OnTableDrop"></a>virtual
void OnTableDrop(text *table_name, </span><span
 style="font-family: monospace;">bool all_rows=false</span><span
 style="font-family: monospace;">) = 0;<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// "On table drop" callback. This function gets called<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // when the table gets DROPped.<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// If all_rows is true then the whole table has been affected&nbsp; <br>
</span><br>
<span style="font-family: monospace;">&nbsp; <a name="OnTableChange"></a>virtual
void OnTableChange(text *table_name, </span><span
 style="font-family: monospace;">bool all_rows=false</span><span
 style="font-family: monospace;">) = 0;<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// "On table change" callback. This function gets called<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // when the table gets changed:
INSERT, UPDATE, DELETE. This<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // callback only informs of the
fact that the table got<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // changed, but it doesn't specify
which row(s) got changed.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // In order to get the info on
individual rows, see "Row events".<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// If all_rows is true then the whole table has been affected&nbsp; <br>
</span><br>
<span style="font-family: monospace;">&nbsp; // --- Row events:<br>
&nbsp; <a name="OnRowInsert"></a>virtual void OnRowInsert(text
*table_name, text *row_id ) = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // "On row insert" callback. This
function gets called when a row<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // is inserted into the table. If
a query was <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // associated with the current
subscription that involves more than one<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // table, this callback will be
invoked for each table of the query.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // "row_id" is the ROWID of the
inserted row.<br>
<br>
&nbsp; <a name="OnRowUpdate"></a>virtual void OnRowUpdate(text
*table_name, text *row_id ) = 0;<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// "On row update" callback. This function gets called when a table row<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // is updated. If a query was <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // associated with the current
subscription that involves more than one<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // table, this callback will be
invoked for each table of the query.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // "row_id" is the ROWID of the
updated row.<br>
</span><br>
<span style="font-family: monospace;">&nbsp;
</span><span style="font-family: monospace;"> <a name="OnRowDelete"></a>virtual
void OnRowDelete(text *table_name, text *row_id ) = 0;<br>
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// "On row delete" callback. This function gets called when a table row<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // is updated. If a query was <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // associated with the current
subscription that involves more than one<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // table, this callback will be
invoked for each table of the query.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // "row_id" is the ROWID of the
updated row.<br>
</span><br>
<pre><font><font size="+2">public:</font></font></pre>
<ul>
  <li><a name="IS_ONLINE"></a>Check if the current subscription is
active (online). This function is convenient to call from <a
 href="#OnDeRegistration">OnDeRegistration</a>() in order to identify
whether the subscription was expired by the client or by the server
timeout.<br>
  </li>
</ul>
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; bool
is_online(void); <br>
</span>
<pre><font size="+2">}; // end of otl_subscriber</font></pre>
Oracle user id that is used to connect to the database and get&nbsp;
Change Notifications needs to have the CHANGE NOTIFICATION privilege
given by the DBA, for example:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span
 style="font-family: monospace;">grant change notification to scott;</span><br>
<br>
Active subscriptions can be viewed via the
USER_CHANGE_NOTIFICATION_REGS system view by the current Oracle user:
<pre>    select * from USER_CHANGE_NOTIFICATION_REGS<br></pre>
When a subscription gets registered, the OCI layer opens a specified
TCP/IP port, and spawns a new listener thread. Firewalls need to take
the TCP/IP port into account.<br>
<span style="text-decoration: underline;"></span>
<p></p>
<hr width="100%">
<center>
<p><a href="otl3_pl_tab.htm">Prev</a> <a href="otl3_iterators.htm">Next</a><a
 href="otl3.htm">Contents</a><a href="home.htm">Go
Home</a></p>
</center>
<p>Copyright &copy; 1996, 2008, Sergei Kuchin, email: <a
 href="mailto:skuchin@aceweb.com">skuchin@aceweb.com</a>,
<a href="mailto:skuchin@gmail.com">skuchin@gmail.com
<script language="JavaScript"><!-- hide from oldgmailsers
 var modDate = new Date(document.lastModified)
 document.write("<i> Last Updated:</i> " + (modDate.getMonth()+1) + "/" + 
                modDate.getDate() + "/" + "0"+(modDate.getYear())%100+".");
 //-->
 </script></a>.
</p>
<p><i>Permission to use, copy, modify and redistribute this document
for
any purpose is hereby granted without fee, provided that the above
copyright
notice appear in all copies.</i>
</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-5456201-1");
pageTracker._trackPageview();
</script>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -