Toggle Menu Visibility











Objectives

Host against which tests are to be executed will (in most cases) be given in configuration as human-readable domain names. Hereafter every test will need to resolve the host address using gethostbyname (or the reentrant version gethostbyname_r) C library function. The first reason for caching results from its execution is speed concern. Resolving the domain name every time a test is executed will lead to kernel overhead, which could possibly slow down other tasks (the watchcub itself). Secondly, failure to resolve the domain name should not lead to failure of the whole test.

 

Theory of Operation

The dns cache will provide some Resolve method, which will be a wrapper of the gethostbyname_r libc function. It will maintain a table where for every DomainNameHostAddress and ExpirationTimestamp will be written. When some plugin calls Resolve for some DomainName, the HostAddress (or 0 if not found) will be returned and after that in case the ExpirationTimestamp is already passed (< current timestamp) the DomainName will be enqued for resolving in some ResolveQueue. Meanwhile NUMBER_OF_RESOLVER_THREADS threads will wait for something to enter the queue. When this happens, one of them gets it out and resolves the IP, and in case resolving was successful one, updates the record in the cache table.

 

 

The Basic Algorithm

 

PROCEDURE ResolveDomainName )

 

# check if someone didn't pass an IP address for resolving

IF IS_IP( DomainName ) THEN

RETURN STR_TO_IP( DomainName )

END IF

 

# get what's inside the cache table

(HostAddress, ExpirationTimestamp) = TABLE_LOOKUP( DNSCacheTable, DomainName )

 

# check if this entry should be Refreshed

IF ExpirationTimestamp < NOW() OR HostAddress = 0 THEN

# the HostAddress for this DomainName should be refreshed

LOCK( ResolveQueue )

ENQUEUE( ResolveQueue, DomainName )

UNLOCK( ResolveQueue )

END IF

 

RETURN HostAddress

 

END PROCEDURE

 

 

PROCEDURE ResolverThreadRoutine()

 

# spin an endless loop

WHILE ( TRUE )

SLEEP( CHECK_INTERVAL )

 

# check in the ResolveQueue and while there is something for resolving -- do resolve it

WHILE ( TRUE )

DomainName := NIL

LOCK( ResolveQueue )

IF NON_EMPTY( ResolveQueue ) THEN

DomainName := POP_FIRST( ResolveQueue )

END IF

UNLOCK( ResolveQueue )

 

IF NOT DomainName THEN

BREAK

END IF

 

(HostAddress, StatusCode) := gethostbyname_r( DomainName )

IF StatusCode = HOST_FOUND THEN

DNSCacheTable[DomainName] := ( HostAddress, NOW() + EXP_INTERVAL )

ELSE

DNSCacheTable[DomainName].ExpirationTimestamp += RETRY_INTERVAL

END IF

END WHILE

 

END WHILE

 

END PROCEDURE