Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 40bc085

Browse files
committed
Updated as per code review comments, added comments on things to do.
1 parent d33e90e commit 40bc085

3 files changed

Lines changed: 73 additions & 19 deletions

File tree

source/core/types/ut_output_dbms_pipe.tpb

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ create or replace type body ut_output_dbms_pipe as
2828
i := i + c_size_limit_chars;
2929
end loop;
3030
--SEND is closed by a EOM message
31-
ut_output_pipe_helper.send( self.output_id, ut_output_pipe_helper.gc_output_eom );
31+
ut_output_pipe_helper.send_eom(self.output_id);
3232
end;
3333

3434
overriding member procedure close(self in out nocopy ut_output_dbms_pipe) is
3535
begin
36-
ut_output_pipe_helper.send(self.output_id, ut_output_pipe_helper.gc_output_eot);
36+
ut_output_pipe_helper.send_eot(self.output_id);
3737
ut_output_pipe_helper.flush(self.output_id);
3838
end;
3939

@@ -43,6 +43,7 @@ create or replace type body ut_output_dbms_pipe as
4343
l_text clob;
4444
l_timeout_occured boolean;
4545
l_need_to_send boolean;
46+
l_item_type integer;
4647
begin
4748
if a_output_id is not null then
4849

@@ -51,20 +52,26 @@ create or replace type body ut_output_dbms_pipe as
5152
l_need_to_send := false;
5253

5354
--build a row. As a rule one call to 'send' is one row.
55+
-- TODO - add detection of newline so that for each new line recieved in text, the code generates a new output row
5456
loop
55-
l_timeout_occured := dbms_pipe.receive_message(a_output_id, a_timeout_sec) != 0;
57+
dbms_pipe.reset_buffer;
58+
l_timeout_occured := (dbms_pipe.receive_message(a_output_id, a_timeout_sec) != 0);
5659
exit when l_timeout_occured;
60+
l_item_type := dbms_pipe.next_item_type();
61+
exit when l_item_type in (ut_output_pipe_helper.gc_eom, ut_output_pipe_helper.gc_eot);
5762
dbms_pipe.unpack_message(l_text_part);
58-
exit when ( l_text_part in (ut_output_pipe_helper.gc_output_eom, ut_output_pipe_helper.gc_output_eot) );
59-
dbms_lob.writeappend(l_text, length(l_text_part), l_text_part);
63+
if l_text_part is not null then
64+
dbms_lob.writeappend(l_text, length(l_text_part), l_text_part);
65+
end if;
6066
l_need_to_send := true;
6167
end loop;
6268

6369
if l_need_to_send then
6470
pipe row( l_text );
71+
dbms_lob.freetemporary(l_text);
6572
end if;
6673

67-
exit when (l_timeout_occured or l_text_part = ut_output_pipe_helper.gc_output_eot);
74+
exit when (l_timeout_occured or l_item_type = ut_output_pipe_helper.gc_eot);
6875
end loop;
6976

7077
l_flag := dbms_pipe.remove_pipe(a_output_id);

source/core/ut_output_pipe_helper.pkb

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
create or replace package body ut_output_pipe_helper is
22

33
-- private
4-
5-
type tt_pipe_buffer is table of varchar2(4000);
4+
type t_pipe_buffer_rec is record(
5+
message_type integer,
6+
message varchar2(4000)
7+
);
8+
type tt_pipe_buffer is table of t_pipe_buffer_rec;
69

