gStore/Server/Client.cpp

330 lines
7.3 KiB
C++

/*=============================================================================
# Filename: Client.cpp
# Author: Bookug Lobert
# Mail: 1181955272@qq.com
# Last Modified: 2016-02-23 13:39
# Description: implement functions in Client.h
=============================================================================*/
#include"Client.h"
using namespace std;
Client::Client()
{
this->ip = Socket::DEFAULT_SERVER_IP;
this->port = Socket::DEFAULT_CONNECT_PORT;
}
Client::Client(string _ip, unsigned short _port)
{
this->ip = _ip;
this->port = _port;
}
Client::Client(unsigned short _port)
{
this->ip = Socket::DEFAULT_SERVER_IP;
this->port = _port;
}
Client::~Client()
{
}
bool Client::connectServer()
{
bool flag = this->socket.create();
if (!flag)
{
cerr << "cannot create socket. @Client::connectServer" << endl;
return false;
}
flag = this->socket.connect(this->ip, this->port);
if (!flag)
{
cerr << "cannot connect to server. @Client::connectServer" << endl;
return false;
}
return true;
}
bool Client::disconnectServer()
{
bool flag = this->socket.close();
return flag;
}
bool Client::send(const string& _msg)
{
bool flag = this->socket.send(_msg);
return flag;
}
bool Client::receiveResponse(string& _recv_msg)
{
bool flag = this->socket.recv(_recv_msg);
return flag;
}
void Client::run()
{
string cmd;
#ifdef READLINE_ON
char *buf, prompt[] = "gsql>";
//printf("Type `help` for information of all commands\n");
//printf("Type `help command_t` for detail of command_t\n");
rl_bind_key('\t', rl_complete);
//QUERY: should add ';'?
while(true)
{
//BETTER:write in multi lines as in below comments
buf = readline(prompt);
if(buf == NULL)
continue;
else
add_history(buf);
if(strncmp(buf, "help", 4) == 0)
{
if(strcmp(buf, "help") == 0)
{
//print commands message
printf("help - print commands message\n");
printf("quit - quit the console normally\n");
printf("import - build a database for a given dataset\n");
printf("load - load an existen database\n");
printf("unload - unload an existen database\n");
printf("sparql - load query from the second argument\n");
printf("show - show the current database's name\n");
}
else
{
//TODO: help for a given command
}
continue;
}
else if(strcmp(buf, "quit") == 0)
break;
else if(strncmp(buf, "import", 6) != 0 && strncmp(buf, "load", 4) != 0 && strncmp(buf, "unload", 6) != 0 && strncmp(buf, "sparql", 6) != 0 && strncmp(buf, "show", 4) != 0)
{
printf("unknown commands\n");
continue;
}
string query_file;
string query;
FILE* fp = stdout; ///default to output on screen
bool ifredirect = false;
//BETTER:build a parser for this console
//spaces/tabs can be before commands
if(strncmp(buf, "sparql", 6) == 0)
{
//NOTICE: if using query string, '>' is ok to exist!
char* rp = buf;
int pos = strlen(buf) - 1;
while(pos > -1)
{
if(*(rp+pos) == '"')
{
break;
}
else if(*(rp+pos) == '>')
{
ifredirect = true;
break;
}
pos--;
}
rp += pos;
//DEBUG:redirect sometimes not work for path query
char* p = buf + strlen(buf) - 1;
if(ifredirect)
{
printf("redirected!\n");
char* tp = p;
while(*tp == ' ' || *tp == '\t')
tp--;
*(tp+1) = '\0';
tp = rp + 1;
while(*tp == ' ' || *tp == '\t')
tp++;
printf("redirect: %s\n", tp);
fp = fopen(tp, "w"); //NOTICE:not judge here!
p = rp - 1; //NOTICE: all separated with ' ' or '\t'
}
while(*p == ' ' || *p == '\t' || *p == '"') //set the end of path
p--;
*(p+1) = '\0';
p = buf + 6;
while(*p == ' ' || *p == '\t') //acquire the start of path
p++;
bool isPath = true;
if(*p == '"')
{
isPath = false;
p++;
}
char* q;
//BETTER:get real path in server port?
if(isPath)
{
//TODO: support the soft links(or hard links)
//there are also readlink and getcwd functions for help
//http://linux.die.net/man/2/readlink
//NOTICE:getcwd and realpath cannot acquire the real path of file
//in the same directory and the program is executing when the
//system starts running
//NOTICE: use realpath(p, NULL) is ok, but need to free the memory
q = realpath(p, NULL); //QUERY:still not work for soft links
#ifdef DEBUG_PRECISE
printf("%s\n", p);
#endif
if(q == NULL)
{
printf("invalid path!\n");
free(q);
free(buf);
continue;
}
else
printf("%s\n", q);
//query = getQueryFromFile(p);
query = Util::getQueryFromFile(q);
}
else
{
//BETTER:check query in ""
query = string(p);
}
if(query.empty())
{
if(isPath)
free(q);
//free(resolved_path);
free(buf);
if(ifredirect)
fclose(fp);
continue;
}
printf("query is:\n%s\n\n", query.c_str());
if(isPath)
free(q);
cmd = string("query ") + query;
}
else if(strncmp(buf, "show", 4) == 0)
{
cmd = string("show databases");
}
else
{
cmd = string(buf);
}
printf("%s\n", cmd.c_str());
free(buf);
//free(resolved_path);
#ifdef DEBUG_PRECISE
printf("after buf freed!\n");
#endif
//interacte with server
bool flag = this->connectServer();
if(!flag)
{
cerr << "connect server error. @Client::run" << endl;
if(ifredirect)
fclose(fp);
continue;
}
flag = this->send(cmd);
if(!flag)
{
cerr << "sent message error. @Client::run" << endl;
if(ifredirect)
fclose(fp);
continue;
}
string recv_msg;
flag = this->receiveResponse(recv_msg);
//BETTER:the string maybe too large?
fprintf(fp, "%s\n", recv_msg.c_str());
this->disconnectServer();
if(!flag)
{
cerr << "disconnect server error. @Client::run" << endl;
if(ifredirect)
fclose(fp);
continue;
}
}
//#else
//while (true)
//{
// while(true)
// {
// //BETTER:readline and parser
// cout << "->";
// string line;
// getline(cin, line);
// int line_len = line.size();
// if (line_len >0 && line[line_len-1] == ';')
// {
// line.resize(line_len - 1);
// cmd += line;
// break;
// }
// cmd += line + "\n";
// }
//
// //cout << "input end" << endl;
//
// if(cmd == "quit")
// {
// break;
// }
//
// bool flag = this->connectServer();
// if (!flag)
// {
// cerr << "connect server error. @Client::run" << endl;
// continue;
// }
//
// flag = this->send(cmd);
// if (!flag)
// {
// cerr << "sent message error. @Client::run" << endl;
// continue;
// }
//
// string recv_msg;
// flag = this->receiveResponse(recv_msg);
// cout << recv_msg << endl;
//
// this->disconnectServer();
// if (!flag)
// {
// cerr << "disconnect server error. @Client::run" << endl;
// continue;
// }
//}
#endif
}