none
This commit is contained in:
commit
75ba4a2169
@ -67,14 +67,6 @@ static AspellApi aapi;
|
|||||||
badnames += #NM + string(" "); \
|
badnames += #NM + string(" "); \
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *aspell_progs[] = {
|
|
||||||
#ifdef ASPELL_PROG
|
|
||||||
ASPELL_PROG ,
|
|
||||||
#endif
|
|
||||||
"/usr/local/bin/aspell",
|
|
||||||
"/usr/bin/aspell"
|
|
||||||
};
|
|
||||||
static const unsigned int naspellprogs = sizeof(aspell_progs) / sizeof(char*);
|
|
||||||
static const char *aspell_lib_suffixes[] = {
|
static const char *aspell_lib_suffixes[] = {
|
||||||
".so",
|
".so",
|
||||||
".so.15",
|
".so.15",
|
||||||
@ -137,12 +129,18 @@ bool Aspell::init(string &reason)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_data = new AspellData;
|
m_data = new AspellData;
|
||||||
for (unsigned int i = 0; i < naspellprogs; i++) {
|
|
||||||
if (access(aspell_progs[i], X_OK) == 0) {
|
const char *aspell_prog_from_env = getenv("ASPELL_PROG");
|
||||||
m_data->m_exec = aspell_progs[i];
|
if (aspell_prog_from_env && access(aspell_prog_from_env, X_OK) == 0) {
|
||||||
break;
|
m_data->m_exec = aspell_prog_from_env;
|
||||||
}
|
#ifdef ASPELL_PROG
|
||||||
|
} else if (access(ASPELL_PROG, X_OK) == 0) {
|
||||||
|
m_data->m_exec = ASPELL_PROG;
|
||||||
|
#endif // ASPELL_PROG
|
||||||
|
} else {
|
||||||
|
ExecCmd::which("aspell", m_data->m_exec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_data->m_exec.empty()) {
|
if (m_data->m_exec.empty()) {
|
||||||
reason = "aspell program not found or not executable";
|
reason = "aspell program not found or not executable";
|
||||||
deleteZ(m_data);
|
deleteZ(m_data);
|
||||||
@ -153,9 +151,8 @@ bool Aspell::init(string &reason)
|
|||||||
// be clever with ASPELL_PROG.
|
// be clever with ASPELL_PROG.
|
||||||
vector<string> libdirs;
|
vector<string> libdirs;
|
||||||
libdirs.push_back(LIBDIR);
|
libdirs.push_back(LIBDIR);
|
||||||
#ifdef ASPELL_PROG
|
// If not in the standard place, the aspell library has to live
|
||||||
// The aspell library has to live under the same prefix as the
|
// under the same prefix as the aspell program.
|
||||||
// aspell program.
|
|
||||||
{
|
{
|
||||||
string aspellPrefix = path_getfather(path_getfather(m_data->m_exec));
|
string aspellPrefix = path_getfather(path_getfather(m_data->m_exec));
|
||||||
// This would probably require some more tweaking on solaris/irix etc.
|
// This would probably require some more tweaking on solaris/irix etc.
|
||||||
@ -164,7 +161,6 @@ bool Aspell::init(string &reason)
|
|||||||
if (libaspell != LIBDIR)
|
if (libaspell != LIBDIR)
|
||||||
libdirs.push_back(libaspell);
|
libdirs.push_back(libaspell);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
reason = "Could not open shared library ";
|
reason = "Could not open shared library ";
|
||||||
for (vector<string>::iterator it = libdirs.begin();
|
for (vector<string>::iterator it = libdirs.begin();
|
||||||
|
|||||||
@ -17,6 +17,12 @@ autom4*
|
|||||||
config.cache
|
config.cache
|
||||||
config.log
|
config.log
|
||||||
config.status
|
config.status
|
||||||
|
doc/user/usermanual.aux
|
||||||
|
doc/user/usermanual.log
|
||||||
|
doc/user/usermanual.out
|
||||||
|
doc/user/usermanual.pdf
|
||||||
|
doc/user/usermanual.tex-pdf
|
||||||
|
doc/user/usermanual.tex-pdf-tmp
|
||||||
excludefile
|
excludefile
|
||||||
kde/recoll_applet
|
kde/recoll_applet
|
||||||
lib/librcl.a
|
lib/librcl.a
|
||||||
|
|||||||
@ -437,6 +437,7 @@ utils/netcon.cpp
|
|||||||
utils/netcon.h
|
utils/netcon.h
|
||||||
utils/pathut.cpp
|
utils/pathut.cpp
|
||||||
utils/pathut.h
|
utils/pathut.h
|
||||||
|
utils/ptmutex.h
|
||||||
utils/pxattr.cpp
|
utils/pxattr.cpp
|
||||||
utils/pxattr.h
|
utils/pxattr.h
|
||||||
utils/readfile.cpp
|
utils/readfile.cpp
|
||||||
|
|||||||
@ -72,7 +72,7 @@ void startManual(const string& helpindex)
|
|||||||
mainWindow->startManual(helpindex);
|
mainWindow->startManual(helpindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool maybeOpenDb(string &reason, bool force)
|
bool maybeOpenDb(string &reason, bool force, bool *maindberror)
|
||||||
{
|
{
|
||||||
if (!rcldb) {
|
if (!rcldb) {
|
||||||
reason = "Internal error: db not created";
|
reason = "Internal error: db not created";
|
||||||
@ -87,9 +87,13 @@ bool maybeOpenDb(string &reason, bool force)
|
|||||||
LOGDEB(("main: adding [%s]\n", it->c_str()));
|
LOGDEB(("main: adding [%s]\n", it->c_str()));
|
||||||
rcldb->addQueryDb(*it);
|
rcldb->addQueryDb(*it);
|
||||||
}
|
}
|
||||||
if (!rcldb->isopen() && !rcldb->open(Rcl::Db::DbRO)) {
|
Rcl::Db::OpenError error;
|
||||||
|
if (!rcldb->isopen() && !rcldb->open(Rcl::Db::DbRO, &error)) {
|
||||||
reason = "Could not open database in " +
|
reason = "Could not open database in " +
|
||||||
theconfig->getDbDir() + " wait for indexing to complete?";
|
theconfig->getDbDir() + " wait for indexing to complete?";
|
||||||
|
if (maindberror) {
|
||||||
|
*maindberror = (error == Rcl::Db::DbOpenMainDb) ? true : false;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rcldb->setAbstractParams(-1, prefs.syntAbsLen, prefs.syntAbsCtx);
|
rcldb->setAbstractParams(-1, prefs.syntAbsLen, prefs.syntAbsCtx);
|
||||||
@ -114,7 +118,7 @@ static void recollCleanup()
|
|||||||
LOGDEB2(("recollCleanup: closing database\n"));
|
LOGDEB2(("recollCleanup: closing database\n"));
|
||||||
deleteZ(rcldb);
|
deleteZ(rcldb);
|
||||||
deleteZ(theconfig);
|
deleteZ(theconfig);
|
||||||
deleteZ(thestableconfig);
|
// deleteZ(thestableconfig);
|
||||||
#ifdef RCL_USE_ASPELL
|
#ifdef RCL_USE_ASPELL
|
||||||
deleteZ(aspell);
|
deleteZ(aspell);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -345,25 +345,31 @@ void RclMain::initDbOpen()
|
|||||||
bool needindexconfig = false;
|
bool needindexconfig = false;
|
||||||
bool nodb = false;
|
bool nodb = false;
|
||||||
string reason;
|
string reason;
|
||||||
if (!maybeOpenDb(reason)) {
|
bool maindberror;
|
||||||
|
if (!maybeOpenDb(reason, true, &maindberror)) {
|
||||||
nodb = true;
|
nodb = true;
|
||||||
switch (QMessageBox::
|
if (maindberror) {
|
||||||
question
|
switch (QMessageBox::
|
||||||
(this, "Recoll",
|
question
|
||||||
qApp->translate("Main", "Could not open database in ") +
|
(this, "Recoll",
|
||||||
QString::fromLocal8Bit(theconfig->getDbDir().c_str()) +
|
qApp->translate("Main", "Could not open database in ") +
|
||||||
qApp->translate("Main",
|
QString::fromLocal8Bit(theconfig->getDbDir().c_str()) +
|
||||||
".\n"
|
qApp->translate("Main",
|
||||||
"Click Cancel if you want to edit the configuration file before indexing starts, or Ok to let it proceed."),
|
".\n"
|
||||||
"Ok", "Cancel", 0, 0)) {
|
"Click Cancel if you want to edit the configuration file before indexing starts, or Ok to let it proceed."),
|
||||||
|
"Ok", "Cancel", 0, 0)) {
|
||||||
|
|
||||||
case 0: // Ok: indexing is going to start.
|
case 0: // Ok: indexing is going to start.
|
||||||
start_indexing(true);
|
start_indexing(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // Cancel
|
case 1: // Cancel
|
||||||
needindexconfig = true;
|
needindexconfig = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(0, "Recoll",
|
||||||
|
tr("Could not open external index. Db not open. Check external indexes list."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,8 @@
|
|||||||
// Misc declarations in need of sharing between the UI files
|
// Misc declarations in need of sharing between the UI files
|
||||||
|
|
||||||
// Open the database if needed. We now force a close/open by default
|
// Open the database if needed. We now force a close/open by default
|
||||||
extern bool maybeOpenDb(std::string &reason, bool force = true);
|
extern bool maybeOpenDb(std::string &reason, bool force = true,
|
||||||
|
bool *maindberror = 0);
|
||||||
|
|
||||||
/** Retrieve configured stemming languages */
|
/** Retrieve configured stemming languages */
|
||||||
bool getStemLangs(list<string>& langs);
|
bool getStemLangs(list<string>& langs);
|
||||||
|
|||||||
@ -534,8 +534,11 @@ list<string> Db::getStemmerNames()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Db::open(OpenMode mode)
|
bool Db::open(OpenMode mode, OpenError *error)
|
||||||
{
|
{
|
||||||
|
if (error)
|
||||||
|
*error = DbOpenMainDb;
|
||||||
|
|
||||||
if (m_ndb == 0 || m_config == 0) {
|
if (m_ndb == 0 || m_config == 0) {
|
||||||
m_reason = "Null configuration or Xapian Db";
|
m_reason = "Null configuration or Xapian Db";
|
||||||
return false;
|
return false;
|
||||||
@ -586,12 +589,17 @@ bool Db::open(OpenMode mode)
|
|||||||
m_ndb->xrdb = Xapian::Database(dir);
|
m_ndb->xrdb = Xapian::Database(dir);
|
||||||
for (list<string>::iterator it = m_extraDbs.begin();
|
for (list<string>::iterator it = m_extraDbs.begin();
|
||||||
it != m_extraDbs.end(); it++) {
|
it != m_extraDbs.end(); it++) {
|
||||||
|
if (error)
|
||||||
|
*error = DbOpenExtraDb;
|
||||||
LOGDEB(("Db::Open: adding query db [%s]\n", it->c_str()));
|
LOGDEB(("Db::Open: adding query db [%s]\n", it->c_str()));
|
||||||
// Used to be non-fatal (1.13 and older) but I can't see why
|
// An error here used to be non-fatal (1.13 and older)
|
||||||
|
// but I can't see why
|
||||||
m_ndb->xrdb.add_database(Xapian::Database(*it));
|
m_ndb->xrdb.add_database(Xapian::Database(*it));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (error)
|
||||||
|
*error = DbOpenMainDb;
|
||||||
|
|
||||||
// Check index format version. Must not try to check a just created or
|
// Check index format version. Must not try to check a just created or
|
||||||
// truncated db
|
// truncated db
|
||||||
@ -608,6 +616,8 @@ bool Db::open(OpenMode mode)
|
|||||||
m_mode = mode;
|
m_mode = mode;
|
||||||
m_ndb->m_isopen = true;
|
m_ndb->m_isopen = true;
|
||||||
m_basedir = dir;
|
m_basedir = dir;
|
||||||
|
if (error)
|
||||||
|
*error = DbOpenNoError;
|
||||||
return true;
|
return true;
|
||||||
} XCATCHERROR(ermsg);
|
} XCATCHERROR(ermsg);
|
||||||
|
|
||||||
|
|||||||
@ -95,7 +95,8 @@ class Db {
|
|||||||
~Db();
|
~Db();
|
||||||
|
|
||||||
enum OpenMode {DbRO, DbUpd, DbTrunc};
|
enum OpenMode {DbRO, DbUpd, DbTrunc};
|
||||||
bool open(OpenMode mode);
|
enum OpenError {DbOpenNoError, DbOpenMainDb, DbOpenExtraDb};
|
||||||
|
bool open(OpenMode mode, OpenError *error = 0);
|
||||||
bool close();
|
bool close();
|
||||||
bool isopen();
|
bool isopen();
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
depth = ..
|
depth = ..
|
||||||
include $(depth)/mk/sysconf
|
include $(depth)/mk/sysconf
|
||||||
|
|
||||||
PROGS = trcopyfile trcircache trmd5 trreadfile trfileudi trconftree \
|
PROGS = trnetcon trcopyfile trcircache trmd5 trreadfile trfileudi trconftree \
|
||||||
wipedir smallut \
|
wipedir smallut \
|
||||||
trfstreewalk trpathut \
|
trfstreewalk trpathut \
|
||||||
transcode trbase64 \
|
transcode trbase64 \
|
||||||
trmimeparse trexecmd utf8iter idfile
|
trmimeparse trexecmd utf8iter idfile
|
||||||
|
|
||||||
all: $(PROGS) $(BIGLIB)
|
all: $(PROGS) $(BIGLIB)
|
||||||
|
|
||||||
@ -54,6 +54,12 @@ trpathut : $(PATHUT_OBJS)
|
|||||||
trpathut.o : pathut.cpp pathut.h
|
trpathut.o : pathut.cpp pathut.h
|
||||||
$(CXX) -o trpathut.o -c $(ALL_CXXFLAGS) -DTEST_PATHUT pathut.cpp
|
$(CXX) -o trpathut.o -c $(ALL_CXXFLAGS) -DTEST_PATHUT pathut.cpp
|
||||||
|
|
||||||
|
NETCON_OBJS= trnetcon.o $(BIGLIB)
|
||||||
|
trnetcon : $(NETCON_OBJS)
|
||||||
|
$(CXX) $(ALL_CXXFLAGS) -o trnetcon $(NETCON_OBJS) $(LIBICONV) $(LIBSYS)
|
||||||
|
trnetcon.o : netcon.cpp netcon.h
|
||||||
|
$(CXX) -o trnetcon.o -c $(ALL_CXXFLAGS) -DTEST_NETCON netcon.cpp
|
||||||
|
|
||||||
FILEUDI_OBJS= trfileudi.o $(BIGLIB)
|
FILEUDI_OBJS= trfileudi.o $(BIGLIB)
|
||||||
trfileudi : $(FILEUDI_OBJS)
|
trfileudi : $(FILEUDI_OBJS)
|
||||||
$(CXX) $(ALL_CXXFLAGS) -o trfileudi $(FILEUDI_OBJS)
|
$(CXX) $(ALL_CXXFLAGS) -o trfileudi $(FILEUDI_OBJS)
|
||||||
|
|||||||
@ -76,7 +76,7 @@ static bool inflateToDynBuf(void *inp, UINT inlen, void **outpp, UINT *outlenp);
|
|||||||
// Entry header.
|
// Entry header.
|
||||||
// 3 x 32 bits sizes as hex integers + 1 x 16 bits flag + at least 1 zero
|
// 3 x 32 bits sizes as hex integers + 1 x 16 bits flag + at least 1 zero
|
||||||
// 15 + 3x(9) + 3 + 1 = 46
|
// 15 + 3x(9) + 3 + 1 = 46
|
||||||
const char *headerformat = "circacheSizes = %x %x %x %hx";
|
static const char *headerformat = "circacheSizes = %x %x %x %hx";
|
||||||
#define CIRCACHE_HEADER_SIZE 64
|
#define CIRCACHE_HEADER_SIZE 64
|
||||||
|
|
||||||
class EntryHeaderData {
|
class EntryHeaderData {
|
||||||
|
|||||||
@ -335,7 +335,11 @@ DebugLog *getdbl()
|
|||||||
}
|
}
|
||||||
DebugLog *dbl;
|
DebugLog *dbl;
|
||||||
if (!(dbl = (DebugLog *)pthread_getspecific(dbl_key))) {
|
if (!(dbl = (DebugLog *)pthread_getspecific(dbl_key))) {
|
||||||
dbl = new DebugLog;
|
if ((dbl = new DebugLog) == 0) {
|
||||||
|
fprintf(stderr, "debuglog: new DebugLog returned 0! ");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
dbl->setwriter(theWriter);
|
dbl->setwriter(theWriter);
|
||||||
initfiles();
|
initfiles();
|
||||||
status = pthread_setspecific(dbl_key, dbl);
|
status = pthread_setspecific(dbl_key, dbl);
|
||||||
|
|||||||
@ -313,16 +313,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// The netcon selectloop that doexec() uses for reading/writing would
|
|
||||||
// be complicated to render thread-safe. Use locking to ensure only
|
|
||||||
// one thread in there
|
|
||||||
static PTMutexInit o_lock;
|
|
||||||
|
|
||||||
int ExecCmd::doexec(const string &cmd, const list<string>& args,
|
int ExecCmd::doexec(const string &cmd, const list<string>& args,
|
||||||
const string *input, string *output)
|
const string *input, string *output)
|
||||||
{
|
{
|
||||||
// Only one thread allowed in here...
|
|
||||||
PTMutexLocker locker(o_lock);
|
|
||||||
|
|
||||||
if (startExec(cmd, args, input != 0, output != 0) < 0) {
|
if (startExec(cmd, args, input != 0, output != 0) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -330,7 +323,7 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
|
|||||||
|
|
||||||
// Cleanup in case we return early
|
// Cleanup in case we return early
|
||||||
ExecCmdRsrc e(this);
|
ExecCmdRsrc e(this);
|
||||||
|
SelectLoop myloop;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (input || output) {
|
if (input || output) {
|
||||||
// Setup output
|
// Setup output
|
||||||
@ -342,7 +335,7 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
|
|||||||
}
|
}
|
||||||
oclicon->setcallback(RefCntr<NetconWorker>
|
oclicon->setcallback(RefCntr<NetconWorker>
|
||||||
(new ExecReader(output, m_advise)));
|
(new ExecReader(output, m_advise)));
|
||||||
Netcon::addselcon(m_fromcmd, Netcon::NETCONPOLL_READ);
|
myloop.addselcon(m_fromcmd, Netcon::NETCONPOLL_READ);
|
||||||
// Give up ownership
|
// Give up ownership
|
||||||
m_fromcmd.release();
|
m_fromcmd.release();
|
||||||
}
|
}
|
||||||
@ -355,14 +348,14 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
|
|||||||
}
|
}
|
||||||
iclicon->setcallback(RefCntr<NetconWorker>
|
iclicon->setcallback(RefCntr<NetconWorker>
|
||||||
(new ExecWriter(input, m_provide)));
|
(new ExecWriter(input, m_provide)));
|
||||||
Netcon::addselcon(m_tocmd, Netcon::NETCONPOLL_WRITE);
|
myloop.addselcon(m_tocmd, Netcon::NETCONPOLL_WRITE);
|
||||||
// Give up ownership
|
// Give up ownership
|
||||||
m_tocmd.release();
|
m_tocmd.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the actual reading/writing/waiting
|
// Do the actual reading/writing/waiting
|
||||||
Netcon::setperiodichandler(0, 0, m_timeoutMs);
|
myloop.setperiodichandler(0, 0, m_timeoutMs);
|
||||||
while ((ret = Netcon::selectloop()) > 0) {
|
while ((ret = myloop.doLoop()) > 0) {
|
||||||
LOGDEB(("ExecCmd::doexec: selectloop returned %d\n", ret));
|
LOGDEB(("ExecCmd::doexec: selectloop returned %d\n", ret));
|
||||||
if (m_advise)
|
if (m_advise)
|
||||||
m_advise->newData(0);
|
m_advise->newData(0);
|
||||||
|
|||||||
@ -83,46 +83,23 @@ int Netcon::select1(int fd, int timeo, int write)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The select loop mechanism allows several netcons to be used for io
|
void SelectLoop::setperiodichandler(int (*handler)(void *), void *p, int ms)
|
||||||
// in a program without blocking as long as there is data to be read
|
|
||||||
// or written.
|
|
||||||
|
|
||||||
// Set by client callback to tell selectloop to return.
|
|
||||||
bool Netcon::o_selectloopDoReturn;
|
|
||||||
int Netcon::o_selectloopReturnValue;
|
|
||||||
|
|
||||||
// Other static data for the selectloop mecanism
|
|
||||||
// Could be declared as static members, but I don't see any advantage
|
|
||||||
// to it as all code in this file is in Netcon:: anyway.
|
|
||||||
|
|
||||||
// Map of NetconP indexed by fd
|
|
||||||
static map<int, NetconP> polldata;
|
|
||||||
|
|
||||||
// The last time we did the periodic thing
|
|
||||||
static struct timeval lasthdlcall;
|
|
||||||
// The call back function and its parameter
|
|
||||||
static int (*periodichandler)(void *);
|
|
||||||
static void *periodicparam;
|
|
||||||
// The periodic interval
|
|
||||||
static int periodicmillis;
|
|
||||||
|
|
||||||
void Netcon::setperiodichandler(int (*handler)(void *), void *p, int ms)
|
|
||||||
{
|
{
|
||||||
periodichandler = handler;
|
m_periodichandler = handler;
|
||||||
periodicparam = p;
|
m_periodicparam = p;
|
||||||
periodicmillis = ms;
|
m_periodicmillis = ms;
|
||||||
if (periodicmillis > 0)
|
if (m_periodicmillis > 0)
|
||||||
gettimeofday(&lasthdlcall, 0);
|
gettimeofday(&m_lasthdlcall, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the appropriate timeout so that the select call returns in
|
// Compute the appropriate timeout so that the select call returns in
|
||||||
// time to call the periodic routine.
|
// time to call the periodic routine.
|
||||||
static void periodictimeout(struct timeval *tv)
|
void SelectLoop::periodictimeout(struct timeval *tv)
|
||||||
{
|
{
|
||||||
// If periodic not set, the select call times out and we loop
|
// If periodic not set, the select call times out and we loop
|
||||||
// after a very long time (we'd need to pass NULL to select for an
|
// after a very long time (we'd need to pass NULL to select for an
|
||||||
// infinite wait, and I'm too lazy to handle it)
|
// infinite wait, and I'm too lazy to handle it)
|
||||||
if (periodicmillis <= 0) {
|
if (m_periodicmillis <= 0) {
|
||||||
tv->tv_sec = 10000;
|
tv->tv_sec = 10000;
|
||||||
tv->tv_usec = 0;
|
tv->tv_usec = 0;
|
||||||
return;
|
return;
|
||||||
@ -130,7 +107,7 @@ static void periodictimeout(struct timeval *tv)
|
|||||||
|
|
||||||
struct timeval mtv;
|
struct timeval mtv;
|
||||||
gettimeofday(&mtv, 0);
|
gettimeofday(&mtv, 0);
|
||||||
int millis = periodicmillis - MILLIS(lasthdlcall, mtv);
|
int millis = m_periodicmillis - MILLIS(m_lasthdlcall, mtv);
|
||||||
|
|
||||||
// millis <= 0 means we should have already done the thing. *dont* set the
|
// millis <= 0 means we should have already done the thing. *dont* set the
|
||||||
// tv to 0, which means no timeout at all !
|
// tv to 0, which means no timeout at all !
|
||||||
@ -142,50 +119,49 @@ static void periodictimeout(struct timeval *tv)
|
|||||||
|
|
||||||
// Check if it's time to call the handler. selectloop will return to
|
// Check if it's time to call the handler. selectloop will return to
|
||||||
// caller if it or we return 0
|
// caller if it or we return 0
|
||||||
static int maybecallperiodic()
|
int SelectLoop::maybecallperiodic()
|
||||||
{
|
{
|
||||||
if (periodicmillis <= 0)
|
if (m_periodicmillis <= 0)
|
||||||
return 1;
|
return 1;
|
||||||
struct timeval mtv;
|
struct timeval mtv;
|
||||||
gettimeofday(&mtv, 0);
|
gettimeofday(&mtv, 0);
|
||||||
int millis = periodicmillis - MILLIS(lasthdlcall, mtv);
|
int millis = m_periodicmillis - MILLIS(m_lasthdlcall, mtv);
|
||||||
if (millis <= 0) {
|
if (millis <= 0) {
|
||||||
gettimeofday(&lasthdlcall, 0);
|
gettimeofday(&m_lasthdlcall, 0);
|
||||||
if (periodichandler)
|
if (m_periodichandler)
|
||||||
return periodichandler(periodicparam);
|
return m_periodichandler(m_periodicparam);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Netcon::selectloop()
|
int SelectLoop::doLoop()
|
||||||
{
|
{
|
||||||
static int placetostart;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (o_selectloopDoReturn) {
|
if (m_selectloopDoReturn) {
|
||||||
o_selectloopDoReturn = false;
|
m_selectloopDoReturn = false;
|
||||||
LOGDEB(("Netcon::selectloop: returning on request\n"));
|
LOGDEB(("Netcon::selectloop: returning on request\n"));
|
||||||
return o_selectloopReturnValue;
|
return m_selectloopReturnValue;
|
||||||
}
|
}
|
||||||
int nfds;
|
int nfds;
|
||||||
fd_set rd, wd;
|
fd_set rd, wd;
|
||||||
FD_ZERO(&rd);
|
FD_ZERO(&rd);
|
||||||
FD_ZERO(&wd);
|
FD_ZERO(&wd);
|
||||||
|
|
||||||
// Look for all descriptors in the map and set up the read and
|
// Walk the netcon map and set up the read and write fd_sets
|
||||||
// write fd_sets for select()
|
// for select()
|
||||||
nfds = 0;
|
nfds = 0;
|
||||||
for (map<int,NetconP>::iterator it = polldata.begin();
|
for (map<int,NetconP>::iterator it = m_polldata.begin();
|
||||||
it != polldata.end(); it++) {
|
it != m_polldata.end(); it++) {
|
||||||
NetconP &pll = it->second;
|
NetconP &pll = it->second;
|
||||||
int fd = it->first;
|
int fd = it->first;
|
||||||
LOGDEB2(("Selectloop: fd %d flags 0x%x\n",fd, pll->m_wantedEvents));
|
LOGDEB2(("Selectloop: fd %d flags 0x%x\n",fd, pll->m_wantedEvents));
|
||||||
if (pll->m_wantedEvents & NETCONPOLL_READ) {
|
if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
|
||||||
FD_SET(fd, &rd);
|
FD_SET(fd, &rd);
|
||||||
nfds = MAX(nfds, fd + 1);
|
nfds = MAX(nfds, fd + 1);
|
||||||
}
|
}
|
||||||
if (pll->m_wantedEvents & NETCONPOLL_WRITE) {
|
if (pll->m_wantedEvents & Netcon::NETCONPOLL_WRITE) {
|
||||||
FD_SET(fd, &wd);
|
FD_SET(fd, &wd);
|
||||||
nfds = MAX(nfds, fd + 1);
|
nfds = MAX(nfds, fd + 1);
|
||||||
}
|
}
|
||||||
@ -199,7 +175,7 @@ int Netcon::selectloop()
|
|||||||
|
|
||||||
// Just in case there would still be open fds in there
|
// Just in case there would still be open fds in there
|
||||||
// (with no r/w flags set). Should not be needed, but safer
|
// (with no r/w flags set). Should not be needed, but safer
|
||||||
polldata.clear();
|
m_polldata.clear();
|
||||||
LOGDEB1(("Netcon::selectloop: no fds\n"));
|
LOGDEB1(("Netcon::selectloop: no fds\n"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -217,7 +193,7 @@ int Netcon::selectloop()
|
|||||||
LOGSYSERR("Netcon::selectloop", "select", "");
|
LOGSYSERR("Netcon::selectloop", "select", "");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (periodicmillis > 0)
|
if (m_periodicmillis > 0)
|
||||||
if (maybecallperiodic() <= 0)
|
if (maybecallperiodic() <= 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -231,10 +207,10 @@ int Netcon::selectloop()
|
|||||||
// map may change between 2 sweeps, so that we'd have to be smart
|
// map may change between 2 sweeps, so that we'd have to be smart
|
||||||
// with the iterator. As the cost per unused fd is low (just 2 bit
|
// with the iterator. As the cost per unused fd is low (just 2 bit
|
||||||
// flag tests), we keep it like this for now
|
// flag tests), we keep it like this for now
|
||||||
if (placetostart >= nfds)
|
if (m_placetostart >= nfds)
|
||||||
placetostart = 0;
|
m_placetostart = 0;
|
||||||
int i, fd;
|
int i, fd;
|
||||||
for (i = 0, fd = placetostart; i < nfds;i++, fd++) {
|
for (i = 0, fd = m_placetostart; i < nfds;i++, fd++) {
|
||||||
if (fd >= nfds)
|
if (fd >= nfds)
|
||||||
fd = 0;
|
fd = 0;
|
||||||
|
|
||||||
@ -247,53 +223,56 @@ int Netcon::selectloop()
|
|||||||
if (none)
|
if (none)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
map<int,NetconP>::iterator it = polldata.find(fd);
|
map<int,NetconP>::iterator it = m_polldata.find(fd);
|
||||||
if (it == polldata.end()) {
|
if (it == m_polldata.end()) {
|
||||||
/// This should not happen actually
|
/// This should not happen actually
|
||||||
LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd));
|
LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next start will be one beyond last serviced (modulo nfds)
|
// Next start will be one beyond last serviced (modulo nfds)
|
||||||
placetostart = fd + 1;
|
m_placetostart = fd + 1;
|
||||||
NetconP &pll = it->second;
|
NetconP &pll = it->second;
|
||||||
if (canread && pll->cando(NETCONPOLL_READ) <= 0)
|
if (canread && pll->cando(Netcon::NETCONPOLL_READ) <= 0)
|
||||||
pll->m_wantedEvents &= ~NETCONPOLL_READ;
|
pll->m_wantedEvents &= ~Netcon::NETCONPOLL_READ;
|
||||||
if (canwrite && pll->cando(NETCONPOLL_WRITE) <= 0)
|
if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0)
|
||||||
pll->m_wantedEvents &= ~NETCONPOLL_WRITE;
|
pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE;
|
||||||
if (!(pll->m_wantedEvents & (NETCONPOLL_WRITE|NETCONPOLL_READ))) {
|
if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE|Netcon::NETCONPOLL_READ))) {
|
||||||
LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n",
|
LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n",
|
||||||
it->first, it->second->m_wantedEvents));
|
it->first, it->second->m_wantedEvents));
|
||||||
polldata.erase(it);
|
m_polldata.erase(it);
|
||||||
}
|
}
|
||||||
} // fd sweep
|
} // fd sweep
|
||||||
|
|
||||||
} // forever loop
|
} // forever loop
|
||||||
LOGERR(("Netcon::selectloop: got out of loop !\n"));
|
LOGERR(("SelectLoop::doLoop: got out of loop !\n"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a connection to the monitored set.
|
// Add a connection to the monitored set.
|
||||||
int Netcon::addselcon(NetconP con, int events)
|
int SelectLoop::addselcon(NetconP con, int events)
|
||||||
{
|
{
|
||||||
if (con.isNull()) return -1;
|
if (con.isNull()) return -1;
|
||||||
LOGDEB1(("Netcon::addselcon: fd %d\n", con->m_fd));
|
LOGDEB1(("Netcon::addselcon: fd %d\n", con->m_fd));
|
||||||
con->set_nonblock(1);
|
con->set_nonblock(1);
|
||||||
con->setselevents(events);
|
con->setselevents(events);
|
||||||
polldata[con->m_fd] = con;
|
m_polldata[con->m_fd] = con;
|
||||||
|
con->setloop(this);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a connection from the monitored set.
|
// Remove a connection from the monitored set.
|
||||||
int Netcon::remselcon(NetconP con)
|
int SelectLoop::remselcon(NetconP con)
|
||||||
{
|
{
|
||||||
if (con.isNull()) return -1;
|
if (con.isNull()) return -1;
|
||||||
LOGDEB1(("Netcon::remselcon: fd %d\n", con->m_fd));
|
LOGDEB1(("Netcon::remselcon: fd %d\n", con->m_fd));
|
||||||
map<int,NetconP>::iterator it = polldata.find(con->m_fd);
|
map<int,NetconP>::iterator it = m_polldata.find(con->m_fd);
|
||||||
if (it == polldata.end()) {
|
if (it == m_polldata.end()) {
|
||||||
LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd));
|
LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
polldata.erase(it);
|
con->setloop(0);
|
||||||
|
m_polldata.erase(it);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,7 +948,7 @@ int main(int argc, char **argv)
|
|||||||
argv++;
|
argv++;
|
||||||
}
|
}
|
||||||
DebugLog::setfilename("stderr");
|
DebugLog::setfilename("stderr");
|
||||||
DebugLog::getdbl()->setloglevel(DEBINFO);
|
DebugLog::getdbl()->setloglevel(DEBDEB2);
|
||||||
|
|
||||||
if (op_flags & OPT_c) {
|
if (op_flags & OPT_c) {
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
@ -1032,7 +1011,8 @@ public:
|
|||||||
}
|
}
|
||||||
if (m_count >= 10) {
|
if (m_count >= 10) {
|
||||||
fprintf(stderr, "Did 10, enough\n");
|
fprintf(stderr, "Did 10, enough\n");
|
||||||
Netcon::selectloopReturn(0);
|
if (con->getloop())
|
||||||
|
con->getloop()->loopReturn(0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1077,9 +1057,10 @@ int trycli(char *host, char *serv)
|
|||||||
RefCntr<NetconWorker> worker =
|
RefCntr<NetconWorker> worker =
|
||||||
RefCntr<NetconWorker>(new CliNetconWorker());
|
RefCntr<NetconWorker>(new CliNetconWorker());
|
||||||
clicon->setcallback(worker);
|
clicon->setcallback(worker);
|
||||||
Netcon::addselcon(con, Netcon::NETCONPOLL_WRITE);
|
SelectLoop myloop;
|
||||||
|
myloop.addselcon(con, Netcon::NETCONPOLL_WRITE);
|
||||||
fprintf(stderr, "client ready\n");
|
fprintf(stderr, "client ready\n");
|
||||||
int ret = Netcon::selectloop();
|
int ret = myloop.doLoop();
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "selectloop failed\n");
|
fprintf(stderr, "selectloop failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -1130,6 +1111,11 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class MyNetconServLis : public NetconServLis {
|
class MyNetconServLis : public NetconServLis {
|
||||||
|
public:
|
||||||
|
MyNetconServLis(SelectLoop &loop)
|
||||||
|
: NetconServLis(), m_loop(loop)
|
||||||
|
{
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
int cando(Netcon::Event reason) {
|
int cando(Netcon::Event reason) {
|
||||||
NetconServCon *con = accept();
|
NetconServCon *con = accept();
|
||||||
@ -1138,9 +1124,10 @@ protected:
|
|||||||
RefCntr<NetconWorker> worker =
|
RefCntr<NetconWorker> worker =
|
||||||
RefCntr<NetconWorker>(new ServNetconWorker());
|
RefCntr<NetconWorker>(new ServNetconWorker());
|
||||||
con->setcallback(worker);
|
con->setcallback(worker);
|
||||||
addselcon(NetconP(con), NETCONPOLL_READ);
|
m_loop.addselcon(NetconP(con), NETCONPOLL_READ);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
SelectLoop& m_loop;
|
||||||
};
|
};
|
||||||
|
|
||||||
NetconP lis;
|
NetconP lis;
|
||||||
@ -1158,7 +1145,8 @@ onexit(int sig)
|
|||||||
int tryserv(char *serv)
|
int tryserv(char *serv)
|
||||||
{
|
{
|
||||||
signal(SIGCHLD, SIG_IGN);
|
signal(SIGCHLD, SIG_IGN);
|
||||||
MyNetconServLis *servlis = new MyNetconServLis();
|
SelectLoop myloop;
|
||||||
|
MyNetconServLis *servlis = new MyNetconServLis(myloop);
|
||||||
lis = NetconP(servlis);
|
lis = NetconP(servlis);
|
||||||
if (lis.isNull()) {
|
if (lis.isNull()) {
|
||||||
fprintf(stderr, "new NetconServLis failed\n");
|
fprintf(stderr, "new NetconServLis failed\n");
|
||||||
@ -1178,9 +1166,9 @@ int tryserv(char *serv)
|
|||||||
fprintf(stderr, "openservice(%s) failed\n", serv);
|
fprintf(stderr, "openservice(%s) failed\n", serv);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
Netcon::addselcon(lis, Netcon::NETCONPOLL_READ);
|
myloop.addselcon(lis, Netcon::NETCONPOLL_READ);
|
||||||
fprintf(stderr, "openservice(%s) Ok\n", serv);
|
fprintf(stderr, "openservice(%s) Ok\n", serv);
|
||||||
if (Netcon::selectloop() < 0) {
|
if (myloop.doLoop() < 0) {
|
||||||
fprintf(stderr, "selectloop failed\n");
|
fprintf(stderr, "selectloop failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,8 +16,12 @@
|
|||||||
* Free Software Foundation, Inc.,
|
* Free Software Foundation, Inc.,
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <map>
|
||||||
#include "refcntr.h"
|
#include "refcntr.h"
|
||||||
|
|
||||||
|
using std::map;
|
||||||
|
|
||||||
/// A set of classes to manage client-server communication over a
|
/// A set of classes to manage client-server communication over a
|
||||||
/// connection-oriented network, or a pipe.
|
/// connection-oriented network, or a pipe.
|
||||||
///
|
///
|
||||||
@ -34,12 +38,14 @@
|
|||||||
/// Base class for all network endpoints:
|
/// Base class for all network endpoints:
|
||||||
class Netcon;
|
class Netcon;
|
||||||
typedef RefCntr<Netcon> NetconP;
|
typedef RefCntr<Netcon> NetconP;
|
||||||
|
class SelectLoop;
|
||||||
|
|
||||||
class Netcon {
|
class Netcon {
|
||||||
public:
|
public:
|
||||||
enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE=0x2};
|
enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE=0x2};
|
||||||
Netcon()
|
Netcon()
|
||||||
: m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0)
|
: m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0),
|
||||||
|
m_loop(0)
|
||||||
{}
|
{}
|
||||||
virtual ~Netcon();
|
virtual ~Netcon();
|
||||||
/// Remember whom we're talking to. We let external code do this because
|
/// Remember whom we're talking to. We let external code do this because
|
||||||
@ -75,12 +81,41 @@ public:
|
|||||||
/// Clear events from current set
|
/// Clear events from current set
|
||||||
int clearselevents(int evs) {return m_wantedEvents &= ~evs;}
|
int clearselevents(int evs) {return m_wantedEvents &= ~evs;}
|
||||||
|
|
||||||
|
friend class SelectLoop;
|
||||||
|
SelectLoop *getloop() {return m_loop;}
|
||||||
|
|
||||||
/// Utility function for a simplified select() interface: check one fd
|
/// Utility function for a simplified select() interface: check one fd
|
||||||
/// for reading or writing, for a specified maximum number of seconds.
|
/// for reading or writing, for a specified maximum number of seconds.
|
||||||
static int select1(int fd, int secs, int writing = 0);
|
static int select1(int fd, int secs, int writing = 0);
|
||||||
|
|
||||||
/// The selectloop interface is used to implement parallel servers.
|
protected:
|
||||||
/// All the interface is static (independant of any given object).
|
char *m_peer; // Name of the connected host
|
||||||
|
int m_fd;
|
||||||
|
bool m_ownfd;
|
||||||
|
int m_didtimo;
|
||||||
|
// Used when part of the selectloop map.
|
||||||
|
short m_wantedEvents;
|
||||||
|
SelectLoop *m_loop;
|
||||||
|
// Method called by the selectloop when something can be done with a netcon
|
||||||
|
virtual int cando(Netcon::Event reason) = 0;
|
||||||
|
// Called when added to loop
|
||||||
|
virtual void setloop(SelectLoop *loop) {m_loop = loop;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// The selectloop interface is used to implement parallel servers.
|
||||||
|
// The select loop mechanism allows several netcons to be used for io
|
||||||
|
// in a program without blocking as long as there is data to be read
|
||||||
|
// or written. In a multithread program which is also using select, it
|
||||||
|
// would typically make sense to have one SelectLoop active per
|
||||||
|
// thread.
|
||||||
|
class SelectLoop {
|
||||||
|
public:
|
||||||
|
SelectLoop()
|
||||||
|
: m_selectloopDoReturn(false), m_selectloopReturnValue(0),
|
||||||
|
m_placetostart(0),
|
||||||
|
m_periodichandler(0), m_periodicparam(0), m_periodicmillis(0)
|
||||||
|
{}
|
||||||
|
|
||||||
/// Loop waiting for events on the connections and call the
|
/// Loop waiting for events on the connections and call the
|
||||||
/// cando() method on the object when something happens (this will in
|
/// cando() method on the object when something happens (this will in
|
||||||
@ -88,20 +123,20 @@ public:
|
|||||||
/// call the periodic handler (if set) at regular intervals.
|
/// call the periodic handler (if set) at regular intervals.
|
||||||
/// @return -1 for error. 0 if no descriptors left for i/o. 1 for periodic
|
/// @return -1 for error. 0 if no descriptors left for i/o. 1 for periodic
|
||||||
/// timeout (should call back in after processing)
|
/// timeout (should call back in after processing)
|
||||||
static int selectloop();
|
int doLoop();
|
||||||
|
|
||||||
/// Call from data handler: make selectloop return the param value
|
/// Call from data handler: make selectloop return the param value
|
||||||
static void selectloopReturn(int value)
|
void loopReturn(int value)
|
||||||
{
|
{
|
||||||
o_selectloopDoReturn = true;
|
m_selectloopDoReturn = true;
|
||||||
o_selectloopReturnValue = value;
|
m_selectloopReturnValue = value;
|
||||||
}
|
}
|
||||||
/// Add a connection to be monitored (this will usually be called
|
/// Add a connection to be monitored (this will usually be called
|
||||||
/// from the server's listen connection's accept callback)
|
/// from the server's listen connection's accept callback)
|
||||||
static int addselcon(NetconP con, int);
|
int addselcon(NetconP con, int events);
|
||||||
/// Remove a connection from the monitored set. Note that this is
|
/// Remove a connection from the monitored set. This is
|
||||||
/// automatically called from the Netcon destructor, and when EOF is
|
/// automatically called when EOF is detected on a connection.
|
||||||
/// detected on a connection.
|
int remselcon(NetconP con);
|
||||||
static int remselcon(NetconP con);
|
|
||||||
|
|
||||||
/// Set a function to be called periodically, or a time before return.
|
/// Set a function to be called periodically, or a time before return.
|
||||||
/// @param handler the function to be called.
|
/// @param handler the function to be called.
|
||||||
@ -112,35 +147,45 @@ public:
|
|||||||
/// @param clp client data to be passed to handler at every call.
|
/// @param clp client data to be passed to handler at every call.
|
||||||
/// @param ms milliseconds interval between handler calls or
|
/// @param ms milliseconds interval between handler calls or
|
||||||
/// before return. Set to 0 for no periodic handler.
|
/// before return. Set to 0 for no periodic handler.
|
||||||
static void setperiodichandler(int (*handler)(void *), void *clp, int ms);
|
void setperiodichandler(int (*handler)(void *), void *clp, int ms);
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
static bool o_selectloopDoReturn;
|
// Set by client callback to tell selectloop to return.
|
||||||
static int o_selectloopReturnValue;
|
bool m_selectloopDoReturn;
|
||||||
char *m_peer; // Name of the connected host
|
int m_selectloopReturnValue;
|
||||||
int m_fd;
|
int m_placetostart;
|
||||||
bool m_ownfd;
|
|
||||||
int m_didtimo;
|
// Map of NetconP indexed by fd
|
||||||
// Used when part of the selectloop map.
|
map<int, NetconP> m_polldata;
|
||||||
short m_wantedEvents;
|
|
||||||
// Method called by the selectloop when something can be done with a netcon
|
// The last time we did the periodic thing. Initialized by setperiodic()
|
||||||
virtual int cando(Netcon::Event reason) = 0;
|
struct timeval m_lasthdlcall;
|
||||||
|
// The call back function and its parameter
|
||||||
|
int (*m_periodichandler)(void *);
|
||||||
|
void *m_periodicparam;
|
||||||
|
// The periodic interval
|
||||||
|
int m_periodicmillis;
|
||||||
|
void periodictimeout(struct timeval *tv);
|
||||||
|
int maybecallperiodic();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
class NetconData;
|
class NetconData;
|
||||||
|
|
||||||
/// Class for the application callback routine (when in
|
/// Class for the application callback routine (when in selectloop).
|
||||||
/// selectloop). It would be nicer to override cando() in a subclass
|
///
|
||||||
/// instead of setting a callback, but this can't be done conveniently
|
/// This is set by the app on the NetconData by calling
|
||||||
/// because accept() always creates a base NetconData (another way
|
/// setcallback(). It is then called from the NetconData's cando()
|
||||||
/// would be to pass a factory function function to the listener, to create
|
/// routine, itself called by selectloop.
|
||||||
/// NetconData derivatives).
|
///
|
||||||
|
/// It would be nicer to override cando() in a subclass instead of
|
||||||
|
/// setting a callback, but this can't be done conveniently because
|
||||||
|
/// accept() always creates a base NetconData (another approach would
|
||||||
|
/// be to pass a factory function to the listener, to create
|
||||||
|
/// NetconData derived classes).
|
||||||
class NetconWorker {
|
class NetconWorker {
|
||||||
public:
|
public:
|
||||||
virtual ~NetconWorker() {}
|
virtual ~NetconWorker() {}
|
||||||
// NetconP holds a NetconData oeuf corse
|
|
||||||
virtual int data(NetconData *con, Netcon::Event reason) = 0;
|
virtual int data(NetconData *con, Netcon::Event reason) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -185,7 +230,7 @@ private:
|
|||||||
int m_bufbytes; // Bytes of data.
|
int m_bufbytes; // Bytes of data.
|
||||||
int m_bufsize; // Total buffer size
|
int m_bufsize; // Total buffer size
|
||||||
RefCntr<NetconWorker> m_user;
|
RefCntr<NetconWorker> m_user;
|
||||||
virtual int cando(Netcon::Event reason);
|
virtual int cando(Netcon::Event reason); // Selectloop slot
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Network endpoint, client side.
|
/// Network endpoint, client side.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user