1
0
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:
Andrew Hutchings
2017-10-26 17:18:17 +01:00
parent 4985f3456e
commit 01446d1e22
1296 changed files with 403852 additions and 353747 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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:

View File

@ -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