DBA Data[Home] [Help]

PACKAGE: SYS.DBMS_ALERT

Source


1 package dbms_alert is
2 
3   ------------
4   --  OVERVIEW
5   --
6   --  This package provides support for the asynchronous (as opposed to
7   --  polling) notification of database events.  By appropriate use of
8   --  this package and database triggers, an application can cause itself
9   --  to be notified whenever values of interest in the database are
10   --  changed.
11   --
12   --  For example, suppose a graphics tool is displaying a graph of some
13   --  data from a database table.  The graphics tool can, after reading and
14   --  graphing the data, wait on a database alert ('dbms_alert.waitone')
15   --  covering the data just read.  The tool will automatically wake up when
16   --  the data is changed by any other user.  All that is required is that a
17   --  trigger be placed on the database table which then performs a signal
18   --  ('dbms_alert.signal') whenever the trigger is fired.
19   --
20   --  Alerts are transaction based.  This means that the waiting session
21   --  does not get alerted until the transaction signalling the alert commits.
22   --
23   --  There can be any number of concurrent signallers of a given alert, and
24   --  there can be any number of concurrent waiters on a given alert.
25   --
26   --  A waiting application will be blocked in the database and cannot do
27   --  any other work.
28   --
29   --  Most of the calls in the package, except for 'signal', do commits.
30   --
31 
32   -----------
33   --  EXAMPLE
34   --
35   --  Suppose the application wishes to graph average salaries, say by
36   --  department, for all employees.  So the application needs to know
37   --  whenever 'emp' is changed.  The application would look like this:
38   --
39   --      dbms_alert.register('emp_table_alert');
40   --    readagain:
41   --      <read the emp table and graph it>
42   --      dbms_alert.waitone('emp_table_alert', :message, :status);
43   --      if status = 0 then goto readagain; else <error condition>
44   --
45   --  The 'emp' table would have a trigger similar to the following:
46   --
47   --    create trigger emptrig after insert or update or delete on emp
48   --    begin
49   --      dbms_alert.signal('emp_table_alert', 'message_text');
50   --    end;
51   --
52   --  When the application is no longer interested in the alert, it does
53   --    dbms_alert.remove('emp_table_alert');
54   --  This is important since it reduces the amount of work required by
55   --  the alert signaller.
56   --
57   --  If a session exits (or dies) while there exist registered alerts,
58   --  they will eventually be cleaned up by future users of this package.
59   --
60   --  The above example guarantees that the application will always see
61   --  the latest data, although it may not see every intermediate value.
62 
63 
64   --------------
65   --  VARIATIONS
66   --
67   --  The application can register for multiple events and can then wait for
68   --  any of them to occur using the 'waitany' call.
69   --
70   --  An application can also supply an optional 'timeout' parameter to the
71   --  'waitone' or 'waitany' calls.  A 'timeout' of 0 returns immediately
72   --  if there is no pending alert.
73   --
74   --  The signalling session can optionally pass a message which will be
75   --  received by the waiting session.
76   --
77   --  Alerts may be signalled more often than the corresponding application
78   --  'wait' calls.  In such cases the older alerts are discaded.  The
79   --  application always gets the latest alert (based on transaction commit
80   --  times).
81   --
82   --  If the application does not require transaction based alerts, then the
83   --  'dbms_pipe' package may provide a useful alternative
84   --
85   --  If the transaction is rolled back after the call to 'dbms_alert.signal',
86   --  no alert will occur.
87   --
88   --  It is possible to receive an alert, read the data, and find that no
89   --  data has changed.  This is because the data changed after the *prior*
90   --  alert, but before the data was read for that *prior* alert.
91 
92 
93   --------------------------
94   --  IMPLEMENTATION DETAILS
95   --
96   --  In most cases the implementation is event-driven, i.e., there are no
97   --  polling loops.  There are two cases where polling loops can occur:
98   --
99   --    1) Parallel mode.  If your database is running parallel mode then
100   --       a polling loop is required to check for alerts from another
101   --       instance.  The polling loop defaults to one second and is settable
102   --       by the 'set_defaults' call.
103   --    2) Waitany call.  If you use the 'waitany' call, and a signalling
104   --       session does a signal but does not commit within one second of the
105   --       signal, then a polling loop is required so that this uncommitted
106   --       alert does not camouflage other alerts.  The polling loop begins
107   --       at a one second interval and exponentially backs off to 30 second
108   --       intervals.
109   --
110   --  This package uses the dbms_lock package (for synchronization between
111   --  signallers and waiters) and the dbms_pipe package (for asynchronous
112   --  event dispatching).
113 
114   -------------------------------------------------------
115   --  INTERACTION WITH MULTI-THREADED AND PARALLEL SERVER
116   --
117   --  When running with the parallel server AND multi-threaded server, a
118   --  multi-threaded (dispatcher) "shared server" will be bound to a
119   --  session (and therefore not shareable) during the time a session has
120   --  any alerts "registered", OR from the time a session "signals" an
121   --  alert until the time the session commits.  Therefore, applications
122   --  which register for alerts should use "dedicated servers" rather than
123   --  connecting through the dispatcher (to a "shared server") since
124   --  registration typically lasts for a long time, and applications which
125   --  cause "signals" should have relatively short transactions so as not
126   --  to tie up "shared servers" for too long.
127 
128   ------------
129   --  SECURITY
130   --
131   --  Security on this package may be controlled by granting execute on
132   --  this package to just those users or roles that you trust.  You may
133   --  wish to write a cover package on top of this one which restricts
134   --  the alertnames used.  Execute privilege on this cover package can
135   --  then be granted rather than on this package.
136 
137 
138   -------------
139   --  RESOURCES
140   --
141   --  This package uses one database pipe and two locks for each alert a
142   --  session has registered.
143 
144 
145   ---------------------
146   --  SPECIAL CONSTANTS
147   --
148   maxwait constant integer :=  86400000; -- 1000 days
149   --  The maximum time to wait for an alert (essentially forever).
150 
151 
152   ----------------------------
153   --  PROCEDURES AND FUNCTIONS
154   --
155   procedure set_defaults(sensitivity in number);
156   --  Set various defaults for this package.
157   --  Input parameters:
158   --    sensitivity
159   --      In case a polling loop is required (see "Implementation Details"
160   --      above), this is the time to sleep between polls.  Deafult is 5 sec.
161   --
162   procedure register(name in varchar2, cleanup in boolean default TRUE);
163   --  Register interest in an alert.  A session may register interest in
164   --    an unlimited number of alerts.  Alerts should be de-registered when
165   --    the session no longer has any interest (see 'remove').  This call
166   --    always performs a 'commit'.
167   --  Input parameters:
168   --    name
169   --      The name of the alert in which this session is interested.
170   --      WARNING:  Alert names beginning with 'ORA$' are reserved for use for
171   --      products provided by Oracle Corporation.  Name must be 30 bytes
172   --      or less.  The name is case-insensitive.
173   --    cleanup
174   --      This specifies whether we should perform cleanup of any orphaned
175   --      pipes that may exist and are used by the dbms_alert package. This
176   --      cleanup is only performed on the first call to "register" for each
177   --      package instantiation. The default for the parameter is TRUE.
178   --
179   procedure remove(name in varchar2);
180   --  Remove alert from registration list.  Do this when the session is no
181   --    longer interested in an alert.  Removing an alert is important
182   --    since it will reduce the amount of work done by signalers of the alert.
183   --    If a session dies without removing the alert, that alert will
184   --    eventually (but not immediately) be cleaned up.  This call always
185   --    performs a commit.
186   --  Input parameters:
187   --    name
188   --      The name of the alert to be removed from registration list. The
189   --      name is case-insensitive.
190   --
191   procedure removeall;
192   --  Remove all alerts for this session from registration list.  Do this
193   --    when the session is no longer interested in any alerts.  Removing
194   --    alerts is important since it will reduce the amount of work done
195   --    by signalers of the alert.  If a session dies without removing all
196   --    of its alerts, the alerts will eventually (but not immediately)
197   --    be cleaned up.  This call always performs a commit.
198   --
199   --    This procedure is called automatically upon first reference to this
200   --    package during a session.  Therefore no alerts from prior sessions
201   --    which may have terminated abnormally can affect this session.
202   procedure waitany(name out varchar2,
203                     message out varchar2,
204                     status out integer,
205                     timeout in number default maxwait);
206   --  Wait for an alert to occur for any of the alerts for which this
207   --    session is registered.  Although probably unusual, the same session
208   --    that waits for the alert may also first signal the alert.  In this
209   --    case remember to commit after the signal and prior to the wait.
210   --    Otherwise a lock request exception (status 4) will occur.  This
211   --    call always performs a commit.
212   --  Input parameters:
213   --    timeout
214   --      The maximum time to wait for an alert.  If no alert occurs before
215   --      timeout seconds, then this call will return with status of 1.
216   --  Output parameters:
217   --    name
218   --      The name of the alert that occurred, in uppercase.
219   --    message
220   --      The message associated with the alert.  This is the message
221   --      provided by the 'signal' call.  Note that if multiple signals
222   --      on this alert occurred before the waitany call, then the message
223   --      will correspond to the most recent signal call.  Messages from
224   --      prior signal calls will be discarded.
225   --    status
226   --      0 - alert occurred
227   --      1 - timeout occurred
228   --  Errors raised:
229   --    -20000, ORU-10024: there are no alerts registered.
230   --       Cause: You must register an alert before waiting.
231   --
232   procedure waitone(name in varchar2,
233                     message out varchar2,
234                     status out integer,
235                     timeout in number default maxwait);
236   --  Wait for specified alert to occur. If the alert was signalled since
237   --    the register or last waitone/waitany, then this call will return
238   --    immediately.  The same session that waits for the alert may also
239   --    first signal the alert.  In this case remember to commit after the
240   --    signal and prior to the wait.  Otherwise a lock request exception
241   --    (status 4) will occur.  This call always performs a commit.
242   --  Input parameters:
243   --    name
244   --      The name of the alert to wait for. The name is case-insensitive.
245   --    timeout
246   --      The maximum time to wait for this alert.  If no alert occurs before
247   --      timeout seconds, then this call will return with status of 1.
248   --      If the named alert has not been registered then the this call
249   --      will return after the timeout period expires.
250   --  Output parameters:
251   --    message
252   --      The message associated with the alert.  This is the message
253   --      provided by the 'signal' call.  Note that if multiple signals
254   --      on this alert occurred before the waitone call, then the message
255   --      will correspond to the most recent signal call.  Messages from
256   --      prior signal calls will be discarded.  The message may be up to
257   --      1800 bytes.
258   --    status
259   --      0 - alert occurred
260   --      1 - timeout occurred
261   --
262   procedure signal(name in varchar2,
263                    message in varchar2);
264   --  Signal an alert.
265   --  Input parameters:
266   --    name
267   --      Name of the alert to signal.  The effect of the signal call only
268   --      occurs when the transaction in which it is made commits.  If the
269   --      transaction rolls back, then the effect of the signal call is as
270   --      if it had never occurred.  All sessions that have registered
271   --      interest in this alert will be notified.  If the interested sessions
272   --      are currently waiting, they will be awakened.  If the interested
273   --      sessions are not currently waiting, then they will be notified the
274   --      next time they do a wait call.  Multiple sessions may concurrently
275   --      perform signals on the same alert.  However the first session
276   --      will block concurrent sessions until the first session commits.
277   --      Name must be 30 bytes or less. It is case-insensitive.  This call
278   --      does not perform a commit.
279   --    message
280   --      Message to associate with this alert.  This will be passed to
281   --      the waiting session.  The waiting session may be able to avoid
282   --      reading the database after the alert occurs by using the
283   --      information in this message.  The message must be 1800 bytes or less.
284 
285 end;