void sinsp_filter::parse_check(sinsp_filter_expression* parent_expr, boolop op) { uint32_t startpos = m_scanpos; vector<char> operand1 = next_operand(true); string str_operand1 = string((char *)&operand1[0]); sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(str_operand1, m_inspector, true); if(chk == NULL) { throw sinsp_exception("filter error: unrecognized field " + str_operand1 + " at pos " + to_string((long long) startpos)); } if(m_ttable_only) { if(!(chk->get_fields()->m_flags & filter_check_info::FL_WORKS_ON_THREAD_TABLE)) { throw sinsp_exception("the given filter is not supported for thread table filtering"); } } ppm_cmp_operator co = next_comparison_operator(); vector<char> operand2 = next_operand(false); chk->m_boolop = op; chk->m_cmpop = co; chk->parse_field_name((char *)&operand1[0]); chk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1); parent_expr->add_check(chk); }
static int request_field(lua_State *ls) { lua_getglobal(ls, "sichisel"); sinsp_chisel* ch = (sinsp_chisel*)lua_touserdata(ls, -1); lua_pop(ls, 1); sinsp* inspector = ch->m_inspector; const char* fld = lua_tostring(ls, 1); if(fld == NULL) { throw sinsp_exception("chisel requesting nil field"); } sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(fld, inspector, false); if(chk == NULL) { throw sinsp_exception("chisel requesting nonexistent field " + string(fld)); } chk->parse_field_name(fld); lua_pushlightuserdata(ls, chk); ch->m_allocated_fltchecks.push_back(chk); return 1; }
void sinsp_filter::parse_check(sinsp_filter_expression* parent_expr, boolop op) { uint32_t startpos = m_scanpos; string operand1 = next_operand(true); sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(operand1, m_inspector, true); if(chk == NULL) { throw sinsp_exception("filter error: unrecognized field " + operand1 + " at pos " + to_string((long long) startpos)); } ppm_cmp_operator co = next_comparison_operator(); string operand2 = next_operand(false); chk->m_boolop = op; chk->m_cmpop = co; chk->parse_field_name(operand1.c_str()); chk->parse_filter_value(operand2.c_str()); parent_expr->add_check(chk); }
void sinsp_table::configure(vector<sinsp_view_column_info>* entries, const string& filter, bool use_defaults, uint32_t view_depth) { m_use_defaults = use_defaults; m_view_depth = view_depth; // // If this is a list table, increase the refresh time to improve realtimyiness // if(m_type == sinsp_table::TT_LIST) { set_refresh_interval(200000000); } ////////////////////////////////////////////////////////////////////////////////////// // If a filter has been spefied, compile it ////////////////////////////////////////////////////////////////////////////////////// if(filter != "") { sinsp_filter_compiler compiler(m_inspector, filter); m_filter = compiler.compile(); } ////////////////////////////////////////////////////////////////////////////////////// // Extract the tokens ////////////////////////////////////////////////////////////////////////////////////// m_premerge_extractors.clear(); for(auto vit : *entries) { sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(vit.get_field(m_view_depth), m_inspector, false); if(chk == NULL) { throw sinsp_exception("invalid field name " + vit.get_field(m_view_depth)); } chk->m_aggregation = (sinsp_field_aggregation)vit.m_aggregation; m_chks_to_free.push_back(chk); chk->parse_field_name(vit.get_field(m_view_depth).c_str(), true); if((vit.m_flags & TEF_IS_KEY) != 0) { if(m_is_key_present) { throw sinsp_exception("invalid table configuration: multiple keys specified"); } m_premerge_extractors.insert(m_premerge_extractors.begin(), chk); m_is_key_present = true; } else { m_premerge_extractors.push_back(chk); } } if(m_type == sinsp_table::TT_TABLE) { // // Make sure this is a valid table // if(!m_is_key_present) { throw sinsp_exception("table is missing the key"); } } else { sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname("util.cnt", m_inspector, false); if(chk == NULL) { throw sinsp_exception("internal table error"); } chk->m_aggregation = A_NONE; m_chks_to_free.push_back(chk); chk->parse_field_name("util.cnt", true); if(m_is_key_present) { throw sinsp_exception("list table can't have a key"); } m_premerge_extractors.insert(m_premerge_extractors.begin(), chk); m_is_key_present = true; } m_premerge_fld_pointers = new sinsp_table_field[m_premerge_extractors.size()]; m_fld_pointers = m_premerge_fld_pointers; m_n_premerge_fields = (uint32_t)m_premerge_extractors.size(); m_n_fields = m_n_premerge_fields; if(m_n_fields < 2) { throw sinsp_exception("table has no values"); } for(auto it = m_premerge_extractors.begin(); it != m_premerge_extractors.end(); ++it) { m_premerge_types.push_back((*it)->get_field_info()->m_type); m_premerge_legend.push_back(*(*it)->get_field_info()); } m_premerge_vals_array_sz = (m_n_fields - 1) * sizeof(sinsp_table_field); m_vals_array_sz = m_premerge_vals_array_sz; ////////////////////////////////////////////////////////////////////////////////////// // If a merge has been specified, configure it ////////////////////////////////////////////////////////////////////////////////////// uint32_t n_gby_keys = 0; for(auto vit : *entries) { if((vit.m_flags & TEF_IS_GROUPBY_KEY) != 0) { n_gby_keys++; } } if(n_gby_keys == 0) { // // No merge string. We can stop here // m_do_merging = false; return; } else if(n_gby_keys > 1) { throw sinsp_exception("invalid table definition: multiple groupby keys"); } // // Merging not supported for lists // if(m_type != sinsp_table::TT_TABLE) { throw sinsp_exception("group by not supported for list tables"); } m_do_merging = true; for(uint32_t j = 0; j < entries->size(); j++) { auto vit = entries->at(j); // // Skip original key when grouping // if((vit.m_flags & TEF_IS_KEY) != 0) { continue; } sinsp_filter_check* chk = m_premerge_extractors[j]; chk->m_merge_aggregation = (sinsp_field_aggregation)vit.m_groupby_aggregation; if((vit.m_flags & TEF_IS_GROUPBY_KEY) != 0) { if(m_is_groupby_key_present) { throw sinsp_exception("invalid table configuration: more than one groupby key specified"); } m_is_groupby_key_present = true; m_postmerge_extractors.insert(m_postmerge_extractors.begin(), chk); m_groupby_columns.insert(m_groupby_columns.begin(), j); } else { m_postmerge_extractors.push_back(chk); m_groupby_columns.push_back(j); } } m_postmerge_fld_pointers = new sinsp_table_field[m_postmerge_extractors.size()]; m_n_postmerge_fields = (uint32_t)m_postmerge_extractors.size(); if(!m_is_groupby_key_present) { throw sinsp_exception("table is missing the groupby key"); } if(m_groupby_columns.size() < 2) { throw sinsp_exception("groupby table has no values"); } for(auto it = m_postmerge_extractors.begin(); it != m_postmerge_extractors.end(); ++it) { m_postmerge_types.push_back((*it)->get_field_info()->m_type); m_postmerge_legend.push_back(*(*it)->get_field_info()); } m_postmerge_vals_array_sz = (m_n_postmerge_fields - 1) * sizeof(sinsp_table_field); }
void sinsp_filter_compiler::parse_check() { uint32_t startpos = m_scanpos; vector<char> operand1 = next_operand(true, false); string str_operand1 = string((char *)&operand1[0]); sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(str_operand1, m_inspector, true); boolop op = m_last_boolop; if(chk == NULL) { throw sinsp_exception("filter error: unrecognized field " + str_operand1 + " at pos " + to_string((long long) startpos)); } if(m_ttable_only) { if(!(chk->get_fields()->m_flags & filter_check_info::FL_WORKS_ON_THREAD_TABLE)) { throw sinsp_exception("the given filter is not supported for thread table filtering"); } } cmpop co = next_comparison_operator(); chk->m_boolop = op; chk->m_cmpop = co; chk->parse_field_name((char *)&operand1[0], true); if(co == CO_IN || co == CO_PMATCH) { // // Skip spaces // if(isblank(m_fltstr[m_scanpos])) { next(); } if(m_fltstr[m_scanpos] != '(') { throw sinsp_exception("expected '(' after 'in/pmatch' operand"); } // // Skip '(' // m_scanpos++; if(chk->get_field_info()->m_type == PT_CHARBUF) { // // For character buffers, we can check all // values at once by putting them in a set and // checking for set membership. // // // Create the 'or' sequence // uint64_t num_values = 0; while(true) { // 'in' clause aware vector<char> operand2 = next_operand(false, true); chk->add_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1, num_values); num_values++; next(); if(m_fltstr[m_scanpos] == ')') { break; } else if(m_fltstr[m_scanpos] == ',') { m_scanpos++; } else { throw sinsp_exception("expected either ')' or ',' after a value inside the 'in/pmatch' clause"); } } m_filter->add_check(chk); } else if (co == CO_PMATCH) { // the pmatch operator can only work on charbufs throw sinsp_exception("pmatch requires all charbuf arguments"); } else { // // In this case we need to create '(field=value1 or field=value2 ...)' // // // Separate the 'or's from the // rest of the conditions // m_filter->push_expression(op); m_last_boolop = BO_NONE; m_nest_level++; // // The first boolean operand will be BO_NONE // Then we will start putting BO_ORs // op = BO_NONE; // // Create the 'or' sequence // uint64_t num_values = 0; while(true) { // 'in' clause aware vector<char> operand2 = next_operand(false, true); // // Append every sinsp_filter_check creating the 'or' sequence // sinsp_filter_check* newchk = g_filterlist.new_filter_check_from_another(chk); newchk->m_boolop = op; newchk->m_cmpop = CO_EQ; newchk->add_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1, num_values); num_values++; m_filter->add_check(newchk); next(); if(m_fltstr[m_scanpos] == ')') { break; } else if(m_fltstr[m_scanpos] == ',') { m_scanpos++; } else { throw sinsp_exception("expected either ')' or ',' after a value inside the 'in' clause"); } // // From now on we 'or' every newchk // op = BO_OR; } // // Come back to the rest of the filter // m_filter->pop_expression(); m_nest_level--; } } else { // // In this case we want next() to return the very next character // At this moment m_scanpos is already at it // e.g. "(field exists) and ..." // if(co == CO_EXISTS) { m_scanpos--; } // // Otherwise we need a value for the operand // else { vector<char> operand2 = next_operand(false, false); chk->add_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1); } m_filter->add_check(chk); } }
void sinsp_evt_formatter::set_format(const string& fmt) { uint32_t j; uint32_t last_nontoken_str_start = 0; string lfmt(fmt); if(lfmt == "") { throw sinsp_exception("empty formatting token"); } // // If the string starts with a *, it means that we are ok with printing // the string even when not all the values it specifies are set. // if(lfmt[0] == '*') { m_require_all_values = false; lfmt.erase(0, 1); } else { m_require_all_values = true; } // // Parse the string and extract the tokens // const char* cfmt = lfmt.c_str(); m_tokens.clear(); for(j = 0; j < lfmt.length(); j++) { if(cfmt[j] == '%') { if(last_nontoken_str_start != j) { rawstring_check* newtkn = new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start)); m_tokens.push_back(newtkn); m_chks_to_free.push_back(newtkn); } sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(string(cfmt + j + 1), m_inspector, false); if(chk == NULL) { throw sinsp_exception("invalid formatting token " + string(cfmt + j + 1)); } m_chks_to_free.push_back(chk); j += chk->parse_field_name(cfmt + j + 1); ASSERT(j <= lfmt.length()); m_tokens.push_back(chk); last_nontoken_str_start = j + 1; } } if(last_nontoken_str_start != j) { m_tokens.push_back(new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start))); } }
void sinsp_evt_formatter::set_format(const string& fmt) { uint32_t j; uint32_t last_nontoken_str_start = 0; string lfmt(fmt); if(lfmt == "") { throw sinsp_exception("empty formatting token"); } // // If the string starts with a *, it means that we are ok with printing // the string even when not all the values it specifies are set. // if(lfmt[0] == '*') { m_require_all_values = false; lfmt.erase(0, 1); } else { m_require_all_values = true; } // // Parse the string and extract the tokens // const char* cfmt = lfmt.c_str(); m_tokens.clear(); uint32_t lfmtlen = lfmt.length(); for(j = 0; j < lfmtlen; j++) { if(cfmt[j] == '%') { int toklen = 0; if(last_nontoken_str_start != j) { rawstring_check* newtkn = new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start)); m_tokens.push_back(newtkn); m_tokenlens.push_back(0); m_chks_to_free.push_back(newtkn); } if(j == lfmtlen - 1) { throw sinsp_exception("invalid formatting syntax: formatting cannot end with a %"); } // // If the field specifier starts with a number, it means that we have a length modifier // if(isdigit(cfmt[j + 1])) { // // Parse the token length // sscanf(cfmt+ j + 1, "%d", &toklen); // // Advance until the beginning of the field name // while(true) { if(j == lfmtlen - 1) { throw sinsp_exception("invalid formatting syntax: formatting cannot end with a number"); } else if(isdigit(cfmt[j + 1])) { j++; continue; } else { break; } } } sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(string(cfmt + j + 1), m_inspector, false); if(chk == NULL) { throw sinsp_exception("invalid formatting token " + string(cfmt + j + 1)); } m_chks_to_free.push_back(chk); j += chk->parse_field_name(cfmt + j + 1); ASSERT(j <= lfmt.length()); m_tokens.push_back(chk); m_tokenlens.push_back(toklen); last_nontoken_str_start = j + 1; } } if(last_nontoken_str_start != j) { m_tokens.push_back(new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start))); m_tokenlens.push_back(0); } }
void sinsp_filter::parse_check(sinsp_filter_expression* parent_expr, boolop op) { uint32_t startpos = m_scanpos; vector<char> operand1 = next_operand(true, false); string str_operand1 = string((char *)&operand1[0]); sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(str_operand1, m_inspector, true); if(chk == NULL) { throw sinsp_exception("filter error: unrecognized field " + str_operand1 + " at pos " + to_string((long long) startpos)); } if(m_ttable_only) { if(!(chk->get_fields()->m_flags & filter_check_info::FL_WORKS_ON_THREAD_TABLE)) { throw sinsp_exception("the given filter is not supported for thread table filtering"); } } ppm_cmp_operator co = next_comparison_operator(); chk->m_boolop = op; chk->m_cmpop = co; chk->parse_field_name((char *)&operand1[0], true); // // In this case we need to create '(field=value1 or field=value2 ...)' // if(co == CO_IN) { // // Separate the 'or's from the // rest of the conditions // push_expression(op); // // Skip spaces // if(isblank(m_fltstr[m_scanpos])) { next(); } if(m_fltstr[m_scanpos] != '(') { throw sinsp_exception("expected '(' after 'in' operand"); } // // Skip '(' // m_scanpos++; // // The first boolean operand will be BO_NONE // Then we will start putting BO_ORs // op = BO_NONE; // // Create the 'or' sequence // while(true) { // 'in' clause aware vector<char> operand2 = next_operand(false, true); // // Append every sinsp_filter_check creating the 'or' sequence // sinsp_filter_check* newchk = g_filterlist.new_filter_check_from_another(chk); newchk->m_boolop = op; newchk->m_cmpop = CO_EQ; newchk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1); // // We pushed another expression before // so 'parent_expr' still referers to // the old one, this is the new nested // level for the 'or' sequence // m_curexpr->add_check(newchk); next(); if(m_fltstr[m_scanpos] == ')') { break; } else if(m_fltstr[m_scanpos] == ',') { m_scanpos++; } else { throw sinsp_exception("expected either ')' or ',' after a value inside the 'in' clause"); } // // From now on we 'or' every newchk // op = BO_OR; } // // Come back to the rest of the filter // pop_expression(); } else { // // In this case we want next() to return the very next character // At this moment m_scanpos is already at it // e.g. "(field exists) and ..." // if(co == CO_EXISTS) { m_scanpos--; } // // Otherwise we need a value for the operand // else { vector<char> operand2 = next_operand(false, false); chk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1); } parent_expr->add_check(chk); } }