DBA Data[Home] [Help]

PROCEDURE: SYS.DBMS_FEATURE_EMX

Source


1 PROCEDURE dbms_feature_emx
2      ( feature_boolean  OUT NUMBER,
3        aux_count        OUT NUMBER,
4        feature_info     OUT CLOB)
5 AS
6   -- total em express usage count since last feature usage collection
7   l_count_total_delta number := 0;
8 
9   -- total em express usage count since the first time it's used
10   l_count_total number := 0;
11 
12   -- feature_info clob
13   l_detailed_usage_clob CLOB := NULL;
14 
15   -- feature_info xml
16   l_detailed_usage_xml xmltype := NULL;
17 
18   -- new xml to add to feature_info xml for one report
19   l_report_usage_xml xmltype   := NULL;
20 
21   -- xpath key to find out if report already has entry in feature_info xml
22   l_report_usage_key varchar2(32767);
23 
24   -- report name
25   l_report_name varchar2(32767) := NULL;
26 
27   -- statistics of existing entry in feature_info xml for report
28   l_old_report_count         number;
29   l_old_report_avg_time      number;
30   l_old_report_avg_cputime   number;
31 
32   -- new statistics to put into feature_info xml for report
33   l_new_report_count         number:= NULL;
34   l_new_report_total_time    number:= NULL;
35   l_new_report_avg_time      number:= NULL;
36   l_new_report_total_cputime number:= NULL;
37   l_new_report_avg_cputime   number:= NULL;
38 
39   -- last db feature usage sample collection time
40   l_last_collection_time date;
41 
42   -- Query to select the delta since last feature usage collection
43   -- from internal fixed table X$KEXSVFU.
44   -- Note if count for the report is 0, but last request timestamp is greater
45   -- than or equal to the latest sample date of db feature usage framework,
46   -- then this report must have been used at least once, therefore decoding
47   -- count from 0 to 1.
48   -- If in CDB, returned result is for this container only
49   cursor emx_fu_cursor(p_last_collection_time date) is
50     select report,
51            sum(total_count) as total_count,
52            sum(total_elapsed_time) as total_elapsed_time,
53            sum(total_cpu_time) as total_cpu_time
54       from table(gv$(cursor(
55              select report_kexsvfu       as report,
56                     decode(count_kexsvfu, 0, 1, count_kexsvfu) as total_count,
57                     elapsed_time_kexsvfu as total_elapsed_time,
58                     cpu_time_kexsvfu     as total_cpu_time
59                from X$KEXSVFU
60               where last_req_time_kexsvfu >= p_last_collection_time
61                 and con_id = sys_context('userenv', 'con_id'))))
62     group by report;
63 
64 begin
65 
66   -- initialize output parameters
67   feature_boolean := 0;
68   aux_count := 0;
69   feature_info := NULL;
70 
71   -- get total em express usage count from aux_count column and
72   -- detailed em express usage info from feature_info column before
73   -- last usage collection
74   begin
75     select nvl(aux_count, 0), feature_info
76       into l_count_total, l_detailed_usage_clob
77       from dba_feature_usage_statistics
78      where name = 'EM Express';
79   exception
80     when NO_DATA_FOUND then
81       l_count_total := 0;
82       l_detailed_usage_clob := NULL;
83   end;
84 
85   -- if no feature_info xml exists, construct a brand new one
86   if (l_detailed_usage_clob is NULL) then
87     l_detailed_usage_xml :=
88       xmltype('<emx_usage time_unit="us"></emx_usage>');
89   -- otherwise update the existing one
90   else
91     l_detailed_usage_xml := xmltype(l_detailed_usage_clob);
92   end if;
93 
94   -- get last db feature usage collection time
95   select nvl(max(last_sample_date), sysdate-7)
96     into l_last_collection_time
97     from dba_feature_usage_statistics;
98 
99   -- get report usage info since last feature usage collection
100   for rc in emx_fu_cursor(l_last_collection_time)
101   loop
102     l_report_name              := rc.report;
103     l_new_report_count         := rc.total_count;
104     l_new_report_total_time    := rc.total_elapsed_time;
105     l_new_report_total_cputime := rc.total_cpu_time;
106 
107     -- update total count for all EM Express reports since last usage
108     -- collection, this will indicate if EM Express has been used since last
109     -- collection, and be added to aux_count column
110     l_count_total_delta := l_count_total_delta + l_new_report_count;
111 
112     --
113     -- update the feature_info detail xml
114     --
115 
116     -- build the xpath key to find out if the report already exists
117     -- in the xml. The key looks like:
118     --   '//report_usage[@report="<report_id>"]'
119     l_report_usage_key := '//report_usage[' ||
120                           '@report="' || l_report_name || '"' ||
121                           ']';
122 
123     -- find out if an xml element for this report already exists in the xml
124     if (l_detailed_usage_xml.existsNode(l_report_usage_key) > 0) then
125 
126       -- get the old count for this report
127       -- if any of the attributes is not found for this report,
128       -- reset it to 0
129       select NVL(EXTRACTVALUE(l_detailed_usage_xml,
130                               l_report_usage_key || '//@count'), 0),
131              NVL(EXTRACTVALUE(l_detailed_usage_xml,
132                               l_report_usage_key || '//@avg_elapsed_time'), 0),
133              NVL(EXTRACTVALUE(l_detailed_usage_xml,
134                               l_report_usage_key || '//@avg_cpu_time'), 0)
135         into l_old_report_count,
136              l_old_report_avg_time,
137              l_old_report_avg_cputime
138         from dual;
139 
140       -- update the statistics, increment count and total time with stats
141       -- since the last usage collection
142       l_new_report_count
143         := l_old_report_count + l_new_report_count;
144 
145       -- recalculate average time
146       l_new_report_avg_time
147         := round((l_old_report_avg_time * l_old_report_count
148                   + l_new_report_total_time) / l_new_report_count, 1);
149 
150       l_new_report_avg_cputime
151         := round((l_old_report_avg_cputime * l_old_report_count
152                  + l_new_report_total_cputime) / l_new_report_count, 1);
153 
154       -- update the xml using the new stats
155       select updateXML(l_detailed_usage_xml,
156                        l_report_usage_key || '//@count',
157                        l_new_report_count,
158                        l_report_usage_key || '//@avg_elapsed_time',
159                        l_new_report_avg_time,
160                        l_report_usage_key || '//@avg_cpu_time',
161                        l_new_report_avg_cputime)
162         into l_detailed_usage_xml
163         from dual;
164 
165     -- if no xml element is found for this report, construct a new one
166     else
167       -- calculate average time
168       l_new_report_avg_time
169         := round(l_new_report_total_time / l_new_report_count, 1);
170       l_new_report_avg_cputime
171         := round(l_new_report_total_cputime / l_new_report_count, 1);
172 
173       -- construct new xml element for this report usage
174       select xmlelement("report_usage",
175                         xmlattributes(
176                           l_report_name              as "report",
177                           l_new_report_count         as "count",
178                           l_new_report_avg_time      as "avg_elapsed_time",
179                           l_new_report_avg_cputime   as "avg_cpu_time"))
180         into l_report_usage_xml
181         from dual;
182 
183       -- append this report usage to the main emx feature usage xml
184       l_detailed_usage_xml :=
185         l_detailed_usage_xml.appendChildxml('/*', l_report_usage_xml);
186 
187     end if;
188 
189   end loop;
190 
191   -- update feature_boolean to indicate if em express has been used or not
192   -- by setting it to the total count since last usage collection
193   feature_boolean := l_count_total_delta;
194 
195   -- update total count in aux_count column
196   aux_count := l_count_total + l_count_total_delta;
197 
198   -- update feature_info for the new collection
199   feature_info := l_detailed_usage_xml.getClobVal();
200 
201 end dbms_feature_emx;