333 lines
7.8 KiB
C++
333 lines
7.8 KiB
C++
|
/*=============================================================================
|
||
|
# Filename: gtest.cpp
|
||
|
# Author: syzz
|
||
|
# Mail: 1181955272@qq.com
|
||
|
# Last Modified: 2015-09-02 00:04
|
||
|
# Description: load index once and query, there are several ways to use this program:
|
||
|
1. ./gtest test all datasets and corresponding queries
|
||
|
2. ./gtest --help simplified as -h, will print the help message
|
||
|
3. ./gtest -f DS_PATH load/test a specified dataset, with all corresponding queries
|
||
|
4. ./gtest -d FD_PATH load/test a dataset folder(like WatDiv/), with all corresponding queries
|
||
|
5. ./gtest -q DB_PATH q1 q2... test a loaded database with given queries(no limit to db and query)
|
||
|
=============================================================================*/
|
||
|
|
||
|
//#include <stdio.h>
|
||
|
//#include <string.h>
|
||
|
//#include <stdlib.h>
|
||
|
//#include <dirent.h>
|
||
|
//#include <unistd.h>
|
||
|
#include "../Database/Database.h"
|
||
|
#include "../Util/Util.h"
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
#define NUM 4
|
||
|
|
||
|
char line1[] = "--------------------------------------------------";
|
||
|
char line2[] = "##################################################";
|
||
|
string path = "/media/wip/common/data/";
|
||
|
string db[NUM] = {"WatDiv/", "LUBM/", "DBpedia/", "Yago/"};
|
||
|
|
||
|
//not achieved, so do not use
|
||
|
void
|
||
|
build_logs()
|
||
|
{
|
||
|
system("rm -rf result.log/");
|
||
|
system("rm -rf time.log/");
|
||
|
system("mkdir result.log");
|
||
|
system("mkdir time.log");
|
||
|
int i;
|
||
|
string cmd;
|
||
|
for(i = 0; i < NUM; ++i)
|
||
|
{
|
||
|
cmd = string("mkdir result.log/\"") + db[i] + "\""; //in case of special characters like &
|
||
|
system(cmd.c_str());
|
||
|
cmd = string("mkdir time.log/\"") + db[i] + "\"";
|
||
|
system(cmd.c_str());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool //if satisfy suffix; case sensitive
|
||
|
judge(const char* p, const char* p0) //both not empty
|
||
|
{
|
||
|
int len = strlen(p), len0 = strlen(p0);
|
||
|
while(len0 > 0 && len > 0)
|
||
|
{
|
||
|
len--;
|
||
|
len0--;
|
||
|
if(p[len] != p0[len0])
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
string
|
||
|
getQueryFromFile(const char* path)
|
||
|
{
|
||
|
char buf[10000];
|
||
|
ifstream fin(path);
|
||
|
if(!fin)
|
||
|
{
|
||
|
printf("can not open %s\n", path);
|
||
|
return "";
|
||
|
}
|
||
|
memset(buf, 0, sizeof(buf));
|
||
|
stringstream ss;
|
||
|
while(!fin.eof())
|
||
|
{
|
||
|
fin.getline(buf, 9999);
|
||
|
ss << buf << "\n";
|
||
|
}
|
||
|
fin.close();
|
||
|
return ss.str();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
help()
|
||
|
{
|
||
|
printf("\
|
||
|
/*=============================================================================\n\
|
||
|
# Filename: gtest.cpp\n\
|
||
|
# Author: syzz\n\
|
||
|
# Mail: 1181955272@qq.com\n\
|
||
|
# Description: load index once and query, there are several ways to use this program:\n\
|
||
|
1. ./gtest test all datasets and corresponding queries\n\
|
||
|
2. ./gtest --help simplified as -h, will print the help message\n\
|
||
|
3. ./gtest -f DS_PATH load/test a specified dataset, with all corresponding queries\n\
|
||
|
4. ./gtest -d FD_PATH load/test a dataset folder(like WatDiv/), with all corresponding queries\n\
|
||
|
5. ./gtest -q DB_PATH q1 q2... test a loaded database with given queries(no limit to db and query)\n\
|
||
|
=============================================================================*/\n\
|
||
|
");
|
||
|
}
|
||
|
|
||
|
FILE *fp0 = NULL, *fp1 = NULL, *fp2 = NULL;
|
||
|
|
||
|
void //single dataset, single query
|
||
|
runSS(Database* _db, string qf) //given a query file
|
||
|
{
|
||
|
string query = getQueryFromFile(qf.c_str());
|
||
|
if(query.empty())
|
||
|
{
|
||
|
fprintf(fp0, "this query is empty:\n%s\n", qf.c_str());
|
||
|
fflush(fp0);
|
||
|
return;
|
||
|
//continue;
|
||
|
}
|
||
|
fprintf(fp0, "%s\n", qf.c_str());
|
||
|
fflush(fp0);
|
||
|
//getchar();getchar();
|
||
|
ResultSet _rs;
|
||
|
long tv_begin, tv_final;
|
||
|
tv_begin = Util::get_cur_time();
|
||
|
//fprintf(fp0, "begin to query!\n");
|
||
|
//fflush(fp0);
|
||
|
_db->query(query, _rs, stdout);
|
||
|
//fprintf(fp0, "finish this query!\n");
|
||
|
tv_final = Util::get_cur_time();
|
||
|
//print to logs
|
||
|
fprintf(fp1, "%s\n%ld\n%s\n", qf.c_str(), tv_final - tv_begin, line1);//time is standarded as ms
|
||
|
fprintf(fp2, "%s\n%s%s\n", qf.c_str(), _rs.to_str().c_str(), line1);
|
||
|
fflush(fp0);
|
||
|
fflush(fp1);
|
||
|
fflush(fp2);
|
||
|
}
|
||
|
|
||
|
void //single dataset, multi queries
|
||
|
runSM(Database* _db, string qd) //given a query directory
|
||
|
{
|
||
|
DIR* dp2;
|
||
|
struct dirent* p2;
|
||
|
dp2 = opendir(qd.c_str());
|
||
|
//finish all queries
|
||
|
while((p2 = readdir(dp2)) != NULL)
|
||
|
{
|
||
|
if(!judge(p2->d_name, ".sql"))
|
||
|
continue;
|
||
|
string file = qd + string(p2->d_name);
|
||
|
runSS(_db, file);
|
||
|
}
|
||
|
fprintf(fp0, "finish all queries!\n");
|
||
|
fflush(fp0);
|
||
|
closedir(dp2);
|
||
|
fprintf(fp0, "ok to close dp2!\n");
|
||
|
}
|
||
|
|
||
|
void //multi datasets, multi queries
|
||
|
runMM(string df) //given dataset folder, end with /
|
||
|
{
|
||
|
DIR *dp1;
|
||
|
struct dirent *p1;
|
||
|
string s1, s2, cmd;
|
||
|
Database* _db;
|
||
|
s1 = df + string("database/");
|
||
|
s2 = df + string("query/");
|
||
|
dp1 = opendir(s1.c_str());
|
||
|
while((p1 = readdir(dp1)) != NULL)
|
||
|
{
|
||
|
if(!judge(p1->d_name, ".nt"))
|
||
|
continue;
|
||
|
system("echo 3 > /proc/sys/vm/drop_caches");
|
||
|
//build the database index first
|
||
|
string db_folder = s1 + string(p1->d_name);
|
||
|
fprintf(fp0, "%s\n", db_folder.c_str());
|
||
|
cmd = string("./gload \"") + string(p1->d_name) + "\" \"" + db_folder + "\" > \"gload_" + string(p1->d_name) + ".log\""; //NOTICE:\" is used to ensure file name with &(etc...) will work ok!
|
||
|
fprintf(fp0, "%s\n", cmd.c_str());
|
||
|
system(cmd.c_str());
|
||
|
fprintf(fp0, "ok to load database!\n");
|
||
|
//getchar();getchar();
|
||
|
//then load the index
|
||
|
_db = new Database(string(p1->d_name));
|
||
|
_db->load();
|
||
|
fprintf(fp0, "ok to load index!\n");
|
||
|
//print to logs
|
||
|
fprintf(fp1, "%s\n%s\n", p1->d_name, line1);
|
||
|
fprintf(fp2, "%s\n%s\n", p1->d_name, line1);
|
||
|
|
||
|
runSM(_db, s2);
|
||
|
|
||
|
fflush(fp0);
|
||
|
fprintf(fp1, "%s\n", line2);
|
||
|
fprintf(fp2, "%s\n", line2);
|
||
|
//NOTICE:may double free due to ~Database
|
||
|
//to remove one when finished, should clean firstly like ~Database()
|
||
|
delete _db;//_db->release(fp0);
|
||
|
cmd = string("rm -rf \"") + string(p1->d_name) + string("\"");
|
||
|
system(cmd.c_str());
|
||
|
fprintf(fp0, "ok to remove %s\n", p1->d_name);
|
||
|
fflush(fp0);
|
||
|
fflush(fp1);
|
||
|
fflush(fp2);
|
||
|
}
|
||
|
closedir(dp1);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
clean()
|
||
|
{
|
||
|
//it is ok to check like this here!
|
||
|
//in other situations, notice that fp is not null after closed!
|
||
|
if(fp0 != NULL)
|
||
|
{
|
||
|
fclose(fp0);
|
||
|
fp0 = NULL;
|
||
|
}
|
||
|
if(fp1 != NULL)
|
||
|
{
|
||
|
fclose(fp1);
|
||
|
fp1 = NULL;
|
||
|
}
|
||
|
if(fp2 != NULL)
|
||
|
{
|
||
|
fclose(fp2);
|
||
|
fp2 = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
EXIT(int ret)
|
||
|
{
|
||
|
clean();
|
||
|
exit(ret);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
main(int argc, const char* argv[])
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
Util util;
|
||
|
#endif
|
||
|
//BETTER: enable user to assign the files for log
|
||
|
int i, j;
|
||
|
fp0 = fopen("run.log", "w+");
|
||
|
if(fp0 == NULL)
|
||
|
{
|
||
|
printf("open error!\n");
|
||
|
EXIT(1);
|
||
|
}
|
||
|
//build_logs();
|
||
|
fp1 = fopen("time.log", "w+");
|
||
|
if(fp1 == NULL)
|
||
|
{
|
||
|
printf("open error!\n");
|
||
|
EXIT(1);
|
||
|
}
|
||
|
fp2 = fopen("result.log", "w+");
|
||
|
if(fp2 == NULL)
|
||
|
{
|
||
|
printf("open error!\n");
|
||
|
EXIT(1);
|
||
|
}
|
||
|
|
||
|
switch(argc)
|
||
|
{
|
||
|
case 1:
|
||
|
help();
|
||
|
printf("this command will do a complete test for Gstore, do you want to continue?YN\n");
|
||
|
char c;
|
||
|
i = 0;
|
||
|
while(scanf("%c", &c))
|
||
|
{
|
||
|
if(c == 'Y' || c == 'y')
|
||
|
{
|
||
|
for(j = 0; j < 4; ++j)
|
||
|
{
|
||
|
runMM(path+db[j]);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
else if(c == 'N' || c == 'n')
|
||
|
EXIT(0);
|
||
|
i++;
|
||
|
if(i > 10) //try no more than 10 times
|
||
|
EXIT(1);
|
||
|
}
|
||
|
break;
|
||
|
case 2:
|
||
|
if(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
|
||
|
{
|
||
|
help();
|
||
|
EXIT(0);
|
||
|
}
|
||
|
else
|
||
|
EXIT(1);
|
||
|
case 3:
|
||
|
if(strcmp(argv[1], "-f") == 0) //this file must be in db[]/database/, end with ".nt"
|
||
|
{
|
||
|
//TODO:use judge to check if is .nt file
|
||
|
int k = strlen(argv[2]) - 1;
|
||
|
string db = string(argv[2]);
|
||
|
while(k >= 0)
|
||
|
{
|
||
|
if(db[k] == '/')
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
string s = db.substr(0, k+1) + "../query/";
|
||
|
//DIR* dp = opendir(s.c_str());
|
||
|
//TODO: gload the dataset and build a new function!
|
||
|
printf("not achieved!\n");
|
||
|
}
|
||
|
else if(strcmp(argv[1], "-d") == 0)
|
||
|
{
|
||
|
runMM(string(argv[2]) + "/");
|
||
|
}
|
||
|
else
|
||
|
EXIT(1);
|
||
|
break;
|
||
|
default: //> 3
|
||
|
if(strcmp(argv[1], "-q") == 0)
|
||
|
{
|
||
|
//TODO: user must gload first?
|
||
|
printf("not achieved!\n");
|
||
|
}
|
||
|
else
|
||
|
EXIT(1);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
clean();
|
||
|
return 0;
|
||
|
}
|
||
|
|