710
type t_output_buffer is record(
811
to_flush boolean := false,
@@ -26,7 +29,13 @@ create or replace package body ut_output_pipe_helper is
2629
--iterate through buffer and try to sent all data from buffer
2730
-- exit loop on timeout
2831
while i is not null loop
29-
dbms_pipe.pack_message( a_buffer(i) );
32+
if a_buffer(i).message_type = gc_eom then
33+
dbms_pipe.pack_message_rowid( NULL );
34+
elsif a_buffer(i).message_type = gc_eot then
35+
dbms_pipe.pack_message_raw( NULL );
36+
else
37+
dbms_pipe.pack_message( a_buffer(i).message );
38+
end if;
3039
l_is_successful := dbms_pipe.send_message(a_output_id, a_timeout_seconds) = 0;
3140
exit when not l_is_successful;
3241
l_last_item := i;
@@ -57,6 +66,7 @@ create or replace package body ut_output_pipe_helper is
5766
--iterates through all the output buffers that were not purged
5867
--for each buffer tries to send the content of the buffer
5968
--if all content was sent, buffer is recycled (removed)
69+
--returns true if the flushing succeeded for all buffers
6070
function flush_buffers(a_timeout_seconds naturaln := 0) return boolean is
6171
l_output_id t_output_id;
6272
l_output_id_to_delete t_output_id;
@@ -66,10 +76,10 @@ create or replace package body ut_output_pipe_helper is
6676
l_output_id := g_outputs_buffer.first;
6777
while l_output_id is not null loop
6878
l_output_id_to_delete := null;
69-
if send_from_buffer(l_output_id, a_timeout_seconds) = true then
79+
80+
l_timed_out := not send_from_buffer(l_output_id, a_timeout_seconds);
81+
if not l_timed_out then
7082
l_output_id_to_delete := l_output_id;
71-
else
72-
l_timed_out := true;
7383
end if;
7484
l_output_id := g_outputs_buffer.next(l_output_id);
7585

@@ -95,27 +105,33 @@ create or replace package body ut_output_pipe_helper is
95105
return true;
96106
end;
97107

98-
--remove all the pipes anf purges all the buffers
108+
-- - remove pipes associated with buffers that are not yet deleted
109+
-- - delete all the buffers
110+
-- TODO - The purge procedure needs to be called by top level program (ut_runner)
111+
-- in the EXCEPTION WHEN OTHERS block before raising back,
112+
-- so that it tries to remove pipes on any exception before raising back to caller
99113
procedure purge is
100114
l_pipe_removal_status integer;
101115
l_output_id t_output_id;
102116
begin
103117
l_output_id := g_outputs_buffer.first;
104118
while l_output_id is not null loop
119+
l_pipe_removal_status := dbms_pipe.remove_pipe(l_output_id);
105120
l_output_id := g_outputs_buffer.next(l_output_id);
106121
end loop;
107122
g_outputs_buffer.delete;
108123
end;
109124

110125
--writes the message to the end of the buffer
111-
procedure buffer(a_output_id t_output_id, a_text t_pipe_item) is
126+
procedure buffer(a_output_id t_output_id, a_text t_pipe_item, a_message_type integer := null) is
112127
begin
113128
if not g_outputs_buffer.exists(a_output_id) then
114129
g_outputs_buffer(a_output_id).data := tt_pipe_buffer();
115130
g_outputs_buffer(a_output_id).to_flush := false;
116131
end if;
117132
g_outputs_buffer(a_output_id).data.extend;
118-
g_outputs_buffer(a_output_id).data(g_outputs_buffer(a_output_id).data.last) := a_text;
133+
g_outputs_buffer(a_output_id).data(g_outputs_buffer(a_output_id).data.last).message_type := a_message_type;
134+
g_outputs_buffer(a_output_id).data(g_outputs_buffer(a_output_id).data.last).message := a_text;
119135
end;
120136

121137

@@ -131,10 +147,27 @@ create or replace package body ut_output_pipe_helper is
131147
l_is_successful := send_from_buffer(a_output_id);
132148
end;
133149

150+
--sends a end of message into a a pipe
151+
procedure send_eom(a_output_id t_output_id) is
152+
l_is_successful boolean;
153+
begin
154+
buffer(a_output_id, null, gc_eom);
155+
l_is_successful := send_from_buffer(a_output_id);
156+
end;
157+
158+
--sends a end of message into a a pipe
159+
procedure send_eot(a_output_id t_output_id) is
160+
l_is_successful boolean;
161+
begin
162+
buffer(a_output_id, null, gc_eot);
163+
l_is_successful := send_from_buffer(a_output_id);
164+
end;
165+
134166
--marks a buffer as ready to be flushed
135167
--tries to flush all the data from all the outputs buffers to the pipes immediately
136168
--in case, all buffers outputs are to be flused, it will try with a timeout.
137169
procedure flush(a_output_id t_output_id, a_timeout_seconds naturaln := gc_flush_timeout_seconds) is
170+
l_buffers_flushed boolean := false;
138171
begin
139172
if g_outputs_buffer.exists(a_output_id) then
140173
g_outputs_buffer(a_output_id).to_flush := true;
@@ -144,9 +177,16 @@ create or replace package body ut_output_pipe_helper is
144177
--try as many times as there are seconds for timeout
145178
--each time try with one second delay
146179
for i in 1 .. a_timeout_seconds loop
147-
exit when flush_buffers(a_timeout_seconds => 1) = true;
180+
l_buffers_flushed := flush_buffers(a_timeout_seconds => 1);
181+
exit when l_buffers_flushed;
148182
end loop;
149-
purge();
183+
184+
--if timeout occured and buffers were not flushed then
185+
-- - remove pipes associated with non flushed buffers
186+
-- - delete the buffers
187+
if not l_buffers_flushed then
188+
purge();
189+
end if;
150190
end if;
151191

152192
end;

source/core/ut_output_pipe_helper.pks

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@ create or replace package ut_output_pipe_helper is
99

1010
--decides how long the process will be waiting to flush buffers
1111
gc_flush_timeout_seconds constant natural := 60;
12-
gc_output_eom constant varchar2(30) := '[{-end-of-message-}]';
13-
gc_output_eot constant varchar2(30) := '[{-end-of-transmission-}]';
12+
gc_text constant integer := 9;
13+
gc_eom constant integer := 11;
14+
gc_eot constant integer := 23;
1415

1516
--adds message to pipe buffer and tries to sent all messages from the buffer
1617
--exists immediately when sending timesout (pipe full)
1718
--the messages that were sent are removed from buffer
1819
procedure send(a_output_id t_output_id, a_text t_pipe_item);
1920

21+
--sends a end of message into a a pipe
22+
procedure send_eom(a_output_id t_output_id);
23+
24+
--sends a end of message into a a pipe
25+
procedure send_eot(a_output_id t_output_id);
26+
2027
--marks a buffer as ready to be flushed and then
2128
--tries to flush all the data from all the outputs buffers to the pipes
2229
--in case, all buffers outputs are to be flushed, it will try until a timeout occurs.

0 commit comments

Comments
 (0)