void VmDnsUnlockWrite( PVMDNS_RWLOCK pLock ) { int* pWriteLockCount = VmDnsGetLockKey(&pLock->writeKey); if (!pWriteLockCount) { VMDNS_LOG_ERROR("Out of memory, can't decrement lock count."); } else { if (*pWriteLockCount ==1) { pthread_rwlock_unlock(&pLock->rwLock); VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[UNLOCK WRITE] result write count is %u.\n", *pWriteLockCount); } if (*pWriteLockCount > 0) { (*pWriteLockCount)--; VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[--WRITE %u]\n", *pWriteLockCount); } else { VmDnsLog(VMDNS_LOG_LEVEL_ERROR, "Unexpected unlock write, write count is %u.\n", *pWriteLockCount); } } }
static DWORD VmDnsForwarderMetricsDelete( PVMDNS_FORWARDER_ENTRY pForwarderEntry ) { DWORD dwError = 0; BAIL_ON_VMDNS_ERROR(dwError); /* dwError = VmMetricsHistogramDelete( gVmDnsMetricsContext, pForwarderEntry->ForwarderMetricsContext.pQueryDuration); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmMetricsHistogramDelete( gVmDnsMetricsContext, pForwarderEntry->ForwarderMetricsContext.pUpdateDuration); BAIL_ON_VMDNS_ERROR(dwError); */ cleanup: return dwError; error: VmDnsLog(VMDNS_LOG_LEVEL_ERROR, "%s failed, error (%d)", __FUNCTION__, dwError); goto cleanup; }
int VmDnsTryLockRead( PVMDNS_RWLOCK pLock ) { int result = ERROR_BUSY; int* pWriteLockCount = VmDnsGetLockKey(&pLock->writeKey); int* pReadLockCount = VmDnsGetLockKey(&pLock->readKey); if (pWriteLockCount && pReadLockCount) { if (*pWriteLockCount > 0) { // Simply increment a read count but don't lock for read // as that would cause undefined behavior. result = 0; VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "Lock read when already holding %u write lock.", *pWriteLockCount); } else { if (*pReadLockCount == 0) { result = pthread_rwlock_tryrdlock(&pLock->rwLock); if (!result) { VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "Locked for read. Result read count: %u\n", *pReadLockCount + 1); } } else { result = 0; } } if (!result) { (*pReadLockCount)++; VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[++READ %u]\n", *pReadLockCount); } } return result; }
DWORD VmDnsCacheRemoveZoneProc( PVOID pData, PCSTR pszZone ) { PVMDNS_CACHE_CONTEXT pCacheContext = (PVMDNS_CACHE_CONTEXT) pData; PVMDNS_ZONE_OBJECT pZoneObject = NULL; DWORD dwError = 0; dwError = VmDnsCacheFindZone(pCacheContext, pszZone, &pZoneObject); BAIL_ON_VMDNS_ERROR_IF(dwError && dwError != ERROR_NOT_FOUND); if (dwError == ERROR_NOT_FOUND) { //already deleted (probably same node) VmDnsLog( VMDNS_LOG_LEVEL_DEBUG, "Zone (%s) already deleted from cache", pszZone ); dwError = 0; } else { VmDnsLog( VMDNS_LOG_LEVEL_DEBUG, "Removing Zone (%s) From Cache", pszZone ); dwError = VmDnsCacheRemoveZone(pCacheContext, pZoneObject); BAIL_ON_VMDNS_ERROR(dwError); } cleanup: VmDnsZoneObjectRelease(pZoneObject); return dwError; error: goto cleanup; }
int VmDnsTryLockWrite( PVMDNS_RWLOCK pLock ) { int result = ERROR_BUSY; int* pWriteLockCount = VmDnsGetLockKey(&pLock->writeKey); int* pReadLockCount = VmDnsGetLockKey(&pLock->readKey); if (pWriteLockCount && pReadLockCount) { if (*pReadLockCount > 0) { VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "Cannot wrlock with %u existing rdlock from same thread.\n", *pReadLockCount); result = ERROR_POSSIBLE_DEADLOCK; } else { if (*pWriteLockCount <= 0) { result = pthread_rwlock_trywrlock(&pLock->rwLock); if (result) { VmDnsLog(VMDNS_LOG_LEVEL_ERROR, "trywrlock returned %u\n", result); } } else { result = 0; } if (!result) { (*pWriteLockCount)++; VmDnsLog(VMDNS_LOG_LEVEL_ERROR, "[++WRITE %u]\n", *pWriteLockCount); } } } return result; }
void VmDnsLockWrite( PVMDNS_RWLOCK pLock ) { int* pWriteLockCount = VmDnsGetLockKey(&pLock->writeKey); if (!pWriteLockCount) { VMDNS_LOG_WARNING("Out of memory, try plain locking."); pthread_rwlock_wrlock(&pLock->rwLock); } else { if (*pWriteLockCount == 0) { pthread_rwlock_wrlock(&pLock->rwLock); VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[LOCK WRITE]"); } (*pWriteLockCount)++; VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[++WRITE %u]\n", *pWriteLockCount); } }
void VmDnsUnlockRead( PVMDNS_RWLOCK pLock ) { int* pWriteLockCount = VmDnsGetLockKey(&pLock->writeKey); int* pReadLockCount = VmDnsGetLockKey(&pLock->readKey); if (!pWriteLockCount || !pReadLockCount) { VMDNS_LOG_ERROR("Out of memory, can't decrement lock count."); } else { if (*pWriteLockCount > 0) { VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "Read unlock while already holding write lock."); } else { if (*pReadLockCount ==1) { pthread_rwlock_unlock(&pLock->rwLock); VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[UNLOCK READ]"); } } if (*pReadLockCount > 0) { (*pReadLockCount)--; VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[--READ %u]\n", *pReadLockCount); } else { VmDnsLog(VMDNS_LOG_LEVEL_ERROR, "Unexpected read unlock."); } } }
void VmDnsLockRead( PVMDNS_RWLOCK pLock ) { int* pWriteLockCount = VmDnsGetLockKey(&pLock->writeKey); int* pReadLockCount = VmDnsGetLockKey(&pLock->readKey); if (!pWriteLockCount || !pReadLockCount) { VMDNS_LOG_WARNING("Out of memory, try plain locking."); pthread_rwlock_rdlock(&pLock->rwLock); } else { if (*pWriteLockCount > 0) { // Simply increment a read count but don't lock for read // as that would cause undefined behavior. VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "Lock read when already holding %u write lock.", *pWriteLockCount); } else { if (*pReadLockCount == 0) { pthread_rwlock_rdlock(&pLock->rwLock); VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "Actually locking for read. Result read count: %u\n", *pReadLockCount + 1); } } (*pReadLockCount)++; VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[++READ %u]\n", *pReadLockCount); } }
static DWORD VmDnsForwarderMetricsInit( PVMDNS_FORWARDER_ENTRY pForwarderEntry ) { DWORD dwError = 0; UINT64 buckets[] = {1, 10, 100, 300, 1000}; VM_METRICS_LABEL labelDurationOps[2][2] = {{{"operation","query"},{"forwarder",""}}, {{"operation","update"},{"forwarder",""}}}; labelDurationOps[0][1].pszValue = pForwarderEntry->pszForwarder; labelDurationOps[1][1].pszValue = pForwarderEntry->pszForwarder; BAIL_ON_VMDNS_ERROR(dwError); dwError = VmMetricsHistogramNew( gVmDnsMetricsContext, "vmdns_forwarder_request_duration", labelDurationOps[0], 2, "Forwarder Process Request Duration", buckets, 5, &pForwarderEntry->ForwarderMetricsContext.pQueryDuration ); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmMetricsHistogramNew( gVmDnsMetricsContext, "vmdns_forwarder_request_duration", labelDurationOps[1], 2, "Forwarder Process Request Duration", buckets, 5, &pForwarderEntry->ForwarderMetricsContext.pUpdateDuration ); BAIL_ON_VMDNS_ERROR(dwError); cleanup: return dwError; error: VmDnsLog(VMDNS_LOG_LEVEL_ERROR, "%s failed, error (%d)", __FUNCTION__, dwError); goto cleanup; }
static DWORD VmDnsNotifyLikewiseServiceManager() { DWORD dwError = ERROR_SUCCESS; PCSTR pszSmNotify = NULL; int ret = 0; int notifyFd = -1; char notifyCode = 0; // interact with likewise service manager (start/stop control) if ((pszSmNotify = getenv("LIKEWISE_SM_NOTIFY")) != NULL) { notifyFd = atoi(pszSmNotify); do { ret = write(notifyFd, ¬ifyCode, sizeof(notifyCode)); } while (ret != sizeof(notifyCode) && errno == EINTR); if (ret < 0) { #define BUFFER_SIZE 1024 char buffer[BUFFER_SIZE]= {0}; int errorNumber = errno; VmDnsStringErrorA( buffer, BUFFER_SIZE, errorNumber ); VmDnsLog( VMDNS_LOG_LEVEL_DEBUG, "Could not notify service manager: %s (%i)", buffer, errorNumber); dwError = LwErrnoToWin32Error(errno); BAIL_ON_VMDNS_ERROR(dwError); #undef BUFFER_SIZE } } error: if(notifyFd != -1) { close(notifyFd); } return dwError; }
DWORD VmDnsCacheEvictEntryProc( PVMDNS_NAME_ENTRY pNameEntry, PVMDNS_ZONE_OBJECT pZoneObject ) { //assumes locks for cache and hashmap are already held DWORD dwError = 0; //Remove if not SOA if (VmDnsStringCompareA( pZoneObject->pszName, pNameEntry->pszName, FALSE ) != 0) { dwError = VmDnsZoneRemoveNameEntry( pZoneObject, pNameEntry ); BAIL_ON_VMDNS_ERROR(dwError); VmDnsLog( VMDNS_LOG_LEVEL_DEBUG, "Purged (%s) from Zone (%s) Cache", pNameEntry->pszName, pZoneObject->pszName ); } else { dwError = ERROR_INVALID_PARAMETER; } cleanup: return dwError; error: goto cleanup; }
int main( int argc, char * argv[]) { DWORD dwError = 0; int logLevel = VMDNS_LOG_LEVEL_INFO; PCSTR pszLogFile = NULL; BOOLEAN bEnableSysLog = FALSE; //dwError = VmDnsSrvUpdateConfig(); //BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsParseArgs( argc, argv, &logLevel, &pszLogFile, &gVmdnsGlobals.iListenPort, &bEnableSysLog, NULL); if(dwError != ERROR_SUCCESS) { ShowUsage( argv[0] ); BAIL_ON_VMDNS_ERROR(dwError); } vmdns_syslog_level = logLevel; if( bEnableSysLog != FALSE ) { vmdns_syslog = 1; } if (pszLogFile) { dwError = VmDnsAllocateStringA( pszLogFile, &gVmdnsGlobals.pszLogFile); BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsConfigGetDword(VMDNS_KEY_VALUE_LOG_CAP, &gVmdnsGlobals.dwMaximumOldFiles); if (dwError) { gVmdnsGlobals.dwMaximumOldFiles = VMDNS_DEFAULT_LOG_CAP; } dwError = VmDnsConfigGetDword(VMDNS_KEY_VALUE_LOG_SIZE, &gVmdnsGlobals.dwMaxLogSizeBytes); if (dwError) { gVmdnsGlobals.dwMaxLogSizeBytes = VMDNS_DEFAULT_LOG_SIZE; } dwError = VmDnsLogInitialize(gVmdnsGlobals.pszLogFile, gVmdnsGlobals.dwMaximumOldFiles, gVmdnsGlobals.dwMaxLogSizeBytes); BAIL_ON_VMDNS_ERROR(dwError); VmDnsLog(VMDNS_LOG_LEVEL_INFO, "Vmdnsd: start" ); VmDnsBlockSelectedSignals(); dwError = VmDnsInit(); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsNotifyLikewiseServiceManager(); BAIL_ON_VMDNS_ERROR(dwError); VmDnsdStateSet(VMDNSD_RUNNING); // main thread waits on signals dwError = VmDnsHandleSignals(); BAIL_ON_VMDNS_ERROR(dwError); VmDnsLog( VMDNS_LOG_LEVEL_INFO, "Vmdnsd exiting..." ); cleanup: VmDnsdStateSet(VMDNS_SHUTDOWN); VmDnsShutdown(); VmDnsLog( VMDNS_LOG_LEVEL_INFO, "Vmdnsd: stop" ); VmDnsLogTerminate(); return dwError; error: goto cleanup; }
DWORD VmDnsCacheSyncZoneProc( PVOID pData, PCSTR pszZone ) { PVMDNS_CACHE_CONTEXT pCacheContext = (PVMDNS_CACHE_CONTEXT) pData; PVMDNS_ZONE_OBJECT pZoneObject = NULL; DWORD dwError = 0; DWORD dwForwarderCount = 0; PSTR* ppszForwarders = NULL; dwError = VmDnsCacheFindZone( pCacheContext, pszZone, &pZoneObject ); BAIL_ON_VMDNS_ERROR_IF(dwError && dwError != ERROR_NOT_FOUND); if (dwError == ERROR_NOT_FOUND) { dwError = VmDnsCacheLoadZoneFromStore(pCacheContext, pszZone); BAIL_ON_VMDNS_ERROR(dwError); VmDnsLog( VMDNS_LOG_LEVEL_DEBUG, "Added Zone %s to Cache", pszZone ); } else if (pZoneObject && pZoneObject->zoneId == VMDNS_ZONE_ID_FORWARDER) { dwError = VmDnsStoreGetForwarders( pszZone, &dwForwarderCount, &ppszForwarders); BAIL_ON_VMDNS_ERROR_IF(dwError && dwError != ERROR_NO_DATA); dwError = 0; if (dwForwarderCount > 0 && *ppszForwarders) { dwError = VmDnsSetForwarders( pZoneObject->pForwarderContext, pszZone, dwForwarderCount, ppszForwarders); BAIL_ON_VMDNS_ERROR(dwError); VmDnsFreeStringCountedArrayA(ppszForwarders, dwForwarderCount); ppszForwarders = NULL; dwForwarderCount = 0; } } cleanup: VmDnsZoneObjectRelease(pZoneObject); if (ppszForwarders) { VmDnsFreeStringCountedArrayA(ppszForwarders, dwForwarderCount); } return dwError; error: goto cleanup; }
DWORD VmDnsCachePurgeRecord( PVMDNS_ZONE_OBJECT pZoneObject, PCSTR pszRecord, DWORD dwCachePurgeEvent ) { PVMDNS_RECORD_LIST pList = NULL; DWORD dwError = 0; if (VmDnsStringCompareA(pZoneObject->pszName, pszRecord, FALSE) == 0) { //update SOA record dwError = VmDnsStoreGetRecords( pZoneObject->pszName, pZoneObject->pszName, &pList ); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsZoneUpdateRecords( pZoneObject, pZoneObject->pszName, pList ); BAIL_ON_VMDNS_ERROR(dwError); VmDnsLog( VMDNS_LOG_LEVEL_DEBUG, "Refreshed (%s) in Cache", pZoneObject->pszName ); } else { dwError = VmDnsZonePurgeRecords(pZoneObject, pszRecord); BAIL_ON_VMDNS_ERROR_IF(dwError && dwError != ERROR_NOT_FOUND) if (dwError == ERROR_NOT_FOUND) { VmDnsLog( VMDNS_LOG_LEVEL_DEBUG, "Record (%s) not found in Cache", pszRecord ); dwError = 0; } else { if (dwCachePurgeEvent == CACHE_PURGE_MODIFICATION) { VmMetricsCounterIncrement(gVmDnsCounterMetrics[CACHE_MODIFY_PURGE_COUNT]); } else if (dwCachePurgeEvent == CACHE_PURGE_REPLICATION) { VmMetricsCounterIncrement(gVmDnsCounterMetrics[CACHE_NOTIFY_PURGE_COUNT]); } VmDnsLog( VMDNS_LOG_LEVEL_DEBUG, "Succesfully Purged (%s) from Cache", pszRecord ); } } cleanup: if (pList) { VmDnsRecordListRelease(pList); } return dwError; error: goto cleanup; }