You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-30 19:23:07 +03:00
Reformat all code to coding standard
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -1,85 +1,86 @@
|
||||
|
||||
/* A Bison parser, made by GNU Bison 2.4.1. */
|
||||
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
CHAR_CONST = 258,
|
||||
RELOP = 259,
|
||||
LOGICOP = 260,
|
||||
QFEP_SELECT = 261,
|
||||
QFEP_FROM = 262,
|
||||
QFEP_WHERE = 263,
|
||||
GROUPBY = 264,
|
||||
OBJNAME = 265,
|
||||
INT_CONST = 266,
|
||||
LIMIT = 267,
|
||||
ORDERBY = 268,
|
||||
ASC = 269,
|
||||
DESC = 270,
|
||||
AS = 271,
|
||||
FUNC = 272
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
{
|
||||
|
||||
/* Line 1676 of yacc.c */
|
||||
#line 31 "qfeparser.ypp"
|
||||
|
||||
execplan::ReturnedColumn* rcp;
|
||||
std::string* cp;
|
||||
std::pair<int, std::string>* cvp;
|
||||
|
||||
|
||||
|
||||
/* Line 1676 of yacc.c */
|
||||
#line 77 "bison-win.hpp"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE qfelval;
|
||||
|
||||
|
||||
|
||||
/* A Bison parser, made by GNU Bison 2.4.1. */
|
||||
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype
|
||||
{
|
||||
CHAR_CONST = 258,
|
||||
RELOP = 259,
|
||||
LOGICOP = 260,
|
||||
QFEP_SELECT = 261,
|
||||
QFEP_FROM = 262,
|
||||
QFEP_WHERE = 263,
|
||||
GROUPBY = 264,
|
||||
OBJNAME = 265,
|
||||
INT_CONST = 266,
|
||||
LIMIT = 267,
|
||||
ORDERBY = 268,
|
||||
ASC = 269,
|
||||
DESC = 270,
|
||||
AS = 271,
|
||||
FUNC = 272
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
{
|
||||
|
||||
/* Line 1676 of yacc.c */
|
||||
#line 31 "qfeparser.ypp"
|
||||
|
||||
execplan::ReturnedColumn* rcp;
|
||||
std::string* cp;
|
||||
std::pair<int, std::string>* cvp;
|
||||
|
||||
|
||||
|
||||
/* Line 1676 of yacc.c */
|
||||
#line 77 "bison-win.hpp"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE qfelval;
|
||||
|
||||
|
||||
|
@ -35,138 +35,152 @@ namespace
|
||||
{
|
||||
void usage()
|
||||
{
|
||||
cout << "usage: cli [-h] [-s serverip] [-p port] [-c schema] <query>" << endl;
|
||||
cout << '\t' << "-s serverip connect to serverip instead of 127.0.0.1" << endl;
|
||||
cout << '\t' << "-p port connect on port instead of 9198" << endl;
|
||||
cout << '\t' << "-c schema use schema as default instead of tpch1" << endl;
|
||||
cout << '\t' << "-h display this help" << endl;
|
||||
cout << "usage: cli [-h] [-s serverip] [-p port] [-c schema] <query>" << endl;
|
||||
cout << '\t' << "-s serverip connect to serverip instead of 127.0.0.1" << endl;
|
||||
cout << '\t' << "-p port connect on port instead of 9198" << endl;
|
||||
cout << '\t' << "-c schema use schema as default instead of tpch1" << endl;
|
||||
cout << '\t' << "-h display this help" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
opterr = 0;
|
||||
int c;
|
||||
string serverip("127.0.0.1");
|
||||
string schema("tpch1");
|
||||
short PortNo = 9198;
|
||||
while ((c = getopt(argc, argv, "s:c:p:h")) != -1)
|
||||
switch (c)
|
||||
{
|
||||
case 's':
|
||||
serverip = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
schema = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
PortNo = atoi(optarg);
|
||||
if (PortNo == 0)
|
||||
{
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
opterr = 0;
|
||||
int c;
|
||||
string serverip("127.0.0.1");
|
||||
string schema("tpch1");
|
||||
short PortNo = 9198;
|
||||
|
||||
if (argc - optind < 1)
|
||||
{
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
while ((c = getopt(argc, argv, "s:c:p:h")) != -1)
|
||||
switch (c)
|
||||
{
|
||||
case 's':
|
||||
serverip = optarg;
|
||||
break;
|
||||
|
||||
string query(argv[optind+0]);
|
||||
case 'c':
|
||||
schema = optarg;
|
||||
break;
|
||||
|
||||
SockType fd = -1;
|
||||
case 'p':
|
||||
PortNo = atoi(optarg);
|
||||
|
||||
if (PortNo == 0)
|
||||
{
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (argc - optind < 1)
|
||||
{
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
string query(argv[optind + 0]);
|
||||
|
||||
SockType fd = -1;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
WSAData wsadata;
|
||||
const WORD minVersion = MAKEWORD(2, 2);
|
||||
if (WSAStartup(minVersion, &wsadata) != 0)
|
||||
cerr << "networking startup error: " << IDBSysErrorStr(WSAGetLastError()) << endl;
|
||||
WSAData wsadata;
|
||||
const WORD minVersion = MAKEWORD(2, 2);
|
||||
|
||||
if (WSAStartup(minVersion, &wsadata) != 0)
|
||||
cerr << "networking startup error: " << IDBSysErrorStr(WSAGetLastError()) << endl;
|
||||
|
||||
#endif
|
||||
fd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (fd < 0)
|
||||
{
|
||||
fd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
cerr << "socket create error: " << IDBSysErrorStr(WSAGetLastError()) << endl;
|
||||
cerr << "socket create error: " << IDBSysErrorStr(WSAGetLastError()) << endl;
|
||||
#else
|
||||
cerr << "socket create error: " << strerror(errno) << endl;
|
||||
cerr << "socket create error: " << strerror(errno) << endl;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
struct sockaddr_in serv_addr;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* res=0;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = PF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
rc = getaddrinfo(serverip.c_str(), 0, &hints, &res);
|
||||
if (rc != 0)
|
||||
{
|
||||
cerr << "Error resolving '" << serverip << "': " << gai_strerror(rc) << endl;
|
||||
return 1;
|
||||
}
|
||||
sockaddr_in* sain=0;
|
||||
sain = reinterpret_cast<sockaddr_in*>(res->ai_addr);
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = PF_INET;
|
||||
serv_addr.sin_addr = sain->sin_addr;
|
||||
serv_addr.sin_port = htons(PortNo);
|
||||
freeaddrinfo(res);
|
||||
int rc = 0;
|
||||
struct sockaddr_in serv_addr;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* res = 0;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = PF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
rc = getaddrinfo(serverip.c_str(), 0, &hints, &res);
|
||||
|
||||
rc = ::connect(fd, (sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||
if (rc < 0)
|
||||
{
|
||||
if (rc != 0)
|
||||
{
|
||||
cerr << "Error resolving '" << serverip << "': " << gai_strerror(rc) << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sockaddr_in* sain = 0;
|
||||
sain = reinterpret_cast<sockaddr_in*>(res->ai_addr);
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = PF_INET;
|
||||
serv_addr.sin_addr = sain->sin_addr;
|
||||
serv_addr.sin_port = htons(PortNo);
|
||||
freeaddrinfo(res);
|
||||
|
||||
rc = ::connect(fd, (sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
cerr << "socket connect error: " << IDBSysErrorStr(WSAGetLastError()) << endl;
|
||||
WSACleanup();
|
||||
cerr << "socket connect error: " << IDBSysErrorStr(WSAGetLastError()) << endl;
|
||||
WSACleanup();
|
||||
#else
|
||||
cerr << "socket connect error: " << strerror(errno) << endl;
|
||||
cerr << "socket connect error: " << strerror(errno) << endl;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
socketio::writeString(fd, schema);
|
||||
socketio::writeString(fd, query);
|
||||
socketio::writeString(fd, schema);
|
||||
socketio::writeString(fd, query);
|
||||
|
||||
uint32_t flag=0;
|
||||
string row;
|
||||
row = socketio::readString(fd);
|
||||
if (row != "OK")
|
||||
{
|
||||
cerr << "query failed: " << row << endl;
|
||||
goto bailout;
|
||||
}
|
||||
uint32_t flag = 0;
|
||||
string row;
|
||||
row = socketio::readString(fd);
|
||||
|
||||
row = socketio::readString(fd);
|
||||
while (!row.empty())
|
||||
{
|
||||
cout << row << endl;
|
||||
row = socketio::readString(fd);
|
||||
}
|
||||
if (row != "OK")
|
||||
{
|
||||
cerr << "query failed: " << row << endl;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
flag=0;
|
||||
SockWriteFcn(fd, &flag, 4);
|
||||
row = socketio::readString(fd);
|
||||
|
||||
while (!row.empty())
|
||||
{
|
||||
cout << row << endl;
|
||||
row = socketio::readString(fd);
|
||||
}
|
||||
|
||||
flag = 0;
|
||||
SockWriteFcn(fd, &flag, 4);
|
||||
bailout:
|
||||
::shutdown(fd, SHUT_RDWR);
|
||||
::shutdown(fd, SHUT_RDWR);
|
||||
#ifdef _MSC_VER
|
||||
::closesocket(fd);
|
||||
WSACleanup();
|
||||
::closesocket(fd);
|
||||
WSACleanup();
|
||||
#else
|
||||
::close(fd);
|
||||
::close(fd);
|
||||
#endif
|
||||
fd = -1;
|
||||
fd = -1;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -22,123 +22,128 @@ namespace utils
|
||||
|
||||
ConstantColumn* createConstCol(const string& valstr)
|
||||
{
|
||||
ConstantColumn* cc= new ConstantColumn(valstr);
|
||||
cc->alias(valstr);
|
||||
return cc;
|
||||
ConstantColumn* cc = new ConstantColumn(valstr);
|
||||
cc->alias(valstr);
|
||||
return cc;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ConstantColumn* createConstCol(const string& valstr, T val)
|
||||
{
|
||||
ConstantColumn* cc= new ConstantColumn(valstr, val);
|
||||
cc->alias(valstr);
|
||||
return cc;
|
||||
ConstantColumn* cc = new ConstantColumn(valstr, val);
|
||||
cc->alias(valstr);
|
||||
return cc;
|
||||
}
|
||||
|
||||
SimpleFilter* createSimpleFilter
|
||||
(
|
||||
boost::shared_ptr<CalpontSystemCatalog>& csc,
|
||||
const CalpontSystemCatalog::TableColName& tcn,
|
||||
const string& opstr,
|
||||
ConstantColumn* cc
|
||||
)
|
||||
(
|
||||
boost::shared_ptr<CalpontSystemCatalog>& csc,
|
||||
const CalpontSystemCatalog::TableColName& tcn,
|
||||
const string& opstr,
|
||||
ConstantColumn* cc
|
||||
)
|
||||
{
|
||||
SimpleFilter* lsf = new SimpleFilter();
|
||||
SimpleFilter* lsf = new SimpleFilter();
|
||||
|
||||
Operator* op = new Operator();
|
||||
op->data(opstr);
|
||||
CalpontSystemCatalog::ColType ccct;
|
||||
ccct = op->resultType();
|
||||
ccct.colDataType = cc->resultType().colDataType;
|
||||
op->operationType(ccct);
|
||||
Operator* op = new Operator();
|
||||
op->data(opstr);
|
||||
CalpontSystemCatalog::ColType ccct;
|
||||
ccct = op->resultType();
|
||||
ccct.colDataType = cc->resultType().colDataType;
|
||||
op->operationType(ccct);
|
||||
|
||||
SOP sop(op);
|
||||
lsf->op(sop);
|
||||
SOP sop(op);
|
||||
lsf->op(sop);
|
||||
|
||||
CalpontSystemCatalog::OID oid = csc->lookupOID(tcn);
|
||||
CalpontSystemCatalog::ColType ct = csc->colType(oid);
|
||||
CalpontSystemCatalog::OID oid = csc->lookupOID(tcn);
|
||||
CalpontSystemCatalog::ColType ct = csc->colType(oid);
|
||||
|
||||
SimpleColumn* sc = new SimpleColumn();
|
||||
sc->schemaName(tcn.schema);
|
||||
sc->tableName(tcn.table);
|
||||
sc->tableAlias(tcn.table);
|
||||
sc->columnName(tcn.column);
|
||||
sc->oid(oid);
|
||||
sc->resultType(ct);
|
||||
sc->alias(tcn.toString());
|
||||
SimpleColumn* sc = new SimpleColumn();
|
||||
sc->schemaName(tcn.schema);
|
||||
sc->tableName(tcn.table);
|
||||
sc->tableAlias(tcn.table);
|
||||
sc->columnName(tcn.column);
|
||||
sc->oid(oid);
|
||||
sc->resultType(ct);
|
||||
sc->alias(tcn.toString());
|
||||
|
||||
lsf->lhs(sc);
|
||||
lsf->rhs(cc);
|
||||
lsf->lhs(sc);
|
||||
lsf->rhs(cc);
|
||||
|
||||
return lsf;
|
||||
return lsf;
|
||||
}
|
||||
|
||||
void appendSimpleFilter
|
||||
(
|
||||
ParseTree*& ptree,
|
||||
SimpleFilter* filter
|
||||
)
|
||||
(
|
||||
ParseTree*& ptree,
|
||||
SimpleFilter* filter
|
||||
)
|
||||
{
|
||||
if( ptree->data() == 0 )
|
||||
{
|
||||
// degenerate case, this filter goes at this node
|
||||
ptree->data( filter );
|
||||
}
|
||||
else if( ptree->right() == 0 && ptree->left() == 0 )
|
||||
{
|
||||
// this will be the case when there is a single node in the tree
|
||||
// that contains a filter. Here we want to make the root node an
|
||||
// 'and' operator, push the existing down to the lhs and make a
|
||||
// new node for the new filter
|
||||
ParseTree* newLhs = new ParseTree( ptree->data() );
|
||||
ParseTree* newRhs = new ParseTree( filter );
|
||||
if ( ptree->data() == 0 )
|
||||
{
|
||||
// degenerate case, this filter goes at this node
|
||||
ptree->data( filter );
|
||||
}
|
||||
else if ( ptree->right() == 0 && ptree->left() == 0 )
|
||||
{
|
||||
// this will be the case when there is a single node in the tree
|
||||
// that contains a filter. Here we want to make the root node an
|
||||
// 'and' operator, push the existing down to the lhs and make a
|
||||
// new node for the new filter
|
||||
ParseTree* newLhs = new ParseTree( ptree->data() );
|
||||
ParseTree* newRhs = new ParseTree( filter );
|
||||
|
||||
Operator* op = new Operator();
|
||||
op->data("and");
|
||||
Operator* op = new Operator();
|
||||
op->data("and");
|
||||
|
||||
ptree->data( op );
|
||||
ptree->left( newLhs );
|
||||
ptree->right( newRhs );
|
||||
}
|
||||
else
|
||||
{
|
||||
// this will be the case once we have a tree with an 'and' at the
|
||||
// root node, a filter in the lhs, and an arbitrary height tree
|
||||
// with the same properties on the rhs. Because all operators
|
||||
// are guaranteed to be and for now we simply insert a new rhs
|
||||
// node and "push down" the existing tree
|
||||
Operator* op = new Operator();
|
||||
op->data("and");
|
||||
ptree->data( op );
|
||||
ptree->left( newLhs );
|
||||
ptree->right( newRhs );
|
||||
}
|
||||
else
|
||||
{
|
||||
// this will be the case once we have a tree with an 'and' at the
|
||||
// root node, a filter in the lhs, and an arbitrary height tree
|
||||
// with the same properties on the rhs. Because all operators
|
||||
// are guaranteed to be and for now we simply insert a new rhs
|
||||
// node and "push down" the existing tree
|
||||
Operator* op = new Operator();
|
||||
op->data("and");
|
||||
|
||||
ParseTree* newRhs = new ParseTree( op );
|
||||
newRhs->left( new ParseTree( filter ) );
|
||||
newRhs->right( ptree->right() );
|
||||
ptree->right( newRhs );
|
||||
}
|
||||
ParseTree* newRhs = new ParseTree( op );
|
||||
newRhs->left( new ParseTree( filter ) );
|
||||
newRhs->right( ptree->right() );
|
||||
ptree->right( newRhs );
|
||||
}
|
||||
}
|
||||
|
||||
void updateParseTree(boost::shared_ptr<execplan::CalpontSystemCatalog>& csc,
|
||||
execplan::CalpontSelectExecutionPlan*& csep,
|
||||
execplan::SimpleColumn* sc,
|
||||
const std::string& relop, pair<int, string> cval)
|
||||
execplan::CalpontSelectExecutionPlan*& csep,
|
||||
execplan::SimpleColumn* sc,
|
||||
const std::string& relop, pair<int, string> cval)
|
||||
{
|
||||
execplan::ConstantColumn* cc=0;
|
||||
if (cval.first == 0)
|
||||
cc = createConstCol(cval.second, static_cast<int64_t>(atoll(cval.second.c_str())));
|
||||
else
|
||||
cc = createConstCol(cval.second);
|
||||
if (sc->schemaName() == "infinidb_unknown" && !DefaultSchema.empty())
|
||||
sc->schemaName(DefaultSchema);
|
||||
execplan::SimpleFilter* sf=0;
|
||||
sf = createSimpleFilter(csc,
|
||||
execplan::make_tcn(sc->schemaName(), sc->tableName(), sc->columnName()),
|
||||
relop, cc);
|
||||
execplan::ParseTree* ptp=0;
|
||||
ptp = csep->filters();
|
||||
if (ptp == 0)
|
||||
ptp = new execplan::ParseTree();
|
||||
appendSimpleFilter(ptp, sf);
|
||||
csep->filters(ptp);
|
||||
execplan::ConstantColumn* cc = 0;
|
||||
|
||||
if (cval.first == 0)
|
||||
cc = createConstCol(cval.second, static_cast<int64_t>(atoll(cval.second.c_str())));
|
||||
else
|
||||
cc = createConstCol(cval.second);
|
||||
|
||||
if (sc->schemaName() == "infinidb_unknown" && !DefaultSchema.empty())
|
||||
sc->schemaName(DefaultSchema);
|
||||
|
||||
execplan::SimpleFilter* sf = 0;
|
||||
sf = createSimpleFilter(csc,
|
||||
execplan::make_tcn(sc->schemaName(), sc->tableName(), sc->columnName()),
|
||||
relop, cc);
|
||||
execplan::ParseTree* ptp = 0;
|
||||
ptp = csep->filters();
|
||||
|
||||
if (ptp == 0)
|
||||
ptp = new execplan::ParseTree();
|
||||
|
||||
appendSimpleFilter(ptp, sf);
|
||||
csep->filters(ptp);
|
||||
}
|
||||
|
||||
//template instantiations
|
||||
|
@ -22,23 +22,23 @@ template <typename T>
|
||||
execplan::ConstantColumn* createConstCol(const std::string& valstr, T val);
|
||||
|
||||
execplan::SimpleFilter* createSimpleFilter
|
||||
(
|
||||
boost::shared_ptr<execplan::CalpontSystemCatalog>& csc,
|
||||
const execplan::CalpontSystemCatalog::TableColName& tcn,
|
||||
const std::string& opstr,
|
||||
execplan::ConstantColumn* cc
|
||||
);
|
||||
(
|
||||
boost::shared_ptr<execplan::CalpontSystemCatalog>& csc,
|
||||
const execplan::CalpontSystemCatalog::TableColName& tcn,
|
||||
const std::string& opstr,
|
||||
execplan::ConstantColumn* cc
|
||||
);
|
||||
|
||||
void appendSimpleFilter
|
||||
(
|
||||
execplan::ParseTree*& ptree,
|
||||
execplan::SimpleFilter* filter
|
||||
);
|
||||
(
|
||||
execplan::ParseTree*& ptree,
|
||||
execplan::SimpleFilter* filter
|
||||
);
|
||||
|
||||
void updateParseTree(boost::shared_ptr<execplan::CalpontSystemCatalog>&,
|
||||
execplan::CalpontSelectExecutionPlan*&,
|
||||
execplan::SimpleColumn*,
|
||||
const std::string&, pair<int, string>);
|
||||
execplan::CalpontSelectExecutionPlan*&,
|
||||
execplan::SimpleColumn*,
|
||||
const std::string&, pair<int, string>);
|
||||
|
||||
} //namespace qfe::utils
|
||||
} //namespace qfe
|
||||
|
@ -27,38 +27,40 @@ using namespace qfe;
|
||||
|
||||
int processDDLStmt(const string& stmt, uint32_t sid)
|
||||
{
|
||||
MessageQueueClient* mq=0;
|
||||
SqlParser parser;
|
||||
MessageQueueClient* mq = 0;
|
||||
SqlParser parser;
|
||||
|
||||
parser.setDefaultSchema(DefaultSchema);
|
||||
parser.Parse(stmt.c_str());
|
||||
if (parser.Good())
|
||||
{
|
||||
const ddlpackage::ParseTree& ptree = parser.GetParseTree();
|
||||
SqlStatement &ddlstmt = *ptree.fList[0];
|
||||
ddlstmt.fSessionID = sid;
|
||||
ddlstmt.fSql = stmt;
|
||||
ddlstmt.fOwner = DefaultSchema;
|
||||
ByteStream bytestream;
|
||||
bytestream << ddlstmt.fSessionID;
|
||||
ddlstmt.serialize(bytestream);
|
||||
mq = new MessageQueueClient("DDLProc");
|
||||
scoped_ptr<MessageQueueClient> smq(mq);
|
||||
ByteStream::byte b=0;
|
||||
mq->write(bytestream);
|
||||
bytestream = mq->read();
|
||||
bytestream >> b;
|
||||
string emsg;
|
||||
bytestream >> emsg;
|
||||
if (b != 0)
|
||||
throw runtime_error(emsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw runtime_error("syntax error");
|
||||
}
|
||||
parser.setDefaultSchema(DefaultSchema);
|
||||
parser.Parse(stmt.c_str());
|
||||
|
||||
return 0;
|
||||
if (parser.Good())
|
||||
{
|
||||
const ddlpackage::ParseTree& ptree = parser.GetParseTree();
|
||||
SqlStatement& ddlstmt = *ptree.fList[0];
|
||||
ddlstmt.fSessionID = sid;
|
||||
ddlstmt.fSql = stmt;
|
||||
ddlstmt.fOwner = DefaultSchema;
|
||||
ByteStream bytestream;
|
||||
bytestream << ddlstmt.fSessionID;
|
||||
ddlstmt.serialize(bytestream);
|
||||
mq = new MessageQueueClient("DDLProc");
|
||||
scoped_ptr<MessageQueueClient> smq(mq);
|
||||
ByteStream::byte b = 0;
|
||||
mq->write(bytestream);
|
||||
bytestream = mq->read();
|
||||
bytestream >> b;
|
||||
string emsg;
|
||||
bytestream >> emsg;
|
||||
|
||||
if (b != 0)
|
||||
throw runtime_error(emsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw runtime_error("syntax error");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -68,12 +70,12 @@ namespace qfe
|
||||
|
||||
void processCreateStmt(const string& stmt, uint32_t sid)
|
||||
{
|
||||
processDDLStmt(stmt, sid);
|
||||
processDDLStmt(stmt, sid);
|
||||
}
|
||||
|
||||
void processDropStmt(const string& stmt, uint32_t sid)
|
||||
{
|
||||
processDDLStmt(stmt, sid);
|
||||
processDDLStmt(stmt, sid);
|
||||
}
|
||||
|
||||
} //namespace qfe
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -41,52 +41,57 @@ extern string DefaultSchema;
|
||||
|
||||
CalpontSelectExecutionPlan* parseQuery(const string& query, const uint32_t sid)
|
||||
{
|
||||
//We're going to make parsing the query single-threaded for now. This makes it a lot
|
||||
// easier to interface with the parser and doesn;t materially affect overall query
|
||||
// performance (I think)
|
||||
mutex::scoped_lock lk(ParserMutex);
|
||||
//We're going to make parsing the query single-threaded for now. This makes it a lot
|
||||
// easier to interface with the parser and doesn;t materially affect overall query
|
||||
// performance (I think)
|
||||
mutex::scoped_lock lk(ParserMutex);
|
||||
|
||||
boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sid);
|
||||
CalpontSelectExecutionPlan* csep=0;
|
||||
csep = new CalpontSelectExecutionPlan();
|
||||
//we use an auto_ptr here with some trepidation. We only want auto delete on an execption.
|
||||
//If the parseing and plan build succeed, we want the ptr to stay around. boost::scoped_ptr<>
|
||||
//doesn't have an API to release ownership, so we use auto_ptr...
|
||||
auto_ptr<CalpontSelectExecutionPlan> scsep(csep);
|
||||
boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sid);
|
||||
CalpontSelectExecutionPlan* csep = 0;
|
||||
csep = new CalpontSelectExecutionPlan();
|
||||
//we use an auto_ptr here with some trepidation. We only want auto delete on an execption.
|
||||
//If the parseing and plan build succeed, we want the ptr to stay around. boost::scoped_ptr<>
|
||||
//doesn't have an API to release ownership, so we use auto_ptr...
|
||||
auto_ptr<CalpontSelectExecutionPlan> scsep(csep);
|
||||
|
||||
yy_buffer_state* ybs=0;
|
||||
ybs = qfe_scan_string(query.c_str());
|
||||
if (ybs != 0)
|
||||
{
|
||||
ParserCSEP = csep;
|
||||
ParserCSC = csc;
|
||||
if (qfeparse() != 0)
|
||||
throw runtime_error("syntax error");
|
||||
qfe_delete_buffer(ybs);
|
||||
}
|
||||
else
|
||||
throw runtime_error("Internal parser memory error");
|
||||
yy_buffer_state* ybs = 0;
|
||||
ybs = qfe_scan_string(query.c_str());
|
||||
|
||||
csep->data(query);
|
||||
if (ybs != 0)
|
||||
{
|
||||
ParserCSEP = csep;
|
||||
ParserCSC = csc;
|
||||
|
||||
SessionManager sm;
|
||||
TxnID txnID;
|
||||
txnID = sm.getTxnID(sid);
|
||||
if (!txnID.valid)
|
||||
{
|
||||
txnID.id = 0;
|
||||
txnID.valid = true;
|
||||
}
|
||||
QueryContext verID;
|
||||
verID = sm.verID();
|
||||
if (qfeparse() != 0)
|
||||
throw runtime_error("syntax error");
|
||||
|
||||
csep->txnID(txnID.id);
|
||||
csep->verID(verID);
|
||||
csep->sessionID(sid);
|
||||
qfe_delete_buffer(ybs);
|
||||
}
|
||||
else
|
||||
throw runtime_error("Internal parser memory error");
|
||||
|
||||
//cout << *csep << endl;
|
||||
scsep.release();
|
||||
return csep;
|
||||
csep->data(query);
|
||||
|
||||
SessionManager sm;
|
||||
TxnID txnID;
|
||||
txnID = sm.getTxnID(sid);
|
||||
|
||||
if (!txnID.valid)
|
||||
{
|
||||
txnID.id = 0;
|
||||
txnID.valid = true;
|
||||
}
|
||||
|
||||
QueryContext verID;
|
||||
verID = sm.verID();
|
||||
|
||||
csep->txnID(txnID.id);
|
||||
csep->verID(verID);
|
||||
csep->sessionID(sid);
|
||||
|
||||
//cout << *csep << endl;
|
||||
scsep.release();
|
||||
return csep;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,66 +30,69 @@ namespace qfe
|
||||
|
||||
void processReturnedRows(MessageQueueClient* mqc, SockType fd)
|
||||
{
|
||||
scoped_ptr<MessageQueueClient> cleaner(mqc);
|
||||
SBS sbs;
|
||||
sbs = mqc->read();
|
||||
//cerr << "got a bs of " << sbs->length() << " bytes" << endl;
|
||||
scoped_ptr<MessageQueueClient> cleaner(mqc);
|
||||
SBS sbs;
|
||||
sbs = mqc->read();
|
||||
//cerr << "got a bs of " << sbs->length() << " bytes" << endl;
|
||||
|
||||
RowGroup rg;
|
||||
rg.deserialize(*sbs);
|
||||
RowGroup rg;
|
||||
rg.deserialize(*sbs);
|
||||
|
||||
//cerr << "got a base rowgroup with rows of " << rg.getRowSize() << " bytes" << endl;
|
||||
//cerr << rg.toString() << endl;
|
||||
//cerr << "got a base rowgroup with rows of " << rg.getRowSize() << " bytes" << endl;
|
||||
//cerr << rg.toString() << endl;
|
||||
|
||||
ByteStream bs;
|
||||
ByteStream::quadbyte tableOID=100;
|
||||
bs.reset();
|
||||
bs << tableOID;
|
||||
mqc->write(bs);
|
||||
ByteStream bs;
|
||||
ByteStream::quadbyte tableOID = 100;
|
||||
bs.reset();
|
||||
bs << tableOID;
|
||||
mqc->write(bs);
|
||||
|
||||
sbs = mqc->read();
|
||||
//cerr << "got a bs of " << sbs->length() << " bytes" << endl;
|
||||
RGData rgd;
|
||||
rgd.deserialize(*sbs, true);
|
||||
rg.setData(&rgd);
|
||||
//cerr << "got a rowgroup with: " << rg.getRowCount() << " rows" << endl;
|
||||
sbs = mqc->read();
|
||||
//cerr << "got a bs of " << sbs->length() << " bytes" << endl;
|
||||
RGData rgd;
|
||||
rgd.deserialize(*sbs, true);
|
||||
rg.setData(&rgd);
|
||||
//cerr << "got a rowgroup with: " << rg.getRowCount() << " rows" << endl;
|
||||
|
||||
socketio::writeString(fd, "OK");
|
||||
Row r;
|
||||
while (rg.getRowCount() > 0)
|
||||
{
|
||||
rg.initRow(&r);
|
||||
rg.getRow(0, &r);
|
||||
string csv;
|
||||
bs.reset();
|
||||
for (unsigned i = 0; i < rg.getRowCount(); i++)
|
||||
{
|
||||
csv = r.toCSV();
|
||||
bs << csv;
|
||||
r.nextRow();
|
||||
}
|
||||
//cerr << "writing " << bs.length() << " bytes back to client" << endl;
|
||||
SockWriteFcn(fd, bs.buf(), bs.length());
|
||||
socketio::writeString(fd, "OK");
|
||||
Row r;
|
||||
|
||||
bs.reset();
|
||||
bs << tableOID;
|
||||
mqc->write(bs);
|
||||
while (rg.getRowCount() > 0)
|
||||
{
|
||||
rg.initRow(&r);
|
||||
rg.getRow(0, &r);
|
||||
string csv;
|
||||
bs.reset();
|
||||
|
||||
sbs = mqc->read();
|
||||
//cerr << "got a bs of " << sbs->length() << " bytes" << endl;
|
||||
rgd.deserialize(*sbs, true);
|
||||
rg.setData(&rgd);
|
||||
//cerr << "got a rowgroup with: " << rg.getRowCount() << " rows" << endl;
|
||||
}
|
||||
for (unsigned i = 0; i < rg.getRowCount(); i++)
|
||||
{
|
||||
csv = r.toCSV();
|
||||
bs << csv;
|
||||
r.nextRow();
|
||||
}
|
||||
|
||||
tableOID=0;
|
||||
bs.reset();
|
||||
bs << tableOID;
|
||||
mqc->write(bs);
|
||||
//cerr << "writing " << bs.length() << " bytes back to client" << endl;
|
||||
SockWriteFcn(fd, bs.buf(), bs.length());
|
||||
|
||||
//sync with the client on end-of-results
|
||||
SockWriteFcn(fd, &tableOID, 4);
|
||||
SockReadFcn(fd, &tableOID, 4);
|
||||
bs.reset();
|
||||
bs << tableOID;
|
||||
mqc->write(bs);
|
||||
|
||||
sbs = mqc->read();
|
||||
//cerr << "got a bs of " << sbs->length() << " bytes" << endl;
|
||||
rgd.deserialize(*sbs, true);
|
||||
rg.setData(&rgd);
|
||||
//cerr << "got a rowgroup with: " << rg.getRowCount() << " rows" << endl;
|
||||
}
|
||||
|
||||
tableOID = 0;
|
||||
bs.reset();
|
||||
bs << tableOID;
|
||||
mqc->write(bs);
|
||||
|
||||
//sync with the client on end-of-results
|
||||
SockWriteFcn(fd, &tableOID, 4);
|
||||
SockReadFcn(fd, &tableOID, 4);
|
||||
|
||||
}
|
||||
|
||||
|
@ -17,38 +17,38 @@ namespace qfe
|
||||
|
||||
MessageQueueClient* sendCSEP(CalpontSelectExecutionPlan* csep)
|
||||
{
|
||||
scoped_ptr<CalpontSelectExecutionPlan> cleaner(csep);
|
||||
scoped_ptr<CalpontSelectExecutionPlan> cleaner(csep);
|
||||
|
||||
ByteStream bs;
|
||||
ByteStream bs;
|
||||
|
||||
MessageQueueClient* mqc=0;
|
||||
MessageQueueClient* mqc = 0;
|
||||
|
||||
mqc = new MessageQueueClient("ExeMgr1");
|
||||
auto_ptr<MessageQueueClient> smqc(mqc);
|
||||
mqc = new MessageQueueClient("ExeMgr1");
|
||||
auto_ptr<MessageQueueClient> smqc(mqc);
|
||||
|
||||
bs.reset();
|
||||
ByteStream::quadbyte wantTuples=4;
|
||||
bs << wantTuples;
|
||||
mqc->write(bs);
|
||||
bs.reset();
|
||||
ByteStream::quadbyte wantTuples = 4;
|
||||
bs << wantTuples;
|
||||
mqc->write(bs);
|
||||
|
||||
bs.reset();
|
||||
csep->serialize(bs);
|
||||
mqc->write(bs);
|
||||
bs.reset();
|
||||
csep->serialize(bs);
|
||||
mqc->write(bs);
|
||||
|
||||
SBS sbs;
|
||||
sbs = mqc->read();
|
||||
*sbs >> wantTuples;
|
||||
//cerr << "got flag: " << wantTuples << endl;
|
||||
string msg;
|
||||
sbs = mqc->read();
|
||||
*sbs >> msg;
|
||||
//cerr << "got msg: " << msg << endl;
|
||||
SBS sbs;
|
||||
sbs = mqc->read();
|
||||
*sbs >> wantTuples;
|
||||
//cerr << "got flag: " << wantTuples << endl;
|
||||
string msg;
|
||||
sbs = mqc->read();
|
||||
*sbs >> msg;
|
||||
//cerr << "got msg: " << msg << endl;
|
||||
|
||||
if (wantTuples != 0)
|
||||
throw runtime_error(msg);
|
||||
if (wantTuples != 0)
|
||||
throw runtime_error(msg);
|
||||
|
||||
smqc.release();
|
||||
return mqc;
|
||||
smqc.release();
|
||||
return mqc;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -90,373 +90,424 @@ using namespace qfe;
|
||||
|
||||
enum StmtType
|
||||
{
|
||||
UNKNOWN,
|
||||
QUERY,
|
||||
CREATE,
|
||||
DROP,
|
||||
SHOW,
|
||||
UNKNOWN,
|
||||
QUERY,
|
||||
CREATE,
|
||||
DROP,
|
||||
SHOW,
|
||||
};
|
||||
|
||||
volatile uint32_t SystemSID;
|
||||
|
||||
void log(const string &s)
|
||||
void log(const string& s)
|
||||
{
|
||||
cerr << s << endl;
|
||||
cerr << s << endl;
|
||||
}
|
||||
|
||||
struct QueryMessage
|
||||
{
|
||||
QueryMessage() : isValid(false) { }
|
||||
~QueryMessage() { }
|
||||
QueryMessage() : isValid(false) { }
|
||||
~QueryMessage() { }
|
||||
|
||||
string toString() const;
|
||||
string toString() const;
|
||||
|
||||
bool isValid;
|
||||
string queryText;
|
||||
string defaultSchema;
|
||||
bool isValid;
|
||||
string queryText;
|
||||
string defaultSchema;
|
||||
};
|
||||
|
||||
string QueryMessage::toString() const
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "valid: " << boolalpha << isValid << ", " <<
|
||||
"queryText: " << queryText << ", " <<
|
||||
"defaultSchema: " << defaultSchema;
|
||||
return oss.str();
|
||||
ostringstream oss;
|
||||
oss << "valid: " << boolalpha << isValid << ", " <<
|
||||
"queryText: " << queryText << ", " <<
|
||||
"defaultSchema: " << defaultSchema;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream& os, const QueryMessage& rhs)
|
||||
{
|
||||
os << rhs.toString();
|
||||
return os;
|
||||
os << rhs.toString();
|
||||
return os;
|
||||
}
|
||||
|
||||
class ThreadFunc
|
||||
{
|
||||
public:
|
||||
ThreadFunc(SockType fd) : fFd(fd) { }
|
||||
~ThreadFunc() { }
|
||||
ThreadFunc(SockType fd) : fFd(fd) { }
|
||||
~ThreadFunc() { }
|
||||
|
||||
void run();
|
||||
void operator()() { run(); }
|
||||
void run();
|
||||
void operator()()
|
||||
{
|
||||
run();
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadFunc(const ThreadFunc& rhs);
|
||||
ThreadFunc& operator=(const ThreadFunc& rhs);
|
||||
ThreadFunc(const ThreadFunc& rhs);
|
||||
ThreadFunc& operator=(const ThreadFunc& rhs);
|
||||
|
||||
SockType fFd;
|
||||
SockType fFd;
|
||||
};
|
||||
|
||||
bool serverInit()
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
|
||||
setsid();
|
||||
setsid();
|
||||
|
||||
//Handle certain signals (we want these to return EINTR so we can throw)
|
||||
//SIGPIPE
|
||||
//I don't think we'll get any of these from init (except possibly HUP, but that's an indication
|
||||
// of bad things anyway)
|
||||
//SIGHUP?
|
||||
//SIGUSR1?
|
||||
//SIGUSR2?
|
||||
//SIGPOLL?
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &sa, 0);
|
||||
sigaction(SIGHUP, &sa, 0);
|
||||
sigaction(SIGUSR1, &sa, 0);
|
||||
sigaction(SIGUSR2, &sa, 0);
|
||||
//Handle certain signals (we want these to return EINTR so we can throw)
|
||||
//SIGPIPE
|
||||
//I don't think we'll get any of these from init (except possibly HUP, but that's an indication
|
||||
// of bad things anyway)
|
||||
//SIGHUP?
|
||||
//SIGUSR1?
|
||||
//SIGUSR2?
|
||||
//SIGPOLL?
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &sa, 0);
|
||||
sigaction(SIGHUP, &sa, 0);
|
||||
sigaction(SIGUSR1, &sa, 0);
|
||||
sigaction(SIGUSR2, &sa, 0);
|
||||
#ifndef __FreeBSD__
|
||||
sigaction(SIGPOLL, &sa, 0);
|
||||
sigaction(SIGPOLL, &sa, 0);
|
||||
#endif
|
||||
#if 0
|
||||
int fd;
|
||||
close(2);
|
||||
fd = open("/tmp/qfe.err",O_CREAT|O_TRUNC|O_WRONLY,0644);
|
||||
if (fd >= 0 && fd != 2)
|
||||
{
|
||||
dup2(fd, 2);
|
||||
close(fd);
|
||||
}
|
||||
int fd;
|
||||
close(2);
|
||||
fd = open("/tmp/qfe.err", O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
||||
|
||||
if (fd >= 0 && fd != 2)
|
||||
{
|
||||
dup2(fd, 2);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
SockType initListenSock(short portNo)
|
||||
{
|
||||
SockType listenSock=-1;
|
||||
SockType listenSock = -1;
|
||||
#ifdef _MSC_VER
|
||||
WSAData wsadata;
|
||||
const WORD minVersion = MAKEWORD(2, 2);
|
||||
WSAStartup(minVersion, &wsadata);
|
||||
WSAData wsadata;
|
||||
const WORD minVersion = MAKEWORD(2, 2);
|
||||
WSAStartup(minVersion, &wsadata);
|
||||
#endif
|
||||
listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
idbassert_s(listenSock >= 0, string("socket create error: ") + strerror(errno));
|
||||
//if (listenSock < 0) throw runtime_error(string("socket create error: ") + strerror(errno));
|
||||
listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
idbassert_s(listenSock >= 0, string("socket create error: ") + strerror(errno));
|
||||
//if (listenSock < 0) throw runtime_error(string("socket create error: ") + strerror(errno));
|
||||
#ifndef _MSC_VER
|
||||
int optval = 1;
|
||||
setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&optval), sizeof(optval));
|
||||
int optval = 1;
|
||||
setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&optval), sizeof(optval));
|
||||
#endif
|
||||
int rc = 0;
|
||||
struct sockaddr_in serv_addr;
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
serv_addr.sin_port = htons(portNo);
|
||||
const int MaxTries = 5 * 60 / 10;
|
||||
int tries = 0;
|
||||
int rc = 0;
|
||||
struct sockaddr_in serv_addr;
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
serv_addr.sin_port = htons(portNo);
|
||||
const int MaxTries = 5 * 60 / 10;
|
||||
int tries = 0;
|
||||
again:
|
||||
rc = ::bind(listenSock, (sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||
if (rc < 0)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
int x = WSAGetLastError();
|
||||
if (x == WSAEADDRINUSE)
|
||||
#else
|
||||
if (errno == EADDRINUSE)
|
||||
#endif
|
||||
{
|
||||
//cerr << "Addr in use..." << endl;
|
||||
if (++tries >= MaxTries)
|
||||
{
|
||||
log("Waited too long for socket to bind...giving up");
|
||||
//cerr << "Waited too long for socket to bind...giving up" << endl;
|
||||
exit(1);
|
||||
}
|
||||
sleep(10);
|
||||
goto again;
|
||||
}
|
||||
idbassert_s(0, string("socket bind error: ") + strerror(errno));
|
||||
//throw runtime_error(string("socket bind error: ") + strerror(errno));
|
||||
}
|
||||
rc = listen(listenSock, 16);
|
||||
idbassert_s(rc >= 0, string("socket listen error") + strerror(errno));
|
||||
//if (rc < 0) throw runtime_error(string("socket listen error") + strerror(errno));
|
||||
rc = ::bind(listenSock, (sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||
|
||||
return listenSock;
|
||||
if (rc < 0)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
int x = WSAGetLastError();
|
||||
|
||||
if (x == WSAEADDRINUSE)
|
||||
#else
|
||||
if (errno == EADDRINUSE)
|
||||
#endif
|
||||
{
|
||||
//cerr << "Addr in use..." << endl;
|
||||
if (++tries >= MaxTries)
|
||||
{
|
||||
log("Waited too long for socket to bind...giving up");
|
||||
//cerr << "Waited too long for socket to bind...giving up" << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sleep(10);
|
||||
goto again;
|
||||
}
|
||||
|
||||
idbassert_s(0, string("socket bind error: ") + strerror(errno));
|
||||
//throw runtime_error(string("socket bind error: ") + strerror(errno));
|
||||
}
|
||||
|
||||
rc = listen(listenSock, 16);
|
||||
idbassert_s(rc >= 0, string("socket listen error") + strerror(errno));
|
||||
//if (rc < 0) throw runtime_error(string("socket listen error") + strerror(errno));
|
||||
|
||||
return listenSock;
|
||||
}
|
||||
|
||||
QueryMessage getNextMsg(SockType fd)
|
||||
{
|
||||
QueryMessage msg;
|
||||
QueryMessage msg;
|
||||
|
||||
try {
|
||||
msg.defaultSchema = socketio::readString(fd);
|
||||
msg.queryText = socketio::readString(fd);
|
||||
msg.isValid = true;
|
||||
} catch (runtime_error& rex) {
|
||||
cerr << "re reading ctl msg: " << rex.what() << endl;
|
||||
msg.queryText = "";
|
||||
} catch (...) {
|
||||
cerr << "ex reading ctl msg" << endl;
|
||||
msg.queryText = "";
|
||||
}
|
||||
try
|
||||
{
|
||||
msg.defaultSchema = socketio::readString(fd);
|
||||
msg.queryText = socketio::readString(fd);
|
||||
msg.isValid = true;
|
||||
}
|
||||
catch (runtime_error& rex)
|
||||
{
|
||||
cerr << "re reading ctl msg: " << rex.what() << endl;
|
||||
msg.queryText = "";
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cerr << "ex reading ctl msg" << endl;
|
||||
msg.queryText = "";
|
||||
}
|
||||
|
||||
return msg;
|
||||
return msg;
|
||||
}
|
||||
|
||||
StmtType guessStatementType(const string& stmt)
|
||||
{
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
char_separator<char> sep;
|
||||
tokenizer tokens(stmt, sep);
|
||||
tokenizer::iterator tok_iter = tokens.begin();
|
||||
string first_word;
|
||||
first_word = *tok_iter;
|
||||
algorithm::to_lower(first_word);
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
char_separator<char> sep;
|
||||
tokenizer tokens(stmt, sep);
|
||||
tokenizer::iterator tok_iter = tokens.begin();
|
||||
string first_word;
|
||||
first_word = *tok_iter;
|
||||
algorithm::to_lower(first_word);
|
||||
|
||||
if (first_word == "select")
|
||||
return QUERY;
|
||||
if (first_word == "create")
|
||||
return CREATE;
|
||||
if (first_word == "drop")
|
||||
return DROP;
|
||||
if (first_word == "show")
|
||||
return SHOW;
|
||||
if (first_word == "select")
|
||||
return QUERY;
|
||||
|
||||
return UNKNOWN;
|
||||
if (first_word == "create")
|
||||
return CREATE;
|
||||
|
||||
if (first_word == "drop")
|
||||
return DROP;
|
||||
|
||||
if (first_word == "show")
|
||||
return SHOW;
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
struct ScopedCleaner
|
||||
{
|
||||
ScopedCleaner(SockType fd=-1) : fFd(fd) { }
|
||||
ScopedCleaner(SockType fd = -1) : fFd(fd) { }
|
||||
#ifdef _MSC_VER
|
||||
~ScopedCleaner() { if (fFd >= 0) shutdown(fFd, SHUT_RDWR); closesocket(fFd); }
|
||||
~ScopedCleaner()
|
||||
{
|
||||
if (fFd >= 0) shutdown(fFd, SHUT_RDWR);
|
||||
|
||||
closesocket(fFd);
|
||||
}
|
||||
#else
|
||||
~ScopedCleaner() { if (fFd >= 0) shutdown(fFd, SHUT_RDWR); close(fFd); }
|
||||
~ScopedCleaner()
|
||||
{
|
||||
if (fFd >= 0) shutdown(fFd, SHUT_RDWR);
|
||||
|
||||
close(fFd);
|
||||
}
|
||||
|
||||
#endif
|
||||
SockType fFd;
|
||||
SockType fFd;
|
||||
};
|
||||
|
||||
void ThreadFunc::run()
|
||||
{
|
||||
QueryMessage m;
|
||||
execplan::CalpontSelectExecutionPlan* csep=0;
|
||||
MessageQueueClient* msgqcl;
|
||||
QueryMessage m;
|
||||
execplan::CalpontSelectExecutionPlan* csep = 0;
|
||||
MessageQueueClient* msgqcl;
|
||||
|
||||
ScopedCleaner cleaner(fFd);
|
||||
ScopedCleaner cleaner(fFd);
|
||||
|
||||
uint32_t sid = 1;
|
||||
sid = atomicops::atomicInc(&SystemSID);
|
||||
uint32_t sid = 1;
|
||||
sid = atomicops::atomicInc(&SystemSID);
|
||||
|
||||
try {
|
||||
m = getNextMsg(fFd);
|
||||
try
|
||||
{
|
||||
m = getNextMsg(fFd);
|
||||
|
||||
if (m.isValid)
|
||||
{
|
||||
DefaultSchema = m.defaultSchema;
|
||||
StmtType st = guessStatementType(m.queryText);
|
||||
switch (st)
|
||||
{
|
||||
case QUERY:
|
||||
csep = parseQuery(m.queryText, sid);
|
||||
//sendCSEP takes ownership of the ptr from parseQuery
|
||||
msgqcl = sendCSEP(csep);
|
||||
//processReturnedRows takes ownership of the ptr from sendCSEP
|
||||
processReturnedRows(msgqcl, fFd);
|
||||
break;
|
||||
case CREATE:
|
||||
processCreateStmt(m.queryText, sid);
|
||||
break;
|
||||
case DROP:
|
||||
processDropStmt(m.queryText, sid);
|
||||
break;
|
||||
case SHOW:
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "select calpontsys.systable.tablename from calpontsys.systable where "
|
||||
"calpontsys.systable.schema='" << m.defaultSchema << "';";
|
||||
csep = parseQuery(oss.str(), sid);
|
||||
msgqcl = sendCSEP(csep);
|
||||
processReturnedRows(msgqcl, fFd);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw runtime_error("couldn't guess the statement type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (std::exception& ex) {
|
||||
socketio::writeString(fFd, ex.what());
|
||||
throw; //in a multi-threaded server this will simply cause this thread to exit
|
||||
} catch (...) {
|
||||
socketio::writeString(fFd, "internal query processing error");
|
||||
throw;
|
||||
}
|
||||
if (m.isValid)
|
||||
{
|
||||
DefaultSchema = m.defaultSchema;
|
||||
StmtType st = guessStatementType(m.queryText);
|
||||
|
||||
switch (st)
|
||||
{
|
||||
case QUERY:
|
||||
csep = parseQuery(m.queryText, sid);
|
||||
//sendCSEP takes ownership of the ptr from parseQuery
|
||||
msgqcl = sendCSEP(csep);
|
||||
//processReturnedRows takes ownership of the ptr from sendCSEP
|
||||
processReturnedRows(msgqcl, fFd);
|
||||
break;
|
||||
|
||||
case CREATE:
|
||||
processCreateStmt(m.queryText, sid);
|
||||
break;
|
||||
|
||||
case DROP:
|
||||
processDropStmt(m.queryText, sid);
|
||||
break;
|
||||
|
||||
case SHOW:
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "select calpontsys.systable.tablename from calpontsys.systable where "
|
||||
"calpontsys.systable.schema='" << m.defaultSchema << "';";
|
||||
csep = parseQuery(oss.str(), sid);
|
||||
msgqcl = sendCSEP(csep);
|
||||
processReturnedRows(msgqcl, fFd);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw runtime_error("couldn't guess the statement type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
socketio::writeString(fFd, ex.what());
|
||||
throw; //in a multi-threaded server this will simply cause this thread to exit
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
socketio::writeString(fFd, "internal query processing error");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int c;
|
||||
SockType listenSock;
|
||||
short portNo;
|
||||
int c;
|
||||
SockType listenSock;
|
||||
short portNo;
|
||||
|
||||
portNo = 0;
|
||||
char* p = getenv("IDB_QFE_PORT");
|
||||
if (p && *p)
|
||||
portNo = atoi(p);
|
||||
portNo = 0;
|
||||
char* p = getenv("IDB_QFE_PORT");
|
||||
|
||||
if (p && *p)
|
||||
portNo = atoi(p);
|
||||
|
||||
if (portNo <= 0)
|
||||
portNo = 9198;
|
||||
|
||||
if (portNo <= 0)
|
||||
portNo = 9198;
|
||||
#ifdef _MSC_VER
|
||||
listenSock = INVALID_SOCKET;
|
||||
listenSock = INVALID_SOCKET;
|
||||
#else
|
||||
listenSock = -1;
|
||||
listenSock = -1;
|
||||
#endif
|
||||
opterr = 0;
|
||||
opterr = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "p:")) != -1)
|
||||
switch (c)
|
||||
{
|
||||
case 'p':
|
||||
portNo = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
while ((c = getopt(argc, argv, "p:")) != -1)
|
||||
switch (c)
|
||||
{
|
||||
case 'p':
|
||||
portNo = atoi(optarg);
|
||||
break;
|
||||
|
||||
if (!serverInit())
|
||||
{
|
||||
log("Could not initialize the QFE Server!");
|
||||
cerr << "Could not initialize the QFE Server!" << endl;
|
||||
return 1;
|
||||
}
|
||||
case '?':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
listenSock = initListenSock(portNo);
|
||||
if (!serverInit())
|
||||
{
|
||||
log("Could not initialize the QFE Server!");
|
||||
cerr << "Could not initialize the QFE Server!" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SystemSID = 0;
|
||||
listenSock = initListenSock(portNo);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SystemSID = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
SOCKET querySock = INVALID_SOCKET;
|
||||
querySock = accept(listenSock, 0, 0);
|
||||
idbassert_s(querySock != INVALID_SOCKET, string("socket accept error: ") + strerror(errno));
|
||||
SOCKET querySock = INVALID_SOCKET;
|
||||
querySock = accept(listenSock, 0, 0);
|
||||
idbassert_s(querySock != INVALID_SOCKET, string("socket accept error: ") + strerror(errno));
|
||||
#if 0
|
||||
uint32_t sndbufsize;
|
||||
int sndbufsizelen=4;
|
||||
int rc;
|
||||
rc = getsockopt(querySock, SOL_SOCKET, SO_SNDBUF, (char*)&sndbufsize, &sndbufsizelen);
|
||||
if (rc != SOCKET_ERROR)
|
||||
{
|
||||
if (sndbufsizelen == 4)
|
||||
{
|
||||
cerr << "getsockopt(): current SO_SNDBUF = " << sndbufsize << endl;
|
||||
sndbufsize = atoi(getenv("SO_SNDBUF"));
|
||||
cerr << "setsockopt(): setting SO_SNDBUF = " << sndbufsize << endl;
|
||||
rc = setsockopt(querySock, SOL_SOCKET, SO_SNDBUF, (const char*)&sndbufsize, sndbufsizelen);
|
||||
if (rc != SOCKET_ERROR)
|
||||
{
|
||||
getsockopt(querySock, SOL_SOCKET, SO_SNDBUF, (char*)&sndbufsize, &sndbufsizelen);
|
||||
cerr << "getsockopt(): new SO_SNDBUF = " << sndbufsize << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "setsockopt(): " << WSAGetLastError() << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "getsockopt(): expecting 4 bytes, got " << sndbufsizelen << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "getsockopt(): " << WSAGetLastError() << endl;
|
||||
}
|
||||
uint32_t sndbufsize;
|
||||
int sndbufsizelen = 4;
|
||||
int rc;
|
||||
rc = getsockopt(querySock, SOL_SOCKET, SO_SNDBUF, (char*)&sndbufsize, &sndbufsizelen);
|
||||
|
||||
if (rc != SOCKET_ERROR)
|
||||
{
|
||||
if (sndbufsizelen == 4)
|
||||
{
|
||||
cerr << "getsockopt(): current SO_SNDBUF = " << sndbufsize << endl;
|
||||
sndbufsize = atoi(getenv("SO_SNDBUF"));
|
||||
cerr << "setsockopt(): setting SO_SNDBUF = " << sndbufsize << endl;
|
||||
rc = setsockopt(querySock, SOL_SOCKET, SO_SNDBUF, (const char*)&sndbufsize, sndbufsizelen);
|
||||
|
||||
if (rc != SOCKET_ERROR)
|
||||
{
|
||||
getsockopt(querySock, SOL_SOCKET, SO_SNDBUF, (char*)&sndbufsize, &sndbufsizelen);
|
||||
cerr << "getsockopt(): new SO_SNDBUF = " << sndbufsize << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "setsockopt(): " << WSAGetLastError() << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "getsockopt(): expecting 4 bytes, got " << sndbufsizelen << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "getsockopt(): " << WSAGetLastError() << endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
uint32_t sndbufsize = 512 * 1024;
|
||||
setsockopt(querySock, SOL_SOCKET, SO_SNDBUF, (const char*)&sndbufsize, 4);
|
||||
uint32_t sndbufsize = 512 * 1024;
|
||||
setsockopt(querySock, SOL_SOCKET, SO_SNDBUF, (const char*)&sndbufsize, 4);
|
||||
#else
|
||||
int querySock = -1;
|
||||
querySock = accept(listenSock, 0, 0);
|
||||
idbassert_s(querySock >= 0, string("socket accept error: ") + strerror(errno));
|
||||
int querySock = -1;
|
||||
querySock = accept(listenSock, 0, 0);
|
||||
idbassert_s(querySock >= 0, string("socket accept error: ") + strerror(errno));
|
||||
#endif
|
||||
|
||||
//ThreadFunc now owns querySock and is responsible for cleaning it up
|
||||
ThreadFunc tf(querySock);
|
||||
//ThreadFunc now owns querySock and is responsible for cleaning it up
|
||||
ThreadFunc tf(querySock);
|
||||
|
||||
#ifdef SINGLE_THREADED
|
||||
try {
|
||||
tf.run();
|
||||
} catch (std::exception& ex) {
|
||||
cerr << "ThreadFunc run threw an exception: " << ex.what() << endl;
|
||||
} catch (...) {
|
||||
cerr << "ThreadFunc run threw an exception" << endl;
|
||||
}
|
||||
#else
|
||||
thread t(tf);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
try
|
||||
{
|
||||
tf.run();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
cerr << "ThreadFunc run threw an exception: " << ex.what() << endl;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cerr << "ThreadFunc run threw an exception" << endl;
|
||||
}
|
||||
|
||||
#else
|
||||
thread t(tf);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
// vim:ts=4 sw=4:
|
||||
|
||||
|
@ -37,165 +37,183 @@ namespace socketio
|
||||
#ifndef _MSC_VER
|
||||
void readn(int fd, void* buf, const size_t wanted)
|
||||
{
|
||||
size_t needed = wanted;
|
||||
size_t sofar = 0;
|
||||
char* p = static_cast<char*>(buf);
|
||||
ssize_t rrc = -1;
|
||||
pollfd fds[1];
|
||||
int en = 0;
|
||||
size_t needed = wanted;
|
||||
size_t sofar = 0;
|
||||
char* p = static_cast<char*>(buf);
|
||||
ssize_t rrc = -1;
|
||||
pollfd fds[1];
|
||||
int en = 0;
|
||||
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
|
||||
while (wanted > sofar)
|
||||
{
|
||||
fds[0].revents = 0;
|
||||
poll(fds, 1, -1);
|
||||
errno = 0;
|
||||
rrc = read(fd, (p + sofar), needed);
|
||||
en = errno;
|
||||
if (rrc < 0)
|
||||
{
|
||||
if (en == EAGAIN || en == EINTR || en == 512)
|
||||
continue;
|
||||
ostringstream oss;
|
||||
oss << "qfe: readn: read() returned " << rrc << " (" << strerror(en) << ")";
|
||||
idbassert_s(0, oss.str());
|
||||
}
|
||||
needed -= rrc;
|
||||
sofar += rrc;
|
||||
}
|
||||
while (wanted > sofar)
|
||||
{
|
||||
fds[0].revents = 0;
|
||||
poll(fds, 1, -1);
|
||||
errno = 0;
|
||||
rrc = read(fd, (p + sofar), needed);
|
||||
en = errno;
|
||||
|
||||
if (rrc < 0)
|
||||
{
|
||||
if (en == EAGAIN || en == EINTR || en == 512)
|
||||
continue;
|
||||
|
||||
ostringstream oss;
|
||||
oss << "qfe: readn: read() returned " << rrc << " (" << strerror(en) << ")";
|
||||
idbassert_s(0, oss.str());
|
||||
}
|
||||
|
||||
needed -= rrc;
|
||||
sofar += rrc;
|
||||
}
|
||||
}
|
||||
|
||||
size_t writen(int fd, const void* data, const size_t nbytes)
|
||||
{
|
||||
size_t nleft;
|
||||
ssize_t nwritten;
|
||||
const char* bufp = static_cast<const char*>(data);
|
||||
nleft = nbytes;
|
||||
size_t nleft;
|
||||
ssize_t nwritten;
|
||||
const char* bufp = static_cast<const char*>(data);
|
||||
nleft = nbytes;
|
||||
|
||||
while (nleft > 0)
|
||||
{
|
||||
// the O_NONBLOCK flag is not set, this is a blocking I/O.
|
||||
if ((nwritten = ::write(fd, bufp, nleft)) < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
nwritten = 0;
|
||||
else {
|
||||
// save the error no first
|
||||
int e = errno;
|
||||
string errorMsg = "qfe: writen: write() error: ";
|
||||
scoped_array<char> buf(new char[80]);
|
||||
while (nleft > 0)
|
||||
{
|
||||
// the O_NONBLOCK flag is not set, this is a blocking I/O.
|
||||
if ((nwritten = ::write(fd, bufp, nleft)) < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
nwritten = 0;
|
||||
else
|
||||
{
|
||||
// save the error no first
|
||||
int e = errno;
|
||||
string errorMsg = "qfe: writen: write() error: ";
|
||||
scoped_array<char> buf(new char[80]);
|
||||
#if STRERROR_R_CHAR_P
|
||||
const char* p;
|
||||
if ((p = strerror_r(e, buf.get(), 80)) != 0)
|
||||
errorMsg += p;
|
||||
#else
|
||||
int p;
|
||||
if ((p = strerror_r(e, buf.get(), 80)) == 0)
|
||||
errorMsg += buf.get();
|
||||
#endif
|
||||
idbassert_s(0, errorMsg);
|
||||
}
|
||||
}
|
||||
nleft -= nwritten;
|
||||
bufp += nwritten;
|
||||
}
|
||||
const char* p;
|
||||
|
||||
return nbytes;
|
||||
if ((p = strerror_r(e, buf.get(), 80)) != 0)
|
||||
errorMsg += p;
|
||||
|
||||
#else
|
||||
int p;
|
||||
|
||||
if ((p = strerror_r(e, buf.get(), 80)) == 0)
|
||||
errorMsg += buf.get();
|
||||
|
||||
#endif
|
||||
idbassert_s(0, errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
nleft -= nwritten;
|
||||
bufp += nwritten;
|
||||
}
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
#else
|
||||
const size_t MAX_RECV_BYTES=64*1024;
|
||||
const size_t MAX_RECV_BYTES = 64 * 1024;
|
||||
void reads(SOCKET fd, void* buf, const size_t wanted)
|
||||
{
|
||||
size_t needed = wanted;
|
||||
size_t sofar = 0;
|
||||
char* p = reinterpret_cast<char*>(buf);
|
||||
ssize_t rrc = -1;
|
||||
pollfd fds[1];
|
||||
int en = 0;
|
||||
size_t needed = wanted;
|
||||
size_t sofar = 0;
|
||||
char* p = reinterpret_cast<char*>(buf);
|
||||
ssize_t rrc = -1;
|
||||
pollfd fds[1];
|
||||
int en = 0;
|
||||
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
|
||||
while (wanted > sofar)
|
||||
{
|
||||
fds[0].revents = 0;
|
||||
poll(fds, 1, -1);
|
||||
errno = 0;
|
||||
//Windows recv() can only read so much at a time...
|
||||
int thisrecv = static_cast<int>(std::min(needed, MAX_RECV_BYTES));
|
||||
rrc = ::recv(fd, (p + sofar), thisrecv, 0);
|
||||
en = errno;
|
||||
if (rrc < 0)
|
||||
{
|
||||
if (en == EAGAIN || en == EINTR)
|
||||
continue;
|
||||
ostringstream oss;
|
||||
oss << "qfe: reads: read() returned " << rrc << " (" << strerror(en) << ")";
|
||||
idbassert_s(0, oss.str());
|
||||
}
|
||||
needed -= rrc;
|
||||
sofar += rrc;
|
||||
}
|
||||
while (wanted > sofar)
|
||||
{
|
||||
fds[0].revents = 0;
|
||||
poll(fds, 1, -1);
|
||||
errno = 0;
|
||||
//Windows recv() can only read so much at a time...
|
||||
int thisrecv = static_cast<int>(std::min(needed, MAX_RECV_BYTES));
|
||||
rrc = ::recv(fd, (p + sofar), thisrecv, 0);
|
||||
en = errno;
|
||||
|
||||
if (rrc < 0)
|
||||
{
|
||||
if (en == EAGAIN || en == EINTR)
|
||||
continue;
|
||||
|
||||
ostringstream oss;
|
||||
oss << "qfe: reads: read() returned " << rrc << " (" << strerror(en) << ")";
|
||||
idbassert_s(0, oss.str());
|
||||
}
|
||||
|
||||
needed -= rrc;
|
||||
sofar += rrc;
|
||||
}
|
||||
}
|
||||
size_t writes(SOCKET fd, const void* data, const size_t nbytes)
|
||||
{
|
||||
size_t nleft;
|
||||
ssize_t nwritten;
|
||||
const char* bufp = static_cast<const char*>(data);
|
||||
nleft = nbytes;
|
||||
size_t nleft;
|
||||
ssize_t nwritten;
|
||||
const char* bufp = static_cast<const char*>(data);
|
||||
nleft = nbytes;
|
||||
|
||||
while (nleft > 0)
|
||||
{
|
||||
int thissend = static_cast<int>(std::min(nleft, MAX_RECV_BYTES));
|
||||
nwritten = ::send(fd, bufp, thissend, 0);
|
||||
int en = errno;
|
||||
if (nwritten == SOCKET_ERROR)
|
||||
{
|
||||
int wsaerrno = WSAGetLastError();
|
||||
if (en == EINTR)
|
||||
nwritten = 0;
|
||||
else {
|
||||
ostringstream oss;
|
||||
oss << "qfe: writes: send() returned " << nwritten << " (WSA: " << wsaerrno << ")";
|
||||
idbassert_s(0, oss.str());
|
||||
}
|
||||
}
|
||||
nleft -= nwritten;
|
||||
bufp += nwritten;
|
||||
}
|
||||
while (nleft > 0)
|
||||
{
|
||||
int thissend = static_cast<int>(std::min(nleft, MAX_RECV_BYTES));
|
||||
nwritten = ::send(fd, bufp, thissend, 0);
|
||||
int en = errno;
|
||||
|
||||
return nbytes;
|
||||
if (nwritten == SOCKET_ERROR)
|
||||
{
|
||||
int wsaerrno = WSAGetLastError();
|
||||
|
||||
if (en == EINTR)
|
||||
nwritten = 0;
|
||||
else
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "qfe: writes: send() returned " << nwritten << " (WSA: " << wsaerrno << ")";
|
||||
idbassert_s(0, oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
nleft -= nwritten;
|
||||
bufp += nwritten;
|
||||
}
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t readNumber32(SockType fd)
|
||||
{
|
||||
uint32_t np;
|
||||
SockReadFcn(fd, &np, 4);
|
||||
return np;
|
||||
uint32_t np;
|
||||
SockReadFcn(fd, &np, 4);
|
||||
return np;
|
||||
}
|
||||
|
||||
string readString(SockType fd)
|
||||
{
|
||||
string s;
|
||||
uint32_t len = readNumber32(fd);
|
||||
if (len > 0)
|
||||
{
|
||||
scoped_array<char> buf(new char[len+1]);
|
||||
SockReadFcn(fd, buf.get(), len);
|
||||
buf[len] = 0;
|
||||
s = buf.get();
|
||||
}
|
||||
return s;
|
||||
string s;
|
||||
uint32_t len = readNumber32(fd);
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
scoped_array<char> buf(new char[len + 1]);
|
||||
SockReadFcn(fd, buf.get(), len);
|
||||
buf[len] = 0;
|
||||
s = buf.get();
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void writeString(SockType fd, const string& data)
|
||||
{
|
||||
uint32_t len=data.length();
|
||||
SockWriteFcn(fd, &len, 4);
|
||||
SockWriteFcn(fd, data.c_str(), len);
|
||||
uint32_t len = data.length();
|
||||
SockWriteFcn(fd, &len, 4);
|
||||
SockWriteFcn(fd, data.c_str(), len);
|
||||
}
|
||||
|
||||
} //namespace qfe::socketio
|
||||
|
Reference in New Issue
Block a user