1 /** 2 * Copyright (c) 2007-2012, Timothy Stack 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * * Neither the name of Timothy Stack nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #ifndef vtab_impl_hh 31 #define vtab_impl_hh 32 33 #include <sqlite3.h> 34 35 #include <map> 36 #include <string> 37 #include <vector> 38 39 #include "logfile_sub_source.hh" 40 41 class textview_curses; 42 43 enum { 44 VT_COL_LINE_NUMBER, 45 VT_COL_PARTITION, 46 VT_COL_LOG_TIME, 47 VT_COL_LOG_ACTUAL_TIME, 48 VT_COL_IDLE_MSECS, 49 VT_COL_LEVEL, 50 VT_COL_MARK, 51 VT_COL_LOG_COMMENT, 52 VT_COL_LOG_TAGS, 53 VT_COL_FILTERS, 54 VT_COL_MAX 55 }; 56 57 class logfile_sub_source; 58 59 struct log_cursor { 60 vis_line_t lc_curr_line; 61 int lc_sub_index; 62 vis_line_t lc_end_line; 63 64 void update(unsigned char op, vis_line_t vl, bool exact = true); 65 set_eoflog_cursor66 void set_eof() { 67 this->lc_curr_line = this->lc_end_line = vis_line_t(0); 68 }; 69 is_eoflog_cursor70 bool is_eof() const { 71 return this->lc_curr_line >= this->lc_end_line; 72 }; 73 }; 74 75 const std::string LOG_BODY = "log_body"; 76 const std::string LOG_TIME = "log_time"; 77 78 class log_vtab_impl { 79 public: 80 struct vtab_column { vtab_columnlog_vtab_impl::vtab_column81 vtab_column(const std::string name = "", 82 int type = SQLITE3_TEXT, 83 const std::string collator = "", 84 bool hidden = false, 85 const std::string comment = "", 86 unsigned int subtype = 0) 87 : vc_name(name), 88 vc_type(type), 89 vc_collator(collator), 90 vc_hidden(hidden), 91 vc_comment(comment), 92 vc_subtype(subtype) { 93 }; 94 with_commentlog_vtab_impl::vtab_column95 vtab_column& with_comment(const std::string comment) { 96 this->vc_comment = comment; 97 return *this; 98 } 99 100 std::string vc_name; 101 int vc_type; 102 std::string vc_collator; 103 bool vc_hidden; 104 std::string vc_comment; 105 int vc_subtype; 106 }; 107 108 static std::pair<int, unsigned int> logline_value_to_sqlite_type(value_kind_t kind); 109 log_vtab_impl(const intern_string_t name)110 log_vtab_impl(const intern_string_t name) : vi_supports_indexes(true), vi_name(name) { 111 this->vi_attrs.resize(128); 112 }; 113 virtual ~log_vtab_impl() = default; 114 get_name() const115 const intern_string_t get_name() const 116 { 117 return this->vi_name; 118 }; 119 120 std::string get_table_statement(); 121 is_valid(log_cursor & lc,logfile_sub_source & lss)122 virtual bool is_valid(log_cursor &lc, logfile_sub_source &lss) { 123 content_line_t cl(lss.at(lc.lc_curr_line)); 124 std::shared_ptr<logfile> lf = lss.find(cl); 125 auto lf_iter = lf->begin() + cl; 126 127 if (!lf_iter->is_message()) { 128 return false; 129 } 130 131 return true; 132 }; 133 134 virtual bool next(log_cursor &lc, logfile_sub_source &lss) = 0; 135 get_columns(std::vector<vtab_column> & cols) const136 virtual void get_columns(std::vector<vtab_column> &cols) const { }; 137 get_foreign_keys(std::vector<std::string> & keys_inout) const138 virtual void get_foreign_keys(std::vector<std::string> &keys_inout) const 139 { 140 keys_inout.emplace_back("log_line"); 141 keys_inout.emplace_back("min(log_line)"); 142 keys_inout.emplace_back("log_mark"); 143 keys_inout.emplace_back("log_time_msecs"); 144 }; 145 extract(std::shared_ptr<logfile> lf,uint64_t line_number,shared_buffer_ref & line,std::vector<logline_value> & values)146 virtual void extract(std::shared_ptr<logfile> lf, 147 uint64_t line_number, 148 shared_buffer_ref &line, 149 std::vector<logline_value> &values) 150 { 151 auto format = lf->get_format(); 152 153 this->vi_attrs.clear(); 154 format->annotate(line_number, line, this->vi_attrs, values, false); 155 }; 156 157 bool vi_supports_indexes; 158 int vi_column_count; 159 string_attrs_t vi_attrs; 160 protected: 161 const intern_string_t vi_name; 162 }; 163 164 class log_format_vtab_impl : public log_vtab_impl { 165 166 public: log_format_vtab_impl(const log_format & format)167 log_format_vtab_impl(const log_format &format) : 168 log_vtab_impl(format.get_name()), lfvi_format(format) { 169 170 } 171 next(log_cursor & lc,logfile_sub_source & lss)172 virtual bool next(log_cursor &lc, logfile_sub_source &lss) 173 { 174 lc.lc_curr_line = lc.lc_curr_line + vis_line_t(1); 175 lc.lc_sub_index = 0; 176 177 if (lc.is_eof()) { 178 return true; 179 } 180 181 auto cl = content_line_t(lss.at(lc.lc_curr_line)); 182 auto lf = lss.find(cl); 183 auto lf_iter = lf->begin() + cl; 184 uint8_t mod_id = lf_iter->get_module_id(); 185 186 if (!lf_iter->is_message()) { 187 return false; 188 } 189 190 auto format = lf->get_format(); 191 if (format->get_name() == this->lfvi_format.get_name()) { 192 return true; 193 } else if (mod_id && mod_id == this->lfvi_format.lf_mod_index) { 194 // XXX 195 return true; 196 } 197 198 return false; 199 }; 200 201 protected: 202 const log_format &lfvi_format; 203 204 }; 205 206 typedef int (*sql_progress_callback_t)(const log_cursor &lc); 207 typedef void (*sql_progress_finished_callback_t)(); 208 209 extern struct _log_vtab_data { 210 sql_progress_callback_t lvd_progress; 211 sql_progress_finished_callback_t lvd_finished; 212 std::string lvd_source; 213 int lvd_line_number{0}; 214 } log_vtab_data; 215 216 class sql_progress_guard { 217 public: sql_progress_guard(sql_progress_callback_t cb,sql_progress_finished_callback_t fcb,const std::string & source,int line_number)218 sql_progress_guard(sql_progress_callback_t cb, 219 sql_progress_finished_callback_t fcb, 220 const std::string &source, 221 int line_number) { 222 log_vtab_data.lvd_progress = cb; 223 log_vtab_data.lvd_finished = fcb; 224 log_vtab_data.lvd_source = source; 225 log_vtab_data.lvd_line_number = line_number; 226 }; 227 ~sql_progress_guard()228 ~sql_progress_guard() { 229 if (log_vtab_data.lvd_finished) { 230 log_vtab_data.lvd_finished(); 231 } 232 log_vtab_data.lvd_progress = nullptr; 233 log_vtab_data.lvd_finished = nullptr; 234 log_vtab_data.lvd_source.clear(); 235 log_vtab_data.lvd_line_number = 0; 236 }; 237 }; 238 239 class log_vtab_manager { 240 public: 241 typedef std::map<intern_string_t, std::shared_ptr<log_vtab_impl>>::const_iterator iterator; 242 243 log_vtab_manager(sqlite3 *db, 244 textview_curses &tc, 245 logfile_sub_source &lss); 246 ~log_vtab_manager(); 247 get_view() const248 textview_curses *get_view() const { return &this->vm_textview; }; 249 get_source()250 logfile_sub_source *get_source() { return &this->vm_source; }; 251 252 std::string register_vtab(std::shared_ptr<log_vtab_impl> vi); 253 std::string unregister_vtab(intern_string_t name); 254 lookup_impl(intern_string_t name) const255 std::shared_ptr<log_vtab_impl> lookup_impl(intern_string_t name) const 256 { 257 auto iter = this->vm_impls.find(name); 258 259 if (iter != this->vm_impls.end()) { 260 return iter->second; 261 } 262 return nullptr; 263 }; 264 begin() const265 iterator begin() const 266 { 267 return this->vm_impls.begin(); 268 }; 269 end() const270 iterator end() const 271 { 272 return this->vm_impls.end(); 273 }; 274 275 private: 276 sqlite3 * vm_db; 277 textview_curses &vm_textview; 278 logfile_sub_source &vm_source; 279 std::map<intern_string_t, std::shared_ptr<log_vtab_impl>> vm_impls; 280 }; 281 #endif 282