diff --git a/build/ag_gen b/build/ag_gen index 0ce9f5a..f95440d 100755 Binary files a/build/ag_gen and b/build/ag_gen differ diff --git a/build/decode b/build/decode index f5330fe..8307cbf 100755 Binary files a/build/decode and b/build/decode differ diff --git a/fpga_examples/Network_5/car_network5.nm b/fpga_examples/Network_5/car_network5.nm index 721ffa1..9548105 100644 --- a/fpga_examples/Network_5/car_network5.nm +++ b/fpga_examples/Network_5/car_network5.nm @@ -3,6 +3,11 @@ network model = # Cars car1; car2; + car3; + car4; + car5; + car6; + facts: quality:car1,brake_months=6; @@ -27,6 +32,49 @@ network model = quality:car2,vacuum_vio=false; quality:car2,compliance_vio=false; + quality:car3,brake_months=6; + quality:car3,exhaust_months=12; + quality:car3,ac_odometer=120000; + quality:car3,vacuum_odometer=120000; + quality:car3,engine=gas; + quality:car3,brake_vio=false; + quality:car3,exhaust_vio=false; + quality:car3,ac_vio=false; + quality:car3,vacuum_vio=false; + quality:car3,compliance_vio=false; + + quality:car4,brake_months=6; + quality:car4,exhaust_months=12; + quality:car4,ac_odometer=120000; + quality:car4,vacuum_odometer=120000; + quality:car4,engine=diesel; + quality:car4,brake_vio=false; + quality:car4,exhaust_vio=false; + quality:car4,ac_vio=false; + quality:car4,vacuum_vio=false; + quality:car4,compliance_vio=false; + + quality:car5,brake_months=6; + quality:car5,exhaust_months=12; + quality:car5,ac_odometer=120000; + quality:car5,vacuum_odometer=120000; + quality:car5,engine=gas; + quality:car5,brake_vio=false; + quality:car5,exhaust_vio=false; + quality:car5,ac_vio=false; + quality:car5,vacuum_vio=false; + quality:car5,compliance_vio=false; + + quality:car6,brake_months=6; + quality:car6,exhaust_months=12; + quality:car6,ac_odometer=120000; + quality:car6,vacuum_odometer=120000; + quality:car6,engine=diesel; + quality:car6,brake_vio=false; + quality:car6,exhaust_vio=false; + quality:car6,ac_vio=false; + quality:car6,vacuum_vio=false; + quality:car6,compliance_vio=false; topology:car1<->car2,road; tags: . diff --git a/src/ag_gen/ag_gen.cpp b/src/ag_gen/ag_gen.cpp index 149dbe1..3dbd7ec 100755 --- a/src/ag_gen/ag_gen.cpp +++ b/src/ag_gen/ag_gen.cpp @@ -15,6 +15,7 @@ #include "../util/odometer.h" #include "../util/db_functions.h" +#include "../util/avail_mem.h" #ifdef REDIS @@ -130,7 +131,7 @@ createPostConditions(std::tuple &group, Keyvalue &facts) { * break and continue checking with the next exploit. * 5. Push the new network state onto the frontier to be expanded later. */ -AGGenInstance &AGGen::generate(bool batch_process, int batch_size, int numThrd, int initQSize ) { +AGGenInstance &AGGen::generate(bool batch_process, int batch_size, int numThrd, int initQSize, double mem_threshold) { std::vector exploit_list = instance.exploits; //Create a vector that contains all the groups of exploits to be fired synchonously @@ -170,6 +171,7 @@ AGGenInstance &AGGen::generate(bool batch_process, int batch_size, int numThrd, od_map[num_params] = od.get_all(); } } + /* //might be where to apply parallelization. while (frontier.size() localFrontier; + //double alpha = get_alpha(); + double f_alpha = 0.0; + auto tot_sys_mem = getTotalSystemMemory(); + std::deque localFrontier; localFrontier.emplace_front(frontier[k]); - while (!localFrontier.empty()){//while starts - //std::cout<<"SIZE: "<(localFrontier.size()) * (localFrontier.back().get_size()))/tot_sys_mem; + retrv_counter += 1; + } + //Leave a 30% buffer in alpha + while((f_alpha <= (mem_threshold * 0.7)) && !unex_empty()); + + std::cout << "Retrieved " << retrv_counter << " factbases from the database." << std::endl; + gettimeofday(&tt2,NULL); + total_tt+=(tt2.tv_sec-tt1.tv_sec)*1000.0+(tt2.tv_usec-tt1.tv_usec)/1000.0; + //printf("Retrieving from db took %lf s.\n", total_tt); + } + //std::cout<<"FRONTIER SIZE: "<(e).size()<(e).size()>1){ if(idr_idx.empty()){ @@ -546,9 +576,65 @@ AGGenInstance &AGGen::generate(bool batch_process, int batch_size, int numThrd, hash_map.insert(std::make_pair(new_state.get_hash(instance.facts), new_state.get_id())); //localFrontier.emplace_front(new_state); - save_unexplored_to_db(new_state); - NetworkState new_state = fetch_unexplored(instance.facts); - localFrontier.emplace_front(new_state); + //See memory usage. If it exceeds the threshold, store new states in the DB + double i_alpha = 0.0; + //double i_usage = (sizeof(instance.factbases) + (sizeof(instance.factbases[0]) * instance.factbases.size()) +\ + sizeof(instance.factbase_items) + (sizeof(instance.factbase_items[0]) * instance.factbase_items.size()) +\ + sizeof(instance.edges) + (sizeof(instance.edges[0]) * instance.edges.size())); + //Get the most recent Factbase's size * total number of factbases, rough approximation of *2 to account for factbase_items + double i_usage = instance.factbases.back().get_size() * instance.factbases.size() * 2 + sizeof(instance.edges[0]) * instance.edges.size(); + + i_alpha = i_usage/tot_sys_mem; + if (!localFrontier.empty()) + f_alpha = (static_cast(localFrontier.size()) * (localFrontier.back().get_size()))/tot_sys_mem; + else + f_alpha = 0.0; + //std::cout << "Frontier Alpha: " << f_alpha << std::endl; + //std::cout << "Instance Alpha: " << i_alpha << std::endl; + //std::cout << "Mem Threshold: " << mem_threshold << std::endl; + if (f_alpha >= (mem_threshold/2)) { + std::cout << "Frontier Alpha prior to database storing: " << f_alpha << std::endl; + //std::cout << "Factbase Usage Before: " << sizeof(instance.factbases) + (sizeof(instance.factbases[0]) * instance.factbases.size()) << std::endl; + //std::cout << "Factbase Item Usage Before: " << sizeof(instance.factbase_items) + (sizeof(instance.factbase_items[0]) * instance.factbase_items.size()) << std::endl; + //std::cout << "Edge Usage Before: " << sizeof(instance.edges) + (sizeof(instance.edges[0]) * instance.edges.size()) << std::endl; + + save_unexplored_to_db(new_state); + if (!localFrontier.empty()) + f_alpha = (static_cast(localFrontier.size()) * (localFrontier.back().get_size()))/tot_sys_mem; + else + f_alpha = 0; + std::cout << "Frontier Alpha after database storing: " << f_alpha << std::endl; + + //std::cout << "Storing in database." << std::endl; + } + + //Store new state in database to ensure proper ordering of the FIFO queue + else if (!unex_empty()){ + save_unexplored_to_db(new_state); + } + //Otherwise, we can just store in memory + else { + localFrontier.emplace_front(new_state); + } + + if (i_alpha >= mem_threshold/2){ + std::cout << "Instance Alpha prior to database storing: " << i_alpha << std::endl; + save_ag_to_db(instance, true); + + //Clear vectors and free memory + std::vector().swap(instance.factbases); + std::vector().swap(instance.factbase_items); + std::vector().swap(instance.edges); + + i_usage = (sizeof(instance.factbases) + (sizeof(instance.factbases[0]) * instance.factbases.size()) +\ + sizeof(instance.factbase_items) + (sizeof(instance.factbase_items[0]) * instance.factbase_items.size()) +\ + sizeof(instance.edges) + (sizeof(instance.edges[0]) * instance.edges.size())); + i_alpha = i_usage/tot_sys_mem; + std::cout << "Instance Alpha after database storing: " << i_alpha << std::endl; + + } + + //NetworkState new_state = fetch_unexplored(instance.facts); Edge ed(current_state.get_id(), new_state.get_id(), exploit, assetGroup); ed.set_id(); diff --git a/src/ag_gen/ag_gen.h b/src/ag_gen/ag_gen.h index e539bf0..7d6d098 100755 --- a/src/ag_gen/ag_gen.h +++ b/src/ag_gen/ag_gen.h @@ -68,7 +68,7 @@ class AGGen { AGGen(AGGenInstance &_instance, RedisManager &_rman); #endif - AGGenInstance &generate(bool batch_process, int batch_num, int numThrd, int initQSize); + AGGenInstance &generate(bool batch_process, int batch_num, int numThrd, int initQSize, double mem_threshold); }; #endif // AG_GEN_HPP diff --git a/src/ag_gen/factbase.cpp b/src/ag_gen/factbase.cpp index 65a5d01..3195db9 100755 --- a/src/ag_gen/factbase.cpp +++ b/src/ag_gen/factbase.cpp @@ -196,3 +196,8 @@ void Factbase::print() const { topo.print(); } } + +int Factbase::get_size() { + return (sizeof(id) + (qualities.size() * sizeof(qualities.back())) +\ + (topologies.size() * sizeof(topologies.back()))); +} diff --git a/src/ag_gen/factbase.h b/src/ag_gen/factbase.h index 04eff84..ccc5c2c 100755 --- a/src/ag_gen/factbase.h +++ b/src/ag_gen/factbase.h @@ -47,6 +47,7 @@ class Factbase { void force_set_id(int i); int get_id() const; size_t hash(Keyvalue &factlist) const; + int get_size(); }; #endif diff --git a/src/ag_gen/network_state.cpp b/src/ag_gen/network_state.cpp index eed68fd..808929e 100755 --- a/src/ag_gen/network_state.cpp +++ b/src/ag_gen/network_state.cpp @@ -39,6 +39,8 @@ void NetworkState::force_set_id(int i) { factbase.force_set_id(i); } */ int NetworkState::get_id() { return factbase.get_id(); } +int NetworkState::get_size() { return factbase.get_size(); } + /** * @return The Factbase for the NetworkState */ diff --git a/src/ag_gen/network_state.h b/src/ag_gen/network_state.h index 952a9ae..33d8622 100755 --- a/src/ag_gen/network_state.h +++ b/src/ag_gen/network_state.h @@ -35,6 +35,7 @@ class NetworkState { void set_id(); void force_set_id(int i); int get_id(); + int get_size(); void add_qualities(std::vector q); void add_topologies(std::vector t); diff --git a/src/main.cpp b/src/main.cpp index 6b81feb..e17084c 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -421,6 +421,7 @@ int main(int argc, char *argv[]) { print_usage(); return 0; } + printf("Start init\n"); std::string opt_nm; std::string opt_xp; @@ -436,8 +437,10 @@ int main(int argc, char *argv[]) { bool use_redis = false; bool use_postgres = false; + double alpha = 0.5; + int opt; - while ((opt = getopt(argc, argv, "rb:g:dhc:n:x:t:q:p")) != -1) { + while ((opt = getopt(argc, argv, "rb:g:dhc:n:x:t:q:pa:")) != -1) { switch (opt) { case 'g': should_graph = true; @@ -474,6 +477,10 @@ int main(int argc, char *argv[]) { case 'p': use_postgres = true; break; + case 'a': + //Save a 10% buffer for PSQL ops + alpha = atof(optarg) - 0.1; + break; case '?': if (optopt == 'c') fprintf(stderr, "Option -%c requires an argument.\n", optopt); @@ -517,16 +524,11 @@ int main(int argc, char *argv[]) { else { - std::cout << "No" << std::endl; - //pqxx::connection c; - //pqxx::work w(c); + std::cout << "Error: Not yet implemented. Database must be used.\ + Please use the '-p' argument when running this program." << std::endl; + return(1); } - - - //int a2=1; - //a2=a2+1; - //while(a2); - + //-------------------------------------------- //program block 2: read in network model and exploit pattern and store them in local database @@ -624,25 +626,19 @@ int main(int argc, char *argv[]) { std::cout << "Generating Attack Graph: " << std::flush; AGGen gen(_instance);//use AGGen class to instantiate an obj with the name gen! _instance obj as the parameter! constructor defined in ag_gen.cpp - postinstance = gen.generate(batch_process, batch_size, thread_count, init_qsize); //The method call to generate the attack graph, defined in ag_gen.cpp. + postinstance = gen.generate(batch_process, batch_size, thread_count, init_qsize, alpha); //The method call to generate the attack graph, defined in ag_gen.cpp. std::cout << "Done\n"; - std::cout << "# of edges " < +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////// +// +// process_mem_usage(double &, double &) - takes two doubles by reference, +// attempts to read the system-dependent data for a process' virtual memory +// size and resident set size, and return the results in KB. +// +// On failure, returns 0.0, 0.0 + +void process_mem_usage(double& vm_usage, double& resident_set) +{ + using std::ios_base; + using std::ifstream; + using std::string; + + vm_usage = 0.0; + resident_set = 0.0; + + // 'file' stat seems to give the most reliable results + // + ifstream stat_stream("/proc/self/stat",ios_base::in); + + // dummy vars for leading entries in stat that we don't care about + // + string pid, comm, state, ppid, pgrp, session, tty_nr; + string tpgid, flags, minflt, cminflt, majflt, cmajflt; + string utime, stime, cutime, cstime, priority, nice; + string O, itrealvalue, starttime; + + // the two fields we want + // + unsigned long vsize; + long rss; + + stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr + >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt + >> utime >> stime >> cutime >> cstime >> priority >> nice + >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest + + stat_stream.close(); + + long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages + vm_usage = vsize / 1024.0; + resident_set = rss * page_size_kb; +} + +unsigned long long getTotalSystemMemory() +{ + long pages = sysconf(_SC_PHYS_PAGES); + long page_size = sysconf(_SC_PAGE_SIZE); + return pages * page_size; +} + +int main() +{ + using std::cout; + using std::endl; + + double vm, rss; + process_mem_usage(vm, rss); + unsigned long long tot_mem = getTotalSystemMemory(); + auto percent = rss/tot_mem; + cout << "Percent: " << percent << endl; + cout << "VM: " << vm << "; RSS: " << rss << endl; + cout << "Total Mem: " << tot_mem; + return 0; +} diff --git a/src/util/avail_mem.cpp b/src/util/avail_mem.cpp new file mode 100644 index 0000000..ab27574 --- /dev/null +++ b/src/util/avail_mem.cpp @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include + +#include "avail_mem.h" +////////////////////////////////////////////////////////////////////////////// +// +// process_mem_usage(double &, double &) - takes two doubles by reference, +// attempts to read the system-dependent data for a process' virtual memory +// size and resident set size, and return the results in KB. +// +// On failure, returns 0.0, 0.0 + +void process_mem_usage(double& vm_usage, double& resident_set) +{ + using std::ios_base; + using std::ifstream; + using std::string; + + vm_usage = 0.0; + resident_set = 0.0; + + // 'file' stat seems to give the most reliable results + // + ifstream stat_stream("/proc/self/stat",ios_base::in); + + // dummy vars for leading entries in stat that we don't care about + // + string pid, comm, state, ppid, pgrp, session, tty_nr; + string tpgid, flags, minflt, cminflt, majflt, cmajflt; + string utime, stime, cutime, cstime, priority, nice; + string O, itrealvalue, starttime; + + // the two fields we want + // + unsigned long vsize; + long rss; + + stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr + >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt + >> utime >> stime >> cutime >> cstime >> priority >> nice + >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest + + stat_stream.close(); + + long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages + vm_usage = vsize / 1024.0; + resident_set = rss * page_size_kb; +} + +unsigned long long getTotalSystemMemory() +{ + long pages = sysconf(_SC_PHYS_PAGES); + long page_size = sysconf(_SC_PAGE_SIZE); + return pages * page_size; +} + +double get_alpha() +{ + using std::cout; + using std::endl; + + double vm, rss, alpha; + //vm and rss are KB + process_mem_usage(vm, rss); + //tot_mem is B + unsigned long long tot_mem = getTotalSystemMemory(); + auto percent = (rss*1024)/tot_mem; + //cout << "Percent: " << percent << endl; + //cout << "VM: " << vm << "; RSS: " << rss << endl; + alpha = percent; + return alpha; +} diff --git a/src/util/avail_mem.h b/src/util/avail_mem.h new file mode 100644 index 0000000..3e79ddc --- /dev/null +++ b/src/util/avail_mem.h @@ -0,0 +1,8 @@ +#ifndef _AVAIL_MEM_H +#define _AVAIL_MEM_H + +void process_mem_usage(double& vm_usage, double& resident_set); +unsigned long long getTotalSystemMemory(); +double get_alpha(); + +#endif \ No newline at end of file diff --git a/src/util/db_functions.cpp b/src/util/db_functions.cpp index 4b1d1c1..2844ffc 100755 --- a/src/util/db_functions.cpp +++ b/src/util/db_functions.cpp @@ -587,26 +587,39 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ gettimeofday(&t1,NULL); db.exec("BEGIN;"); if (!factbases.empty()){ - printf("The size of the factbases is %ld\n",factbases.size()); + //printf("The size of the factbases is %ld\n",factbases.size()); std::string factbase_sql_query = "INSERT INTO factbase VALUES "; - + int factbase_counter = 0; + int flag = 0; for (int i = 0; i < factbases.size(); ++i) { + /** redirect state info printing to states.txt file **/ factbases[i].print(); - if (i == 0) { + if (i == 0 || flag == 1) { factbase_sql_query += "(" + std::to_string(factbases[i].get_id()) + ",'" + - std::to_string(factbases[i].hash(factlist)) + "')"; + std::to_string(factbases[i].hash(factlist)) + "')"; + flag = 0; } else { factbase_sql_query += ",(" + std::to_string(factbases[i].get_id()) + ",'" + std::to_string(factbases[i].hash(factlist)) + "')"; } + //Break up query due to memory constraints. Suboptimal approach. + factbase_counter += 1; + if (factbase_counter >= 500){ + factbase_sql_query += ";"; + db.execAsync(factbase_sql_query); + flag = 1; + factbase_sql_query = "INSERT INTO factbase VALUES "; + db.exec("COMMIT;"); + db.exec("BEGIN;"); + } } factbase_sql_query += ";"; db.execAsync(factbase_sql_query); @@ -619,9 +632,12 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ //gettimeofday(&t2,NULL); //printf("The preparation of factbases took %lf ms\n",(t2.tv_sec-t1.tv_sec)*1000.0+(t2.tv_usec-t1.tv_usec)/1000.0); + + //this part takes 1.5s //gettimeofday(&t1,NULL); //potentially bug in forming the string for db storage, check if the first record has a comma before it + /*FACTBASE ITEMS if (!factbase_items.empty()) { int fis=factbase_items.size(); //fis=4; @@ -635,6 +651,7 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ std::string quality_sql_query = ""; std::string topology_sql_query = ""; int sql_index=0; + *///FACTBASE ITEMS /* for (int j = 0; j(items); for (auto qi : quals) { */ - + //UNCOMMENT FOR FACTBASE ITEM STORAGE + /* + int fbi_counter = 0; + int fbi_q_flag = 0; + int fbi_t_flag = 0; for (int j = 0, sql_index = 0; j < factbase_items.size(); ++j) { auto fbi = factbase_items[j]; int id = std::get<1>(fbi); @@ -654,10 +675,12 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ auto quals = std::get<0>(items); auto topo = std::get<1>(items); for (auto qi : quals) { - if (sql_index == 0) + if (sql_index == 0 || fbi_q_flag == 1){ quality_sql_query += "(" + std::to_string(id) + "," + std::to_string(qi.get_encoding()) + ",'quality')"; + fbi_q_flag = 0; + } else quality_sql_query += ",(" + std::to_string(id) + "," + @@ -667,10 +690,12 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ } for (auto ti : topo) { - if (sql_index == 0) + if (sql_index == 0 || fbi_t_flag == 1) { topology_sql_query += "(" + std::to_string(id) + "," + std::to_string(ti.get_encoding()) + ",'topology')"; + fbi_t_flag = 0; + } else topology_sql_query += ",(" + std::to_string(id) + "," + @@ -678,9 +703,23 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ ",'topology')"; sql_index++; } + //Break up query due to memory constraints. Suboptimal approach. + fbi_counter += 1; + if (fbi_counter >= 500){ + item_sql_query += quality_sql_query + topology_sql_query + "ON CONFLICT DO NOTHING;"; + db.exec("BEGIN;"); + db.execAsync(item_sql_query); + db.execAsync("COMMIT;"); + fbi_q_flag = 1; + fbi_t_flag = 1; + item_sql_query = "INSERT INTO factbase_item VALUES "; + quality_sql_query = ""; + topology_sql_query = ""; + } + } - item_sql_query += quality_sql_query + topology_sql_query + "ON CONFLICT DO NOTHING;"; + item_sql_query += quality_sql_query + topology_sql_query + "ON CONFLICT DO NOTHING;"; int thrd_num=omp_get_thread_num(); if(thrd_num==0){ db.exec("BEGIN;"); @@ -705,12 +744,14 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ } } gettimeofday(&t2,NULL); - printf("The saving of factbase and items took %lf ms\n",(t2.tv_sec-t1.tv_sec)*1000.0+(t2.tv_usec-t1.tv_usec)/1000.0); - + //printf("The saving of factbase and items took %lf ms\n",(t2.tv_sec-t1.tv_sec)*1000.0+(t2.tv_usec-t1.tv_usec)/1000.0); + *///FACTBASE ITEMS //this part takes 42.0s //probably where to apply parallelization, this part takes most of the db saving time (>=80%) gettimeofday(&t1,NULL); + int edge_counter = 0; + int edge_flag = 0; if (!edges.empty()) { std::vector edge_queries; edge_queries.resize(edges.size()); @@ -743,15 +784,27 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ int eid = edges[i].get_id(); //int eid = edges[i].set_id(); - if (ii == 0) { + if (ii == 0 | edge_flag == 1) { edge_sql_query += "(" + std::to_string(eid) + "," + ei.first; edge_assets_sql_query += edges[i].get_asset_query(); + edge_flag = 0; } else { edge_sql_query += ",(" + std::to_string(eid) + "," + ei.first; edge_assets_sql_query += "," + edges[i].get_asset_query(); } ++ii; + //Break up query due to memory constraints. Suboptimal approach. + edge_counter += 1; + if (edge_counter >= 500){ + edge_sql_query += "ON CONFLICT DO NOTHING;"; + edge_assets_sql_query += "ON CONFLICT DO NOTHING;"; + db.execAsync(edge_sql_query); + db.execAsync(edge_assets_sql_query); + edge_flag = 1; + edge_sql_query = "INSERT INTO edge VALUES "; + edge_assets_sql_query = "INSERT INTO edge_asset_binding VALUES "; + } } edge_sql_query += " ON CONFLICT DO NOTHING;"; edge_assets_sql_query += " ON CONFLICT DO NOTHING;"; @@ -761,8 +814,8 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ gettimeofday(&t6,NULL); db.execAsync(edge_assets_sql_query); //7.6s gettimeofday(&t7,NULL); - printf("The saving of edges took %lf ms\n",(t6.tv_sec-t5.tv_sec)*1000.0+(t6.tv_usec-t5.tv_usec)/1000.0); - printf("The saving of edges_assets_bingding took %lf ms\n",(t7.tv_sec-t6.tv_sec)*1000.0+(t7.tv_usec-t6.tv_usec)/1000.0); + // printf("The saving of edges took %lf ms\n",(t6.tv_sec-t5.tv_sec)*1000.0+(t6.tv_usec-t5.tv_usec)/1000.0); + //printf("The saving of edges_assets_bingding took %lf ms\n",(t7.tv_sec-t6.tv_sec)*1000.0+(t7.tv_usec-t6.tv_usec)/1000.0); //----second method to store into db //---------------------------------- @@ -837,7 +890,7 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ } gettimeofday(&t2,NULL); - printf("The saving of edge and edge_asset_binding took %lf ms\n",(t2.tv_sec-t1.tv_sec)*1000.0+(t2.tv_usec-t1.tv_usec)/1000.0);//42.0s + //printf("The saving of edge and edge_asset_binding took %lf ms\n",(t2.tv_sec-t1.tv_sec)*1000.0+(t2.tv_usec-t1.tv_usec)/1000.0);//42.0s //this part takes around 8.6s gettimeofday(&t1,NULL); @@ -860,7 +913,7 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue){ } db.execAsync("COMMIT;"); gettimeofday(&t2,NULL); - printf("The saving of keyvalue took %lf ms\n",(t2.tv_sec-t1.tv_sec)*1000.0+(t2.tv_usec-t1.tv_usec)/1000.0); + //printf("The saving of keyvalue took %lf ms\n",(t2.tv_sec-t1.tv_sec)*1000.0+(t2.tv_usec-t1.tv_usec)/1000.0); } void save_unexplored_to_db(NetworkState netstate) { @@ -997,4 +1050,32 @@ NetworkState fetch_unexplored(Keyvalue &facts){ fetched_state.force_set_id(id); return fetched_state; +} + +bool unex_empty() +{ + std::vector row = db.exec("SELECT count(*) FROM unex_state_q LIMIT 1;"); + for (auto &r : row){ + auto count = std::stoi(r[0]); + if (count == 0) + return true; + else + return false; + } +} + +int get_num_states() +{ + std::vector row = db.exec("SELECT count(*) AS exact_count FROM factbase;"); + for (auto &r : row) { + return std::stoi(r[0]); + } +} + +int get_num_edges() +{ + std::vector row = db.exec("SELECT count(*) AS exact_count FROM edge;"); + for (auto &r : row) { + return std::stoi(r[0]); + } } \ No newline at end of file diff --git a/src/util/db_functions.h b/src/util/db_functions.h index aebd00b..f5db12a 100755 --- a/src/util/db_functions.h +++ b/src/util/db_functions.h @@ -79,5 +79,9 @@ void save_ag_to_db(AGGenInstance &instance, bool save_keyvalue); void save_unexplored_to_db(NetworkState netstate); NetworkState fetch_unexplored(Keyvalue &facts); +bool unex_empty(); + +int get_num_states(); +int get_num_edges(); #endif