28#include <netinet/in.h>
35# include <arpa/nameser.h>
41#include <tqapplication.h>
48#include <tqwaitcondition.h>
49#include <tqsemaphore.h>
54#include "kresolver_p.h"
55#include "kresolverworkerbase.h"
62 void initStandardWorkers();
67using namespace KNetwork::Internal;
136# ifndef RES_INIT_THREADSAFE
137 TQWaitCondition cond;
145 if (KDE_stat(
"/etc/resolv.conf", &st) != 0)
148 if (mTime != st.st_mtime)
150 kdDebug(179) <<
"shouldResInit: /etc/resolv.conf updated" <<
endl;
162 kdDebug(179) <<
"callResInit: calling res_init()" <<
endl;
167 if (KDE_stat(
"/etc/resolv.conf", &st) == 0)
172 : mTime(0), useCount(0)
180# ifndef RES_INIT_THREADSAFE
181 TQMutexLocker locker(&mutex);
200# ifndef RES_INIT_THREADSAFE
251static const int maxThreadWaitTime = 2000;
252static const int maxThreads = 5;
256KResolverThread::KResolverThread()
262void KResolverThread::run()
268 KResolverManager::manager()->registerThread(
this);
271 data = KResolverManager::manager()->requestData(
this, ::maxThreadWaitTime);
286 KResolverManager::manager()->releaseData(
this, data);
294 KResolverManager::manager()->unregisterThread(
this);
298bool KResolverThread::checkResolver()
300 return resInit.shouldResInit();
303void KResolverThread::acquireResolver()
305#if defined(NEED_MUTEX) && !defined(Q_OS_FREEBSD)
306 getXXbyYYmutex.lock();
312void KResolverThread::releaseResolver()
314#if defined(NEED_MUTEX) && !defined(Q_OS_FREEBSD)
315 getXXbyYYmutex.unlock();
321static KResolverManager *globalManager;
323KResolverManager* KResolverManager::manager()
325 if (globalManager == 0L)
326 new KResolverManager();
327 return globalManager;
330KResolverManager::KResolverManager()
331 : runningThreads(0), availableThreads(0)
333 globalManager =
this;
334 workers.setAutoDelete(
true);
335 currentRequests.setAutoDelete(
true);
337 initStandardWorkers();
342KResolverManager::~KResolverManager()
347 for (workers.first(); workers.current(); workers.next())
348 workers.current()->terminate();
351void KResolverManager::registerThread(KResolverThread* )
355void KResolverManager::unregisterThread(KResolverThread*)
361RequestData* KResolverManager::requestData(KResolverThread *th,
int maxWaitTime)
369 TQMutexLocker locker(&mutex);
370 RequestData *data = findData(th);
378 feedWorkers.wait(&mutex, maxWaitTime);
385RequestData* KResolverManager::findData(KResolverThread* th)
393 for (RequestData *curr = newRequests.first(); curr; curr = newRequests.next())
394 if (!curr->worker->m_finished)
398 curr->obj->status = KResolver::InProgress;
399 curr->worker->th = th;
402 currentRequests.append(newRequests.take());
412void KResolverManager::releaseData(KResolverThread *, RequestData* data)
423 data->obj->status = KResolver::PostProcessing;
426 data->worker->m_finished =
true;
427 data->worker->th = 0L;
434void KResolverManager::handleFinished()
437 TQPtrQueue<RequestData> doneRequests;
444 RequestData *curr = currentRequests.last();
447 if (curr->worker->th == 0L)
449 if (handleFinishedItem(curr))
451 doneRequests.enqueue(currentRequests.take());
452 if (curr->requestor &&
453 curr->requestor->nRequests == 0 &&
454 curr->requestor->worker->m_finished)
460 curr = currentRequests.prev();
464 while (RequestData *d = doneRequests.dequeue())
478bool KResolverManager::handleFinishedItem(RequestData* curr)
484 if (curr->worker->m_finished && curr->nRequests == 0)
488 curr->obj->status = KResolver::PostProcessing;
491 --curr->requestor->nRequests;
502void KResolverManager::registerNewWorker(KResolverWorkerFactoryBase *factory)
504 workerFactories.append(factory);
507KResolverWorkerBase* KResolverManager::findWorker(KResolverPrivate* p)
522 KResolverWorkerBase *worker;
523 for (KResolverWorkerFactoryBase *factory = workerFactories.first(); factory;
524 factory = workerFactories.next())
526 worker = factory->create();
529 worker->input = &p->input;
531 if (worker->preprocess())
534 if (worker->m_finished)
535 p->status = KResolver::PostProcessing;
537 p->status = KResolver::Queued;
549void KResolverManager::doNotifying(RequestData *p)
580 p->obj->mutex.lock();
584 if (p->obj->status == KResolver::Canceled)
586 p->obj->status = KResolver::Canceled;
587 p->obj->errorcode = KResolver::Canceled;
588 p->obj->syserror = 0;
594 p->worker->postprocess();
598 r = p->worker->results;
601 r.
setAddress(p->input->node, p->input->service);
606 p->obj->errorcode = r.
error();
608 p->obj->status = !r.isEmpty() ?
609 KResolver::Success : KResolver::Failed;
614 r.
setError(p->obj->errorcode, p->obj->syserror);
618 if (!p->obj->waiting && parent)
622 TQApplication::postEvent(parent,
new TQEvent((TQEvent::Type)(ResolutionCompleted)));
625 p->obj->mutex.unlock();
631 p->worker->postprocess();
642 notifyWaiters.wakeAll();
648void KResolverManager::enqueue(
KResolver *obj, RequestData *requestor)
650 RequestData *newrequest =
new RequestData;
651 newrequest->nRequests = 0;
652 newrequest->obj = obj->d;
653 newrequest->input = &obj->d->input;
654 newrequest->requestor = requestor;
658 if ((newrequest->worker = findWorker(obj->d)) == 0L)
662 obj->d->status = KResolver::Failed;
663 obj->d->errorcode = KResolver::UnsupportedFamily;
664 obj->d->syserror = 0;
666 doNotifying(newrequest);
673 requestor->nRequests++;
675 if (!newrequest->worker->m_finished)
676 dispatch(newrequest);
677 else if (newrequest->nRequests > 0)
680 currentRequests.append(newrequest);
685 doNotifying(newrequest);
690void KResolverManager::dispatch(RequestData *data)
696 TQMutexLocker locker(&mutex);
699 newRequests.append(data);
727 if (availableThreads == 0 && runningThreads < maxThreads)
732 KResolverThread *th = workers.first();
733 while (th && th->running())
738 th =
new KResolverThread;
747 feedWorkers.wakeAll();
751 while (workers.current())
753 if (!workers.current()->running())
761bool KResolverManager::dequeueNew(
KResolver* obj)
767 KResolverPrivate *d = obj->d;
770 RequestData *curr = newRequests.first();
776 d->status = KResolver::Canceled;
777 d->errorcode = KResolver::Canceled;
787 curr = newRequests.next();
790 curr = currentRequests.first();
798 d->status = KResolver::Canceled;
799 d->errorcode = KResolver::Canceled;
806 curr->worker->input = 0L;
811 curr = currentRequests.next();
818void KResolverManager::dequeue(
KResolver *obj)
820 TQMutexLocker locker(&mutex);
Name and service resolution results.
void setAddress(const TQString &host, const TQString &service)
Sets the new nodename and service name.
int systemError() const
Retrieves the system error code, if any.
int error() const
Retrieves the error code associated with this resolution.
void setError(int errorcode, int systemerror=0)
Sets the error codes.
Name and service resolution class.
kndbgstream & endl(kndbgstream &s)
Does nothing.
A namespace to store all networking-related (socket) classes.
TDEAction * redo(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)