xref: /aosp_15_r20/external/perfetto/src/trace_processor/perfetto_sql/intrinsics/functions/clock_functions.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_FUNCTIONS_CLOCK_FUNCTIONS_H_
18 #define SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_FUNCTIONS_CLOCK_FUNCTIONS_H_
19 
20 #include <sqlite3.h>
21 #include <unordered_map>
22 #include "perfetto/ext/base/base64.h"
23 #include "protos/perfetto/common/builtin_clock.pbzero.h"
24 #include "src/trace_processor/importers/common/clock_converter.h"
25 #include "src/trace_processor/perfetto_sql/intrinsics/functions/sql_function.h"
26 #include "src/trace_processor/util/status_macros.h"
27 
28 namespace perfetto {
29 namespace trace_processor {
30 
31 struct AbsTimeStr : public SqlFunction {
32   using Context = ClockConverter;
33   static base::Status Run(ClockConverter* tracker,
34                           size_t argc,
35                           sqlite3_value** argv,
36                           SqlValue& out,
37                           Destructors& destructors);
38 };
39 
Run(ClockConverter * tracker,size_t argc,sqlite3_value ** argv,SqlValue & out,Destructors & destructors)40 base::Status AbsTimeStr::Run(ClockConverter* tracker,
41                              size_t argc,
42                              sqlite3_value** argv,
43                              SqlValue& out,
44                              Destructors& destructors) {
45   if (argc != 1) {
46     return base::ErrStatus("ABS_TIME_STR: 1 arg required");
47   }
48 
49   // If the timestamp is null, just return null as the result.
50   if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
51     return base::OkStatus();
52   }
53   if (sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
54     return base::ErrStatus("ABS_TIME_STR: first argument should be timestamp");
55   }
56 
57   int64_t ts = sqlite3_value_int64(argv[0]);
58   base::StatusOr<std::string> iso8601 = tracker->ToAbsTime(ts);
59   if (!iso8601.ok()) {
60     // We are returning an OkStatus, because one bad timestamp shouldn't stop
61     // the query.
62     return base::OkStatus();
63   }
64 
65   std::unique_ptr<char, base::FreeDeleter> s(
66       static_cast<char*>(malloc(iso8601->size() + 1)));
67   memcpy(s.get(), iso8601->c_str(), iso8601->size() + 1);
68 
69   destructors.string_destructor = free;
70   out = SqlValue::String(s.release());
71   return base::OkStatus();
72 }
73 
74 struct ToMonotonic : public SqlFunction {
75   using Context = ClockConverter;
76   static base::Status Run(ClockConverter* tracker,
77                           size_t argc,
78                           sqlite3_value** argv,
79                           SqlValue& out,
80                           Destructors& destructors);
81 };
82 
Run(ClockConverter * converter,size_t argc,sqlite3_value ** argv,SqlValue & out,Destructors &)83 base::Status ToMonotonic::Run(ClockConverter* converter,
84                               size_t argc,
85                               sqlite3_value** argv,
86                               SqlValue& out,
87                               Destructors&) {
88   if (argc != 1) {
89     return base::ErrStatus("TO_MONOTONIC: 1 arg required");
90   }
91 
92   // If the timestamp is null, just return null as the result.
93   if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
94     return base::OkStatus();
95   }
96   if (sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
97     return base::ErrStatus("TO_MONOTONIC: first argument should be timestamp");
98   }
99 
100   int64_t ts = sqlite3_value_int64(argv[0]);
101   base::StatusOr<int64_t> monotonic = converter->ToMonotonic(ts);
102 
103   if (!monotonic.ok()) {
104     // We are returning an OkStatus, because one bad timestamp shouldn't stop
105     // the query.
106     return base::OkStatus();
107   }
108 
109   out = SqlValue::Long(*monotonic);
110   return base::OkStatus();
111 }
112 
113 struct ToRealtime : public SqlFunction {
114   using Context = ClockConverter;
115   static base::Status Run(ClockConverter* tracker,
116                           size_t argc,
117                           sqlite3_value** argv,
118                           SqlValue& out,
119                           Destructors& destructors);
120 };
121 
Run(ClockConverter * converter,size_t argc,sqlite3_value ** argv,SqlValue & out,Destructors &)122 base::Status ToRealtime::Run(ClockConverter* converter,
123                              size_t argc,
124                              sqlite3_value** argv,
125                              SqlValue& out,
126                              Destructors&) {
127   if (argc != 1) {
128     return base::ErrStatus("TO_REALTIME: 1 arg required");
129   }
130 
131   // If the timestamp is null, just return null as the result.
132   if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
133     return base::OkStatus();
134   }
135   if (sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
136     return base::ErrStatus("TO_REALTIME: first argument should be timestamp");
137   }
138 
139   int64_t ts = sqlite3_value_int64(argv[0]);
140   base::StatusOr<int64_t> realtime = converter->ToRealtime(ts);
141 
142   if (!realtime.ok()) {
143     // We are returning an OkStatus, because one bad timestamp shouldn't stop
144     // the query.
145     return base::OkStatus();
146   }
147 
148   out = SqlValue::Long(*realtime);
149   return base::OkStatus();
150 }
151 
152 struct ToTimecode : public SqlFunction {
153   static base::Status Run(void*,
154                           size_t argc,
155                           sqlite3_value** argv,
156                           SqlValue& out,
157                           Destructors& destructors);
158 };
159 
Run(void *,size_t argc,sqlite3_value ** argv,SqlValue & out,Destructors & destructors)160 base::Status ToTimecode::Run(void*,
161                              size_t argc,
162                              sqlite3_value** argv,
163                              SqlValue& out,
164                              Destructors& destructors) {
165   if (argc != 1) {
166     return base::ErrStatus("TO_TIMECODE: 1 arg required");
167   }
168 
169   // If the timestamp is null, just return null as the result.
170   if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
171     return base::OkStatus();
172   }
173   if (sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
174     return base::ErrStatus("TO_TIMECODE: first argument should be timestamp");
175   }
176 
177   int64_t ns = sqlite3_value_int64(argv[0]);
178 
179   int64_t us = ns / 1000;
180   ns = ns % 1000;
181 
182   int64_t ms = us / 1000;
183   us = us % 1000;
184 
185   int64_t ss = ms / 1000;
186   ms = ms % 1000;
187 
188   int64_t mm = ss / 60;
189   ss = ss % 60;
190 
191   int64_t hh = mm / 60;
192   mm = mm % 60;
193 
194   base::StackString<64> buf("%02" PRId64 ":%02" PRId64 ":%02" PRId64
195                             " %03" PRId64 " %03" PRId64 " %03" PRId64,
196                             hh, mm, ss, ms, us, ns);
197   std::unique_ptr<char, base::FreeDeleter> s(
198       static_cast<char*>(malloc(buf.len() + 1)));
199   memcpy(s.get(), buf.c_str(), buf.len() + 1);
200 
201   destructors.string_destructor = free;
202   out = SqlValue::String(s.release());
203 
204   return base::OkStatus();
205 }
206 
207 }  // namespace trace_processor
208 }  // namespace perfetto
209 
210 #endif  // SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_FUNCTIONS_CLOCK_FUNCTIONS_H_
211