27 #include <sys/types.h>
28 #include <netinet/in.h>
33 # include <sys/stat.h>
35 # include <arpa/nameser.h>
41 #include <tqapplication.h>
43 #include <tqcstring.h>
44 #include <tqptrlist.h>
48 #include <tqwaitcondition.h>
49 #include <tqsemaphore.h>
53 #include "kresolver.h"
54 #include "kresolver_p.h"
55 #include "kresolverworkerbase.h"
62 void initStandardWorkers();
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
251 static const int maxThreadWaitTime = 2000;
252 static const int maxThreads = 5;
256 KResolverThread::KResolverThread()
262 void 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);
298 bool KResolverThread::checkResolver()
300 return resInit.shouldResInit();
303 void KResolverThread::acquireResolver()
305 #if defined(NEED_MUTEX) && !defined(Q_OS_FREEBSD)
306 getXXbyYYmutex.lock();
312 void KResolverThread::releaseResolver()
314 #if defined(NEED_MUTEX) && !defined(Q_OS_FREEBSD)
315 getXXbyYYmutex.unlock();
321 static KResolverManager *globalManager;
323 KResolverManager* KResolverManager::manager()
325 if (globalManager == 0L)
326 new KResolverManager();
327 return globalManager;
330 KResolverManager::KResolverManager()
331 : runningThreads(0), availableThreads(0)
333 globalManager =
this;
334 workers.setAutoDelete(
true);
335 currentRequests.setAutoDelete(
true);
337 initStandardWorkers();
342 KResolverManager::~KResolverManager()
347 for (workers.first(); workers.current(); workers.next())
348 workers.current()->terminate();
351 void KResolverManager::registerThread(KResolverThread* )
355 void KResolverManager::unregisterThread(KResolverThread*)
361 RequestData* KResolverManager::requestData(KResolverThread *th,
int maxWaitTime)
369 TQMutexLocker locker(&mutex);
370 RequestData *data = findData(th);
378 feedWorkers.wait(&mutex, maxWaitTime);
385 RequestData* 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());
412 void KResolverManager::releaseData(KResolverThread *, RequestData* data)
423 data->obj->status = KResolver::PostProcessing;
426 data->worker->m_finished =
true;
427 data->worker->th = 0L;
434 void 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())
478 bool KResolverManager::handleFinishedItem(RequestData* curr)
484 if (curr->worker->m_finished && curr->nRequests == 0)
488 curr->obj->status = KResolver::PostProcessing;
491 --curr->requestor->nRequests;
502 void KResolverManager::registerNewWorker(KResolverWorkerFactoryBase *factory)
504 workerFactories.append(factory);
507 KResolverWorkerBase* 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;
549 void 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();
648 void 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);
690 void 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())
761 bool 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();
818 void KResolverManager::dequeue(
KResolver *obj)
820 TQMutexLocker locker(&mutex);
Name and service resolution class.
Name and service resolution results.
A namespace to store all networking-related (socket) classes.
int systemError() const
Retrieves the system error code, if any.
TDEAction * redo(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
void setAddress(const TQString &host, const TQString &service)
Sets the new nodename and service name.
void setError(int errorcode, int systemerror=0)
Sets the error codes.
kndbgstream & endl(kndbgstream &s)
Does nothing.
int error() const
Retrieves the error code associated with this resolution.