/*****************************************************************************/ /* ProxyMaint.c See PROXYCACHE.C for commentary. This module implements both the ROUTINE and REACTIVE purge maintenance for the proxy file cache. See PROXYCACHE.C module for information on cache management strategy. Routine proxy maintenance can be initiated from the command line. /PROXY=PURGE=BACKGROUND[=ProxyCachePurgeList] /PROXY=PURGE=REACTIVE[=ProxyCachePurgeList] /PROXY=PURGE=ROUTINE[=ProxyCachePurgeList] /PROXY=CACHE=STATISTICS VERSION HISTORY --------------- 28-APR-2018 MGD refactor Admin..() AST delivery 18-JAN-2010 JPP bugfix; ProxyMaintInit() use v10orPrev10() for scan spec 19-AUG-2007 MGD use PercentOf() to avoid divide-by-zero exceptions 12-APR-2005 MGD ProxyMaintSupervisor() return if caching not enabled 04-SEP-2004 MGD PROXYCACHE.C v9.0.0 cache file header date/time usage 30-APR-2004 MGD use QIO to erase cache file (save a few cycles) 13-JAN-2004 MGD DECC 6.2 objected to '$DESCRIPTOR(name,ptr->string)' 11-JUN-2003 MGD bugfix; ProxyMaintDeviceStats() volume count (set) handling 11-MAY-2003 MGD proxy unknown request fields 29-APR-2003 MGD add proxy cache device error count statistics 02-APR-2003 MGD maintain 'ProxyXForwardedFor', modify for 'ProxyForwarded' 20-FEB-2003 MGD ProxytMaintSupervisor() used instead of timers, background purge (set with '[ProxyCacheRoutineHourOfDay] 24') 03-JUN-2002 MGD bugfix; ensure sys$search() RMS channel is released 15-MAY-2002 MGD proxy gateway statistics 11-APR-2002 MGD make a reactive purge initially more agressive, bugfix; switch return not break with next reactive scan 04-APR-2002 MGD add command-line and menu STOP to cache scans, update admin and monitor status string with scan progress, bugfix; command-line cache maintenance reporting 02-FEB-2002 MGD rework POSTed query due to request body processing changes 22-SEP-2001 MGD InstanceLock/UnLock() to control access to cache 04-AUG-2001 MGD support module WATCHing 07-MAY-2001 MGD monitor global section accounting changes 05-APR-2001 MGD add boolean to prevent ProxyMaintCacheLock() lock status block overwriting if multiple scans intiated from Admin Menu 20-DEC-2000 MGD routine proxy maintainence optionally disabled/external 13-SEP-2000 MGD ProxyMaintReport() call refined to optionally provide host name cache entries 08-JUL-2000 MGD add VMS locking around cache scan (for clusters) 04-MAR-2000 MGD use FaolToBuffer(), et.al. 03-JAN-2000 MGD no changes required for ODS-5 compliance ... it's not (see note in PROXYCACHE.C) 30-DEC-1999 MGD change $GETDVI() to $GETDVIW() (potential bugfix) 04-DEC-1999 MGD rework startup cache device and report details 22-OCT-1999 MGD inaccessable cache device non-fatal during startup 20-JUN-1999 MGD allow for cache devices >9GB in space calculations, some refinement to statistics report 19-AUG-1998 MGD initial development (recommenced DEC 1998) */ /*****************************************************************************/ #ifdef WASD_VMS_V7 #undef _VMS__V6__SOURCE #define _VMS__V6__SOURCE #undef __VMS_VER #define __VMS_VER 70000000 #undef __CRTL_VER #define __CRTL_VER 70000000 #endif /* standard C header files */ #include #include #include #include /* VMS related header files */ #include #include #include #include #include #include #include #include #include #include #include /* application-related header files */ #include "wasd.h" #define WASD_MODULE "PROXYMAINT" /******************/ /* global storage */ /******************/ char ErrorProxyMaintTooManyDevices [] = "Volume set has too many members."; BOOL ProxyMaintChangeToReactive, ProxyMaintStopScan; int ProxyMaintAllocBlocks, ProxyMaintBackgroundFileCount, ProxyMaintBackgroundInterval, ProxyMaintBackgroundPurgeCount, ProxyMaintDeletedAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintFileAllocBlocks, ProxyMaintFileCount, ProxyMaintFileUsedBlocks, ProxyMaintPurgeAtHour, ProxyMaintPurgeHoursIndex, ProxyMaintReactivePurgeCount, ProxyMaintResultFileNameLength, ProxyMaintRoutinePurgeCount, ProxyMaintRoutineHoursIndex, ProxyMaintScanFileSpecLength, ProxyMaintScanType, ProxyMaintStatScanCount, ProxyMaintTargetPercent; ProxyMaintUsedBlocks; unsigned long ProxyMaintScanStartTime64 [2]; char *ProxyMaintScanFileSpec; char ProxyMaintEraseFileName [256], ProxyMaintExpandedFileName [256], ProxyMaintStatusStringBckGrnd [128] = "none", ProxyMaintStatusStringReactive [196] = "none", ProxyMaintStatusStringRoutine [128] = "none", ProxyMaintStatusStringStatScan [128] = "none", ProxyMaintResultFileName [256]; struct FAB ProxyMaintSearchFab; struct NAM ProxyMaintSearchNam; PROXY_CACHE_FILE_QIO ProxyMaintCacheFileQio; /********************/ /* external storage */ /********************/ extern BOOL ProxyCacheEnabled, ProxyCacheFreeSpaceAvailable, ProxyReportLog, ProxyReportCacheLog, ProxyServingEnabled, ProxyUnknownRequestFields; extern int EfnWait, EfnNoWait, HttpdTickSecond, OpcomMessages, ProxyCacheDeviceCheckMinutes, ProxyCacheDeviceMaxPercent, ProxyCacheDevicePurgePercent, ProxyCacheDeviceTargetPercent, ProxyCacheFileKBytesMax, ProxyCacheNegativeSeconds, ProxyCacheNoReloadSeconds, ProxyCachePurgeList[], ProxyCachePurgeListCount, ProxyCacheRoutineHourOfDay, ProxyConnectPersistMax, ProxyConnectPersistSeconds, ProxyConnectTimeoutSeconds, ProxyForwardedBy, ProxyHostLookupRetryCount, ProxyNetConnectCount, ProxyVerifyRecordMax, ProxyXForwardedFor; extern int ProxyCacheReloadList[], ToLowerCase[], ToUpperCase[]; extern char CliProxyMaint[], ErrorSanityCheck[], ServerHostPort[]; extern char *ProxyCacheReloadListPtr, *ProxyCachePurgeListPtr; extern unsigned short HttpdNumTime[]; extern ACCOUNTING_STRUCT *AccountingPtr; extern CONFIG_STRUCT Config; extern MSG_STRUCT Msgs; extern PROXY_ACCOUNTING_STRUCT *ProxyAccountingPtr; extern PROXYVERIFY_GBLSEC *ProxyVerifyGblSecPtr; extern WATCH_STRUCT Watch; /****************************************************************************/ /* Initialize maintainence values. */ ProxyMaintInit () { int status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintInit()"); ProxyMaintScanFileSpec = v10orPrev10(PROXY_CACHE_SPEC,-1); ProxyMaintScanFileSpecLength = strlen(ProxyMaintScanFileSpec); ProxyCacheFreeSpaceAvailable = ProxyMaintDeviceFreeSpace (ProxyCacheDeviceMaxPercent); InstanceMutexLock (INSTANCE_MUTEX_HTTPD); ProxyAccountingPtr->FreeSpaceAvailable = ProxyCacheFreeSpaceAvailable; if (!ProxyAccountingPtr->StatusString[0] || strstr (ProxyAccountingPtr->StatusString, "in-progress")) strcpy (ProxyAccountingPtr->StatusString, "(none)"); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); /* if space available schedule a purge, else if exceeded begin a purge */ if (ProxyCacheFreeSpaceAvailable) ProxyMaintPrintDeviceStats (true); else ProxyMaintScanBegin (PROXY_MAINT_SCAN_REACTIVE); /* disable if not sensible */ if (ProxyCacheRoutineHourOfDay < 0) ProxyCacheRoutineHourOfDay = -1; if (ProxyCacheRoutineHourOfDay > 24) ProxyCacheRoutineHourOfDay = -1; if (ProxyCacheRoutineHourOfDay == 24) FaoToStdout ("%HTTPD-I-PROXYMAINT, background purge active\n"); else if (ProxyCacheRoutineHourOfDay < 0) FaoToStdout ("%HTTPD-I-PROXYMAINT, routine purge disabled\n"); } /****************************************************************************/ /* Initiate some proxy maintainance from the command line. */ ProxyMaintCli () { BOOL ScanBackground, ScanRoutine, ScanReactive, ScanStatistics; int ScanType; char *cptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintCli()"); ScanRoutine = ScanReactive = ScanStatistics = false; if ((ScanBackground = strsame (CliProxyMaint, "PURGE=BACKGROUND", 16)) || (ScanRoutine = strsame (CliProxyMaint, "PURGE=ROUTINE", 13)) || (ScanReactive = strsame (CliProxyMaint, "PURGE=REACTIVE", 14)) || (ScanStatistics = strsame (CliProxyMaint, "CACHE=STATISTICS", 16))) { /* read the server configuration file (for OPCOM & proxy settings) */ ConfigLoad (&Config); /* now configure up the proxy settings (disabled is OK here) */ ProxyCacheInit (false); /* we'll assume it's always enabled */ ProxyCacheEnabled = true; /* for CLI maintainance we always want messages on SYS$OUTPUT */ ProxyReportLog = true; if (ScanBackground) { /* override the configuration purge list if CLI one provided */ if (CliProxyMaint[16] == '=') ProxyCachePurgeListPtr = CliProxyMaint + 16; ScanType = PROXY_MAINT_SCAN_BCKGRND; } else if (ScanRoutine) { /* override the configuration purge list if CLI one provided */ if (CliProxyMaint[13] == '=') ProxyCachePurgeListPtr = CliProxyMaint + 14; ScanType = PROXY_MAINT_SCAN_ROUTINE; } else if (ScanReactive) { /* override the configuration purge list if CLI one provided */ if (CliProxyMaint[14] == '=') { cptr = ProxyCachePurgeListPtr = CliProxyMaint + 15; while (*cptr && *cptr != '%') cptr++; if (*cptr && cptr > ProxyCachePurgeListPtr) { ProxyCacheDeviceTargetPercent = atoi(ProxyCachePurgeListPtr); if (ProxyCacheDeviceTargetPercent <= 0 || ProxyCacheDeviceTargetPercent >= 100) { FaoToStdout ("%HTTPD-I-PROXYMAINT, device percentage problem\n"); exit (STS$K_ERROR | STS$M_INHIB_MSG); } while (*cptr && !isdigit(*cptr)) cptr++; ProxyCachePurgeListPtr = cptr; } } ScanType = PROXY_MAINT_SCAN_REACTIVE; } else if (ScanStatistics) { ProxyCachePurgeListPtr = NULL; ScanType = PROXY_MAINT_SCAN_STATISTICS; } if (ProxyCachePurgeListPtr) { ProxyCacheInitPurgeList (); if (ProxyCachePurgeListPtr[0] == '*') { FaoToStdout ("%HTTPD-I-PROXYMAINT, purge list problem\n"); exit (STS$K_ERROR | STS$M_INHIB_MSG); } } /* if the scan starts OK then hibernate waiting for it to finish */ if (VMSok (ProxyMaintScanBegin (ScanType))) sys$hiber (); exit (SS$_NORMAL); } fprintf (stdout, "%%HTTPD-E-IVKEYW, unrecognized keyword\n \\%s\\\n", CliProxyMaint); exit (STS$K_ERROR | STS$M_INHIB_MSG); } /****************************************************************************/ /* Print cache device statistics to stdout. */ ProxyMaintPrintDeviceStats (BOOL PrintToLog) { int status, ErrorCount, FreeBlocks, FreeMBytes, FreePercent, TotalMBytes, TotalBlocks, UsedBlocks, UsedMBytes, UsedPercent; char *DevNamePtr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintPrintDeviceStats() !UL", PrintToLog); status = ProxyMaintDeviceStats (&DevNamePtr, &TotalBlocks, &UsedBlocks, &FreeBlocks, &ErrorCount); if (VMSok (status)) { TotalMBytes = PROXY_MAINT_DEVICE_MBYTES(TotalBlocks); UsedMBytes = PROXY_MAINT_DEVICE_MBYTES(UsedBlocks); FreeMBytes = PROXY_MAINT_DEVICE_MBYTES(FreeBlocks); UsedPercent = PercentOf(UsedBlocks,TotalBlocks); FreePercent = PercentOf(FreeBlocks,TotalBlocks); } else TotalBlocks = TotalMBytes = UsedBlocks = UsedMBytes = UsedPercent = FreeBlocks = FreeMBytes = FreePercent = 0; if (PrintToLog || ProxyReportLog) FaoToStdout ( "%HTTPD-I-PROXYMAINT, cache device !AZ, !UL error!%s, !&S\n\ !UL blocks (!ULMB), !UL used (!ULMB !UL%), !UL free (!ULMB !UL%)\n", DevNamePtr, ErrorCount, status, TotalBlocks, TotalMBytes, UsedBlocks, UsedMBytes, UsedPercent, FreeBlocks, FreeMBytes, FreePercent); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-I-PROXYMAINT, cache device !AZ, !&S\r\n\ !UL blocks (!ULMB), !UL used (!ULMB !UL%), !UL free (!ULMB !UL%)", DevNamePtr, status, TotalBlocks, TotalMBytes, UsedBlocks, UsedMBytes, UsedPercent, FreeBlocks, FreeMBytes, FreePercent); } /****************************************************************************/ /* Include cache device statistics in WATCH report. */ ProxyMaintWatchDeviceStats () { int status, ErrorCount, FreeBlocks, FreeMBytes, FreePercent, TotalMBytes, TotalBlocks, UsedBlocks, UsedMBytes, UsedPercent; char *DevNamePtr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintWatchDeviceStats()"); status = ProxyMaintDeviceStats (&DevNamePtr, &TotalBlocks, &UsedBlocks, &FreeBlocks, &ErrorCount); if (VMSok (status)) { TotalMBytes = PROXY_MAINT_DEVICE_MBYTES(TotalBlocks); UsedMBytes = PROXY_MAINT_DEVICE_MBYTES(UsedBlocks); FreeMBytes = PROXY_MAINT_DEVICE_MBYTES(FreeBlocks); UsedPercent = PercentOf(UsedBlocks,TotalBlocks); FreePercent = PercentOf(FreeBlocks,TotalBlocks); } else TotalBlocks = TotalMBytes = UsedBlocks = UsedMBytes = UsedPercent = FreeBlocks = FreeMBytes = FreePercent = 0; #if WATCH_CAT WatchDataFormatted ( "!AZ !UL error!%s !&S \ !UL blocks (!ULMB), !UL used (!ULMB !UL%), !UL free (!ULMB !UL%)\n", DevNamePtr, ErrorCount, status, TotalBlocks, TotalMBytes, UsedBlocks, UsedMBytes, UsedPercent, FreeBlocks, FreeMBytes, FreePercent); #endif /* WATCH_CAT */ } /****************************************************************************/ /* Return information about file system space on the proxy cache device. Will function correctly with volume sets of up to eight members. Returns a VMS status code that should be checked for success. */ int ProxyMaintDeviceStats ( char **DevNamePtrPtr, int *TotalBlocksPtr, int *UsedBlocksPtr, int *FreeBlocksPtr, int *ErrorCountPtr ) { #define PROXY_MAINT_CACHE_DEVICE_MAX 8 static int DeviceCount, ErrCnt, FreeBlocks, MaxBlock, VolCount; static unsigned short Length; static short DevChannel [PROXY_MAINT_CACHE_DEVICE_MAX]; static char CacheDevName [65], DevName [65]; static $DESCRIPTOR (DevNameDsc, ""); static struct { short BufferLength; short ItemCode; void *BufferPtr; void *LengthPtr; } DevNamItemList [] = { { sizeof(CacheDevName), DVI$_DEVNAM, &CacheDevName, &Length }, { sizeof(VolCount), DVI$_VOLCOUNT, &VolCount, 0 }, { 0, 0, 0, 0 } }, NextDevNamItemList [] = { { sizeof(DevName), DVI$_NEXTDEVNAM, &DevName, &Length }, { 0, 0, 0, 0 } }, BlocksItemList [] = { { sizeof(MaxBlock), DVI$_MAXBLOCK, &MaxBlock, 0 }, { sizeof(FreeBlocks), DVI$_FREEBLOCKS, &FreeBlocks, 0 }, { sizeof(ErrCnt), DVI$_ERRCNT, &ErrCnt, 0 }, { 0, 0, 0, 0 } }; int idx, status, ErrorCount, TotalBlocks, TotalFreeBlocks, TotalUsedBlocks; IO_SB IOsb; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintDeviceStats()"); if (DevNamePtrPtr) *DevNamePtrPtr = DevName; if (TotalBlocksPtr) *TotalBlocksPtr = 0; if (UsedBlocksPtr) *UsedBlocksPtr = 0; if (FreeBlocksPtr) *FreeBlocksPtr = 0; if (ErrorCountPtr) *ErrorCountPtr = 0; if (!DeviceCount) { /**************/ /* initialize */ /**************/ DevNameDsc.dsc$a_pointer = v10orPrev10(PROXY_CACHE_ROOT,-1); DevNameDsc.dsc$w_length = strlen(DevNameDsc.dsc$a_pointer); if (DevNamePtrPtr) *DevNamePtrPtr = DevNameDsc.dsc$a_pointer; /* assign a channel to the cache device (or primary if a volume set) */ if (VMSnok (status = sys$assign (&DevNameDsc, &DevChannel[DeviceCount], 0, 0))) return (status); DeviceCount++; status = sys$getdviw (EfnWait, DevChannel[0], 0, &DevNamItemList, &IOsb, 0, 0, 0); if (VMSok (status)) status = IOsb.Status; if (VMSnok (status)) return (status); CacheDevName[Length] = '\0'; if (CacheDevName[0] == '_') memmove (CacheDevName, CacheDevName+1, Length); /* loop assigning a channel to all devices in volume set (if it is!) */ while (--VolCount) { if (DeviceCount >= PROXY_MAINT_CACHE_DEVICE_MAX) ErrorExitVmsStatus (0, ErrorProxyMaintTooManyDevices, FI_LI); status = sys$getdviw (EfnWait, DevChannel[0], 0, &NextDevNamItemList, &IOsb, 0, 0, 0); if (VMSok (status)) status = IOsb.Status; if (VMSnok (status)) return (status); DevName[Length] = '\0'; if (!Length) break; DevNameDsc.dsc$w_length = Length; DevNameDsc.dsc$a_pointer = DevName; if (VMSnok (status = sys$assign (&DevNameDsc, &DevChannel[DeviceCount++], 0, 0))) return (status); } } /***********/ /* process */ /***********/ ErrorCount = TotalBlocks = TotalFreeBlocks = 0; for (idx = 0; idx < DeviceCount; idx++) { status = sys$getdviw (EfnWait, DevChannel[idx], 0, &BlocksItemList, &IOsb, 0, 0, 0); if (VMSok (status)) status = IOsb.Status; if (VMSnok (status)) return (status); TotalBlocks += MaxBlock; TotalFreeBlocks += FreeBlocks; ErrorCount += ErrCnt; } TotalUsedBlocks = TotalBlocks - TotalFreeBlocks; if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "!UL !UL !UL !ULMB !ULMB !ULMB !UL% !UL%", TotalBlocks, TotalFreeBlocks, TotalUsedBlocks, TotalBlocks >> 11, TotalFreeBlocks >> 11, TotalUsedBlocks >> 11, TotalFreeBlocks*100/TotalBlocks, TotalUsedBlocks*100/TotalBlocks); if (DevNamePtrPtr) *DevNamePtrPtr = CacheDevName; if (TotalBlocksPtr) *TotalBlocksPtr = TotalBlocks; if (UsedBlocksPtr) *UsedBlocksPtr = TotalUsedBlocks; if (FreeBlocksPtr) *FreeBlocksPtr = TotalFreeBlocks; if (ErrorCountPtr) *ErrorCountPtr = ErrorCount; return (SS$_NORMAL); } /****************************************************************************/ /* If the percentage of used space on the cache device is greater than or equal to the specified percentage then return true, otherwise return false. */ BOOL ProxyMaintDeviceFreeSpace (int LimitPercent) { int status, UsedBlocks, UsedPercent, TotalBlocks; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintDeviceFreeSpace() !UL", LimitPercent); if (VMSok (status = ProxyMaintDeviceStats (NULL, &TotalBlocks, &UsedBlocks, NULL, NULL))) { UsedPercent = PercentOf(UsedBlocks,TotalBlocks); if (UsedPercent > LimitPercent) return (false); else return (true); } else { FaoToStdout ( "%HTTPD-W-PROXYMAINT, !20%D, cache device problem - PROXY CACHING DISABLED\n\ -!&M\n", 0, status); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-W-PROXYMAINT, cache device problem - PROXY CACHING DISABLED\r\n\ -!&M", status); /* fudge ... indicate sufficient space, suppresses any purging */ return (true); } } /*****************************************************************************/ /* Called by HttpdTick() every minute (or so). This routine schedules the approriate proxy cache purge management activities. */ ProxyMaintSupervisor () { static int SupervisorSecond, RoutineYear, RoutineMonth, RoutineDay; int status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintSupervisor()"); if (ProxyServingEnabled) ProxyTunnelLogicalName (NULL); if (!ProxyServingEnabled || !ProxyCacheEnabled) return; if (SupervisorSecond < HttpdTickSecond) { /******************/ /* reactive purge */ /******************/ ProxyCacheFreeSpaceAvailable = ProxyMaintDeviceFreeSpace (ProxyCacheDeviceMaxPercent); InstanceMutexLock (INSTANCE_MUTEX_HTTPD); ProxyAccountingPtr->FreeSpaceAvailable = ProxyCacheFreeSpaceAvailable; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { if (ProxyCacheFreeSpaceAvailable) WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT sufficient free SPACE !UL% max", ProxyCacheDeviceMaxPercent); else WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT INSUFFICIENT free SPACE !UL% max", ProxyCacheDeviceMaxPercent); ProxyMaintWatchDeviceStats (); } /* if insufficient free space */ if (!ProxyCacheFreeSpaceAvailable) { if (ProxyMaintScanType == PROXY_MAINT_SCAN_NONE) { /* can purge now */ ProxyMaintScanBegin (PROXY_MAINT_SCAN_REACTIVE); } else if (ProxyMaintScanType == PROXY_MAINT_SCAN_BCKGRND) { /* after background has stopped */ ProxyMaintChangeToReactive = true; } } } if (ProxyCacheRoutineHourOfDay >= 0 && ProxyCacheRoutineHourOfDay <= 23) { /*****************/ /* routine purge */ /*****************/ /* only if during the first five minutes of that hour */ if (ProxyCacheRoutineHourOfDay == HttpdNumTime[3] && (RoutineDay != HttpdNumTime[2] || RoutineMonth != HttpdNumTime[1] || RoutineYear != HttpdNumTime[0]) && HttpdNumTime[4] <= 5) { RoutineYear = HttpdNumTime[0]; RoutineMonth = HttpdNumTime[1]; RoutineDay = HttpdNumTime[2]; /* if no other scan is underway then start the routine one */ if (ProxyMaintScanType == PROXY_MAINT_SCAN_NONE) ProxyMaintScanBegin (PROXY_MAINT_SCAN_ROUTINE); } } else if (ProxyCacheRoutineHourOfDay == 24) { /********************/ /* background purge */ /********************/ /* check for background purge at same time and rate as reactive */ if (SupervisorSecond < HttpdTickSecond) { /* if another scan is not already underway start one */ if (ProxyMaintScanType == PROXY_MAINT_SCAN_NONE) ProxyMaintScanBegin (PROXY_MAINT_SCAN_BCKGRND); } } if (SupervisorSecond < HttpdTickSecond) SupervisorSecond = HttpdTickSecond + ProxyCacheDeviceCheckMinutes * 60; } /*****************************************************************************/ /* Queue a wait for the apprpriate milliseconds before continuing on to the next file in the cache. There are 86400 seconds in a 24 hour period. At one per second we can therefore scan 86400 files in that day (more or less). At two per second 172,800 per day. At four per second 345,600 files per day. And so on. Returns false if ProxyMaintScanSearch() should continue with the file scan, true if it should wait. When the timer expires the AST calls ProxyMaintScanSearch() to continue with the scan. */ BOOL ProxyMaintBackgroundTimer () { static BOOL FlipFlop; static int mSec, PrevFileCount = -1; static unsigned long DelayDelta [2]; static struct RateTableStruct { int min, max, mSec; } RateTable [] = { { 0, 4320, 250 }, /* the default rate (4 per second) */ { 4321, 33200, 2000 }, /* 1 every 2 seconds */ { 33201, 86400, 1000 }, /* 1 per second */ { 86401, 172800, 500 }, /* 2 per second */ { 172801, 259200, 333 }, /* 3 per second */ { 259201, 345600, 250 }, /* 4 per second */ { 345601, 432000, 200 }, /* 5 per second */ { 432001, 518400, 167 }, /* 6 per second */ { 518401, 604800, 143 }, /* 7 per second */ { 604801, 691200, 125 }, /* 8 per second */ { 691201, 777600, 111 }, /* 9 per second */ { 777601, 864000, 100 }, /* 10 per second */ { 864001, 1728000, 50 }, /* 20 per second */ { 1728001, 3456000, 25 }, /* 40, highly unlikely :^) */ { 0, 0, 0 } /* sentinal */ }; int idx, status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintBackgroundTimer() !&B !UL", FlipFlop, mSec); /* only every alternate call delays */ if (FlipFlop = !FlipFlop) return (false); if (PrevFileCount != ProxyMaintBackgroundFileCount) { PrevFileCount = ProxyMaintBackgroundFileCount; /* scan through the rate table looking for a matching number of files */ for (idx = 0; RateTable[idx].mSec; idx++) if (ProxyMaintBackgroundFileCount >= RateTable[idx].min && ProxyMaintBackgroundFileCount < RateTable[idx].max) break; mSec = ProxyMaintBackgroundInterval = RateTable[idx].mSec; if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "!UL >= !UL < !UL !SL mS", RateTable[idx].min, ProxyMaintBackgroundFileCount, RateTable[idx].max, mSec); /* this is one millisecond delta */ DelayDelta[0] = -10000; DelayDelta[1] = -1; /* multiply by the number of milliseconds between each file */ if (VMSnok (status = lib$mult_delta_time (&mSec, &DelayDelta))) ErrorExitVmsStatus (status, NULL, FI_LI); } /* if matching rate not found (exceeds maximum) go like the clappers */ if (!mSec) return (false); /* queue up a timer event delaying the next file check */ if (VMSnok (status = sys$setimr (0, &DelayDelta, &ProxyMaintScanSearch, 0, 0))) ErrorExitVmsStatus (status, NULL, FI_LI); return (true); } /****************************************************************************/ /* Initialize ready to begin a routine or purge pass. */ int ProxyMaintScanBegin (int ScanType) { static BOOL NotEnabledMessage; int status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintScanBegin() !UL", ScanType); if (!ProxyCacheEnabled) { if (NotEnabledMessage) return (STS$K_ERROR); NotEnabledMessage = true; if (ProxyReportLog) FaoToStdout ("%HTTPD-W-PROXYMAINT, !20%D, cache not enabled\n", 0); return (STS$K_ERROR); } NotEnabledMessage = false; if (ScanType == PROXY_MAINT_SCAN_REACTIVE && ProxyMaintScanType == PROXY_MAINT_SCAN_BCKGRND) { /****************************/ /* after background stopped */ /****************************/ ProxyMaintChangeToReactive = true; return (SS$_NORMAL); } if (ScanType == PROXY_MAINT_SCAN_STOP) { /************/ /* whooaaa! */ /************/ ProxyMaintStopScan = true; return (SS$_NORMAL); } /* attempt to obtain the cache scan lock */ status = InstanceLockNoWait (INSTANCE_CLUSTER_PROXYMAINT); if (status == SS$_NOTQUEUED) { if (ProxyMaintScanType == PROXY_MAINT_SCAN_BCKGRND) { /* background scans don't report such startup failures */ return (STS$K_ERROR); } if (ProxyReportLog) FaoToStdout ("%HTTPD-W-PROXYMAINT, !20%D, cache already locked\n", &ProxyMaintScanStartTime64); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ("%HTTPD-W-PROXYMAINT, cache already locked"); return (STS$K_ERROR); } if (VMSnok (status)) ErrorExitVmsStatus (status, "InstanceLock()", FI_LI); /* only useful after the scan has started ;^) */ ProxyMaintStopScan = false; sys$gettim (&ProxyMaintScanStartTime64); ProxyMaintScanType = ScanType; ProxyMaintTargetPercent = ProxyCacheDeviceTargetPercent; ProxyMaintPurgeHoursIndex = 0; /* if reactive purge we start a little more aggressively */ if (ProxyMaintScanType == PROXY_MAINT_SCAN_REACTIVE) if (ProxyMaintPurgeHoursIndex < ProxyCachePurgeListCount) ProxyMaintPurgeHoursIndex++; ProxyMaintPurgeAtHour = ProxyCachePurgeList[ProxyMaintPurgeHoursIndex]; ProxyMaintDeletedCount = ProxyMaintDeletedAllocBlocks = ProxyMaintDeletedUsedBlocks = ProxyMaintAllocBlocks = ProxyMaintUsedBlocks = 0; switch (ProxyMaintScanType) { case PROXY_MAINT_SCAN_STATISTICS : /****************************/ /* getting cache statistics */ /****************************/ if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT begin STATISTICS SCAN"); ProxyMaintWatchDeviceStats (); } if (ProxyReportLog) FaoToStdout ("%HTTPD-I-PROXYMAINT, !20%D, begin statistics scan\n", &ProxyMaintScanStartTime64); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ("%HTTPD-I-PROXYMAINT, begin statistics scan"); ProxyMaintPrintDeviceStats (false); ProxyMaintStatScanCount++; ProxyMaintScanNow (); return (SS$_NORMAL); case PROXY_MAINT_SCAN_REACTIVE : /********************************/ /* purging to create free space */ /********************************/ if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT begin REACTIVE PURGE (>!UL hours, !UL% max, !UL% target)", ProxyMaintPurgeAtHour, ProxyCacheDeviceMaxPercent, ProxyMaintTargetPercent); ProxyMaintWatchDeviceStats (); } if (ProxyReportLog) FaoToStdout ( "%HTTPD-I-PROXYMAINT, !20%D, begin reactive purge\n\ (>!UL hours, !UL% max, !UL% target)\n", &ProxyMaintScanStartTime64, ProxyMaintPurgeAtHour, ProxyCacheDeviceMaxPercent, ProxyMaintTargetPercent); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-I-PROXYMAINT, begin reactive purge\r\n\ (>!UL hours, !UL% max, !UL% target)", ProxyMaintPurgeAtHour, ProxyCacheDeviceMaxPercent, ProxyMaintTargetPercent); ProxyMaintPrintDeviceStats (false); ProxyMaintReactivePurgeCount++; ProxyMaintScanNow (); return (SS$_NORMAL); case PROXY_MAINT_SCAN_ROUTINE : /*******************/ /* routine cleanup */ /*******************/ if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT begin ROUTINE PURGE (>!UL hours)", ProxyMaintPurgeAtHour); ProxyMaintWatchDeviceStats (); } if (ProxyReportLog) FaoToStdout ( "%HTTPD-I-PROXYMAINT, !20%D, begin routine purge (>!UL hours)\n", &ProxyMaintScanStartTime64, ProxyMaintPurgeAtHour); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-I-PROXYMAINT, begin routine purge (>!UL hours)", ProxyMaintPurgeAtHour); ProxyMaintPrintDeviceStats (false); ProxyMaintRoutinePurgeCount++; ProxyMaintScanNow (); return (SS$_NORMAL); case PROXY_MAINT_SCAN_BCKGRND : /**********************/ /* background cleanup */ /**********************/ if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT begin BACKGROUND PURGE (>!UL hours)", ProxyMaintPurgeAtHour); ProxyMaintWatchDeviceStats (); } if (ProxyReportLog) FaoToStdout ( "%HTTPD-I-PROXYMAINT, !20%D, begin background purge (>!UL hours)\n", &ProxyMaintScanStartTime64, ProxyMaintPurgeAtHour); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-I-PROXYMAINT, begin background purge (>!UL hours)", ProxyMaintPurgeAtHour); InstanceMutexLock (INSTANCE_MUTEX_HTTPD); ProxyMaintBackgroundFileCount = ProxyAccountingPtr->PrevFileCount; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); ProxyMaintPrintDeviceStats (false); ProxyMaintBackgroundPurgeCount++; ProxyMaintScanNow (); return (SS$_NORMAL); } ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); } /****************************************************************************/ /* End of a single pass through the entire cache directory tree. A PURGE will be made up of multiple passes, each using the next access hours found in the 'ProxyCachePurgeList' array. A ROUTINE purge will only make the one pass though the tree using only the hours in the zero element. */ ProxyMaintScanEnd () { int status, FreeBlocks, FreePercent, TotalBlocks; unsigned long CurrentTime64 [2], DeltaTime [2]; char *cptr; PROXY_CACHE_FILE_QIO *cfqptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintScanEnd()"); /* first ensure release of search channel by doing a syntax-only parse */ ProxyMaintSearchFab.fab$l_fna = "a:[b]c.d;"; ProxyMaintSearchFab.fab$b_fns = 9; ProxyMaintSearchFab.fab$b_dns = 0; ProxyMaintSearchFab.fab$l_fop &= ~FAB$M_ASY; ProxyMaintSearchNam.nam$l_esa = ProxyMaintExpandedFileName; ProxyMaintSearchNam.nam$b_ess = sizeof(ProxyMaintExpandedFileName)-1; ProxyMaintSearchNam.nam$l_rlf = 0; ProxyMaintSearchNam.nam$b_nop = NAM$M_SYNCHK; status = sys$parse (&ProxyMaintSearchFab, 0, 0); cfqptr = &ProxyMaintCacheFileQio; if (cfqptr->AcpChannel) { sys$dassgn (cfqptr->AcpChannel); cfqptr->AcpChannel = 0; } if (ProxyMaintStopScan) { cptr = "  (manually STOPed)"; if (ProxyReportLog) FaoToStdout ("%HTTPD-I-PROXYMAINT, !20%D, cache scan manually STOPed\n", 0); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ("%HTTPD-I-PROXYMAINT, cache scan manually STOPed"); ProxyCacheFreeSpaceAvailable = ProxyMaintDeviceFreeSpace (ProxyCacheDeviceMaxPercent); } else { cptr = ""; ProxyCacheFreeSpaceAvailable = ProxyMaintDeviceFreeSpace (ProxyMaintTargetPercent); } InstanceMutexLock (INSTANCE_MUTEX_HTTPD); ProxyAccountingPtr->FreeSpaceAvailable = ProxyCacheFreeSpaceAvailable; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); sys$gettim (&CurrentTime64); lib$sub_times (&CurrentTime64, &ProxyMaintScanStartTime64, &DeltaTime); switch (ProxyMaintScanType) { case PROXY_MAINT_SCAN_STATISTICS : /*******************/ /* cach statistics */ /*******************/ if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT end STATISTICS SCAN !UL files (!UL/!UL blocks)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks); ProxyMaintWatchDeviceStats (); } if (ProxyReportLog) FaoToStdout ( "%HTTPD-I-PROXYMAINT, !20%D, end statistics scan\n\ !UL files (!UL/!UL)\n", 0, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-I-PROXYMAINT, end statistics scan\r\n\ !UL files (!UL/!UL)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks); ProxyMaintPrintDeviceStats (false); FaoToBuffer (ProxyMaintStatusStringStatScan, sizeof(ProxyMaintStatusStringStatScan), NULL, "!UL, !20%D (!%T)
!UL files (!UL/!UL)!AZ", ProxyMaintStatScanCount, &ProxyMaintScanStartTime64, &DeltaTime, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, cptr); { /* don't use WASD functions to write into the locked areas */ $DESCRIPTOR (FaoDsc, "!AZ, !UL files (!UL/!UL)\0"); $DESCRIPTOR (StringDsc, ""); StringDsc.dsc$w_length = sizeof(ProxyAccountingPtr->StatusString)-1; StringDsc.dsc$a_pointer = ProxyAccountingPtr->StatusString; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); sys$fao (&FaoDsc, NULL, &StringDsc, DigitDayTime(0), ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } break; case PROXY_MAINT_SCAN_REACTIVE : /********************************/ /* purging to create free space */ /********************************/ /* if reached desired percent, or one complete purge, or no files */ if (ProxyCacheFreeSpaceAvailable || ProxyMaintPurgeHoursIndex >= ProxyCachePurgeListCount || !ProxyMaintFileCount || ProxyMaintStopScan) { /*****************/ /* cease purging */ /*****************/ if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT end REACTIVE PURGE \ !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); } if (ProxyReportLog) FaoToStdout ( "%HTTPD-I-PROXYMAINT, !20%D, end reactive purge\n\ !UL files (!UL/!UL), !UL deleted (!UL/!UL)\n", 0, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-I-PROXYMAINT, end reactive purge\r\n\ !UL files (!UL/!UL), !UL deleted (!UL/!UL)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); ProxyMaintPrintDeviceStats (false); FaoToBuffer (ProxyMaintStatusStringReactive, sizeof(ProxyMaintStatusStringReactive), NULL, "!UL, !20%D (!%T)
!UL files (!UL/!UL), !UL deleted (!UL/!UL)!AZ", ProxyMaintReactivePurgeCount, &ProxyMaintScanStartTime64, &DeltaTime, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks, cptr); { /* don't use WASD functions to write into the locked areas */ $DESCRIPTOR (FaoDsc, "!AZ, !UL files (!UL/!UL), !UL deleted (!UL/!UL)\0"); $DESCRIPTOR (StringDsc, ""); StringDsc.dsc$w_length = sizeof(ProxyAccountingPtr->StatusString)-1; StringDsc.dsc$a_pointer = ProxyAccountingPtr->StatusString; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); sys$fao (&FaoDsc, NULL, &StringDsc, DigitDayTime(0), ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } break; } /**********************/ /* next pass of purge */ /**********************/ ProxyMaintPurgeAtHour = ProxyCachePurgeList[++ProxyMaintPurgeHoursIndex]; if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT end pass REACTIVE PURGE \ !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT next REACTIVE PURGE >!UL hours !UL% max !UL% target", ProxyMaintPurgeAtHour, ProxyCacheDeviceMaxPercent, ProxyMaintTargetPercent); ProxyMaintWatchDeviceStats (); } if (ProxyReportLog) FaoToStdout ( "%HTTPD-I-PROXYMAINT, !20%D, end reactive pass\n\ !UL files (!UL/!UL), !UL deleted (!UL/!UL)\n\ next pass >!UL hours !UL% max !UL% target\n", 0, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks, ProxyMaintPurgeAtHour, ProxyCacheDeviceMaxPercent, ProxyMaintTargetPercent); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-I-PROXYMAINT, end reactive pass\r\n\ !UL files (!UL/!UL), !UL deleted (!UL/!UL)\r\n\ next pass >!UL hours !UL% max !UL% target", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks, ProxyMaintPurgeAtHour, ProxyCacheDeviceMaxPercent, ProxyMaintTargetPercent); ProxyMaintPrintDeviceStats (false); { /* don't use WASD functions to write into the locked areas */ $DESCRIPTOR (FaoDsc, "!AZ, REACTIVE purge, >!UL hours, !UL% max, !UL% target\0"); $DESCRIPTOR (StringDsc, ""); StringDsc.dsc$w_length = sizeof(ProxyAccountingPtr->StatusString)-1; StringDsc.dsc$a_pointer = ProxyAccountingPtr->StatusString; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); sys$fao (&FaoDsc, NULL, &StringDsc, DigitDayTime(0), ProxyMaintPurgeAtHour, ProxyCacheDeviceMaxPercent, ProxyMaintTargetPercent); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } /* reset these, we want to accumulate the deleted totals */ ProxyMaintAllocBlocks = ProxyMaintUsedBlocks = 0; ProxyMaintScanNow (); /* we're doing another scan, so we don't break! */ return; case PROXY_MAINT_SCAN_ROUTINE : /*******************/ /* routine cleanup */ /*******************/ if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT end ROUTINE PURGE \ !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); ProxyMaintWatchDeviceStats (); } if (ProxyReportLog) FaoToStdout ( "%HTTPD-I-PROXYMAINT, !20%D, end routine purge\n\ !UL files (!UL/!UL), !UL deleted (!UL/!UL)\n", 0, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-I-PROXYMAINT, end routine purge\r\n\ !UL files (!UL/!UL), !UL deleted (!UL/!UL)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); ProxyMaintPrintDeviceStats (false); FaoToBuffer (ProxyMaintStatusStringRoutine, sizeof(ProxyMaintStatusStringRoutine), NULL, "!UL, !20%D (!%T)
!UL files (!UL/!UL), !UL deleted (!UL/!UL)!AZ", ProxyMaintRoutinePurgeCount, &ProxyMaintScanStartTime64, &DeltaTime, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks, cptr); { /* don't use WASD functions to write into the locked areas */ $DESCRIPTOR (FaoDsc, "!AZ, !UL files (!UL/!UL), !UL deleted (!UL/!UL)\0"); $DESCRIPTOR (StringDsc, ""); StringDsc.dsc$w_length = sizeof(ProxyAccountingPtr->StatusString)-1; StringDsc.dsc$a_pointer = ProxyAccountingPtr->StatusString; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); sys$fao (&FaoDsc, NULL, &StringDsc, DigitDayTime(0), ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } break; case PROXY_MAINT_SCAN_BCKGRND : /**********************/ /* background cleanup */ /**********************/ if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT end BACKGROUND PURGE \ !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); ProxyMaintWatchDeviceStats (); } if (ProxyReportLog) FaoToStdout ( "%HTTPD-I-PROXYMAINT, !20%D, end background purge\n\ !UL files (!UL/!UL), !UL deleted (!UL/!UL)\n", 0, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-I-PROXYMAINT, end background purge\r\n\ !UL files (!UL/!UL), !UL deleted (!UL/!UL)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); ProxyMaintPrintDeviceStats (false); if (!ProxyMaintChangeToReactive && !ProxyMaintStopScan) FaoToBuffer (ProxyMaintStatusStringBckGrnd, sizeof(ProxyMaintStatusStringBckGrnd), NULL, "!UL, !20%D (!%T)
!UL files (!UL/!UL), !UL deleted (!UL/!UL)!AZ", ProxyMaintBackgroundPurgeCount, &ProxyMaintScanStartTime64, &DeltaTime, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks, cptr); { /* don't use WASD functions to write into the locked areas */ $DESCRIPTOR (FaoDsc, "!AZ, !UL files (!UL/!UL), !UL deleted (!UL/!UL)\0"); $DESCRIPTOR (StringDsc, ""); StringDsc.dsc$w_length = sizeof(ProxyAccountingPtr->StatusString)-1; StringDsc.dsc$a_pointer = ProxyAccountingPtr->StatusString; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); sys$fao (&FaoDsc, NULL, &StringDsc, DigitDayTime(0), ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } break; default : ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); } InstanceMutexLock (INSTANCE_MUTEX_HTTPD); ProxyAccountingPtr->PrevFileCount = ProxyMaintFileCount; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); /* release the cache lock */ if (VMSnok (status = InstanceUnLock (INSTANCE_CLUSTER_PROXYMAINT))) ErrorExitVmsStatus (status, "InstanceUnLock()", FI_LI); if (ProxyMaintScanType == PROXY_MAINT_SCAN_BCKGRND) { if (ProxyMaintChangeToReactive) { ProxyMaintChangeToReactive = false; ProxyMaintScanType = PROXY_MAINT_SCAN_NONE; ProxyMaintScanBegin (PROXY_MAINT_SCAN_REACTIVE); return; } } ProxyMaintStopScan = false; ProxyMaintScanType = PROXY_MAINT_SCAN_NONE; /* if from the command-line wake the main thread */ if (CliProxyMaint[0]) sys$wake (0, 0); } /****************************************************************************/ /* Initialize the RMS structures ready for the file search. */ ProxyMaintScanNow () { int status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintScanNow() !&Z", ProxyMaintScanFileSpec); ProxyMaintScanFileSpec = v10orPrev10(PROXY_CACHE_SPEC,-1); ProxyMaintSearchFab = cc$rms_fab; ProxyMaintSearchFab.fab$l_fna = ProxyMaintScanFileSpec; ProxyMaintSearchFab.fab$b_fns = ProxyMaintScanFileSpecLength; ProxyMaintSearchFab.fab$l_nam = &ProxyMaintSearchNam; /* initialize the NAM block */ ProxyMaintSearchNam = cc$rms_nam; ProxyMaintSearchNam.nam$l_esa = ProxyMaintExpandedFileName; ProxyMaintSearchNam.nam$b_ess = sizeof(ProxyMaintExpandedFileName)-1; ProxyMaintSearchNam.nam$l_rsa = ProxyMaintResultFileName; ProxyMaintSearchNam.nam$b_rss = sizeof(ProxyMaintResultFileName)-1; status = sys$parse (&ProxyMaintSearchFab, 0, 0); if (VMSnok (status)) { if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "sys$parse() !&S", status); ProxyMaintScanEnd (); return; } if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) WatchThis (WATCHALL, WATCH_PROXY_CACHE, "SCAN !AZ !AZ", ProxyMaintScanFileSpec, ProxyMaintExpandedFileName); ProxyMaintFileCount = 0; /* now we've done the parse do the searching asynchronously */ ProxyMaintSearchFab.fab$l_fop = FAB$M_ASY; ProxyMaintScanSearch (); } /****************************************************************************/ /* Simply queue another asynchronous RMS search. */ ProxyMaintScanSearch () { int status; unsigned long CurrentTime64 [2], DeltaTime [2]; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintScanSearch()"); if (ProxyMaintStopScan || ProxyMaintChangeToReactive) { ProxyMaintScanEnd (); return; } switch (ProxyMaintScanType) { case PROXY_MAINT_SCAN_BCKGRND : /* if we should wait before continuing with the next file */ if (ProxyMaintBackgroundTimer ()) return; /* just continue */ break; case PROXY_MAINT_SCAN_ROUTINE : case PROXY_MAINT_SCAN_STATISTICS : /* just continue through the complete scan */ break; case PROXY_MAINT_SCAN_REACTIVE : /* only recheck free space after every ten files deleted */ if (ProxyMaintFileCount && (!ProxyMaintDeletedCount || ProxyMaintDeletedCount % 10)) break; if (ProxyMaintDeviceFreeSpace (ProxyMaintTargetPercent)) { /* reached our desired limit, cease purging */ ProxyMaintScanEnd (); return; } break; default : ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); } if (ProxyMaintFileCount % PROXY_MAINT_SCAN_MONITOR_FILES == 0) { sys$gettim (&CurrentTime64); lib$sub_times (&CurrentTime64, &ProxyMaintScanStartTime64, &DeltaTime); switch (ProxyMaintScanType) { case PROXY_MAINT_SCAN_STATISTICS : if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT STATISTICS SCAN !UL files (!UL/!UL blocks)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks); ProxyMaintWatchDeviceStats (); } FaoToBuffer (ProxyMaintStatusStringStatScan, sizeof(ProxyMaintStatusStringStatScan), NULL, "!UL, !20%D (!%T)
!UL files (!UL/!UL)", ProxyMaintStatScanCount, &ProxyMaintScanStartTime64, &DeltaTime, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks); { /* don't use WASD functions to write into the locked areas */ $DESCRIPTOR (FaoDsc, "!AZ, STATISTICS, !UL (!UL/!UL)\0"); $DESCRIPTOR (StringDsc, ""); StringDsc.dsc$w_length = sizeof(ProxyAccountingPtr->StatusString)-1; StringDsc.dsc$a_pointer = ProxyAccountingPtr->StatusString; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); sys$fao (&FaoDsc, NULL, &StringDsc, DigitDayTime(&ProxyMaintScanStartTime64), ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } break; case PROXY_MAINT_SCAN_REACTIVE : if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT REACTIVE !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); ProxyMaintWatchDeviceStats (); } FaoToBuffer (ProxyMaintStatusStringReactive, sizeof(ProxyMaintStatusStringReactive), NULL, "!UL, !20%D (!%T), >!UL hours, !UL% max, !UL% target
\ !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks)", ProxyMaintReactivePurgeCount, &ProxyMaintScanStartTime64, &DeltaTime, ProxyMaintPurgeAtHour, ProxyCacheDeviceMaxPercent, ProxyMaintTargetPercent, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); { /* don't use WASD functions to write into the locked areas */ $DESCRIPTOR (FaoDsc, "!AZ, REACTIVE, !UL (!UL/!UL) - !UL (!UL/!UL)\0"); $DESCRIPTOR (StringDsc, ""); StringDsc.dsc$w_length = sizeof(ProxyAccountingPtr->StatusString)-1; StringDsc.dsc$a_pointer = ProxyAccountingPtr->StatusString; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); sys$fao (&FaoDsc, NULL, &StringDsc, DigitDayTime(&ProxyMaintScanStartTime64), ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } break; case PROXY_MAINT_SCAN_ROUTINE : if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT ROUTINE !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); ProxyMaintWatchDeviceStats (); } FaoToBuffer (ProxyMaintStatusStringRoutine, sizeof(ProxyMaintStatusStringRoutine), NULL, "!UL, !20%D (!%T)
\ !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks)", ProxyMaintRoutinePurgeCount, &ProxyMaintScanStartTime64, &DeltaTime, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); { /* don't use WASD functions to write into the locked areas */ $DESCRIPTOR (FaoDsc, "!AZ, ROUTINE, !UL (!UL/!UL) - !UL (!UL/!UL)\0"); $DESCRIPTOR (StringDsc, ""); StringDsc.dsc$w_length = sizeof(ProxyAccountingPtr->StatusString)-1; StringDsc.dsc$a_pointer = ProxyAccountingPtr->StatusString; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); sys$fao (&FaoDsc, NULL, &StringDsc, DigitDayTime(&ProxyMaintScanStartTime64), ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } break; case PROXY_MAINT_SCAN_BCKGRND : if (WATCH_CATEGORY(WATCH_PROXY_CACHE)) { WatchThis (WATCHALL, WATCH_PROXY_CACHE, "MAINT BACKGROUND !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks)", ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); ProxyMaintWatchDeviceStats (); } FaoToBuffer (ProxyMaintStatusStringBckGrnd, sizeof(ProxyMaintStatusStringBckGrnd), NULL, "!UL, !20%D (!%T)
\ !UL files (!UL/!UL blocks) !UL deleted (!UL/!UL blocks) !UL mSec", ProxyMaintBackgroundPurgeCount, &ProxyMaintScanStartTime64, &DeltaTime, ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks, ProxyMaintBackgroundInterval); { /* don't use WASD functions to write into the locked areas */ $DESCRIPTOR (FaoDsc, "!AZ, BACKGROUND, !UL (!UL/!UL) - !UL (!UL/!UL)\0"); $DESCRIPTOR (StringDsc, ""); StringDsc.dsc$w_length = sizeof(ProxyAccountingPtr->StatusString)-1; StringDsc.dsc$a_pointer = ProxyAccountingPtr->StatusString; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); sys$fao (&FaoDsc, NULL, &StringDsc, DigitDayTime(&ProxyMaintScanStartTime64), ProxyMaintFileCount, ProxyMaintUsedBlocks, ProxyMaintAllocBlocks, ProxyMaintDeletedCount, ProxyMaintDeletedUsedBlocks, ProxyMaintDeletedAllocBlocks); InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } break; default : ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); } } status = sys$search (&ProxyMaintSearchFab, &ProxyMaintScanSearchAst, &ProxyMaintScanSearchAst); } /****************************************************************************/ /* AST from sys$search(). Check status and report any error. Otherwise generate and queue an asynchronous ACP file information QIO. */ ProxyMaintScanSearchAst (struct FAB *FabPtr) { static $DESCRIPTOR (DeviceDsc, ""); int status; ATRDEF *atptr; PROXY_CACHE_FILE_QIO *cfqptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintScanSearchAst() !&F !&X !&X", &ProxyMaintScanSearchAst, FabPtr->fab$l_sts, FabPtr->fab$l_stv); cfqptr = &ProxyMaintCacheFileQio; if (VMSnok (status = FabPtr->fab$l_sts)) { /****************/ /* search error */ /****************/ if (status == RMS$_NMF || (!ProxyMaintFileCount && status == RMS$_FNF)) { /* end of search */ ProxyMaintScanEnd (); return; } if (status == RMS$_FNF) { /* file probably deleted during search, just continue searching */ ProxyMaintScanSearch (); return; } FaoToStdout ( "%HTTPD-W-PROXYMAINT, !20%D, cache maintenance problem\n\ -!&M\n", 0, status); if (OpcomMessages & OPCOM_PROXY_MAINT) FaoToOpcom ( "%HTTPD-W-PROXYMAINT, cache maintenance problem\r\n\ -!&M", status); ProxyMaintScanEnd (); return; } ProxyMaintFileCount++; ProxyMaintResultFileNameLength = ProxyMaintSearchNam.nam$b_rsl; ProxyMaintResultFileName[ProxyMaintResultFileNameLength] = '\0'; /************/ /* file ACP */ /************/ if (!cfqptr->AcpChannel) { /* clean the structure out */ memset (cfqptr, sizeof(ProxyMaintCacheFileQio), 0); /* assign a channel to the disk device containing the file */ DeviceDsc.dsc$a_pointer = ProxyMaintSearchNam.nam$l_dev; DeviceDsc.dsc$w_length = ProxyMaintSearchNam.nam$b_dev; status = sys$assign (&DeviceDsc, &cfqptr->AcpChannel, 0, 0, 0); if (VMSnok (status)) ErrorExitVmsStatus (status, "sys$assign()", FI_LI); /* set up the File Information Block for the ACP interface */ cfqptr->FibDsc.dsc$w_length = sizeof(struct fibdef); cfqptr->FibDsc.dsc$a_pointer = &cfqptr->Fib; atptr = &cfqptr->FileAtr; atptr->atr$w_size = sizeof(cfqptr->BdtTime64); atptr->atr$w_type = ATR$C_BAKDATE; atptr->atr$l_addr = &cfqptr->BdtTime64; atptr++; atptr->atr$w_size = sizeof(cfqptr->CdtTime64); atptr->atr$w_type = ATR$C_CREDATE; atptr->atr$l_addr = &cfqptr->CdtTime64; atptr++; atptr->atr$w_size = sizeof(cfqptr->EdtTime64); atptr->atr$w_type = ATR$C_EXPDATE; atptr->atr$l_addr = &cfqptr->EdtTime64; atptr++; atptr->atr$w_size = sizeof(cfqptr->RdtTime64); atptr->atr$w_type = ATR$C_REVDATE; atptr->atr$l_addr = &cfqptr->RdtTime64; atptr++; atptr->atr$w_size = sizeof(cfqptr->AscDates); atptr->atr$w_type = ATR$C_ASCDATES; atptr->atr$l_addr = &cfqptr->AscDates; atptr++; atptr->atr$w_size = sizeof(cfqptr->RecAttr); atptr->atr$w_type = ATR$C_RECATTR; atptr->atr$l_addr = &cfqptr->RecAttr; atptr++; atptr->atr$w_size = atptr->atr$w_type = atptr->atr$l_addr = 0; } memcpy (&cfqptr->Fib.fib$w_did, &ProxyMaintSearchNam.nam$w_did, 6); cfqptr->FileNameDsc.dsc$a_pointer = ProxyMaintSearchNam.nam$l_name; cfqptr->FileNameDsc.dsc$w_length = ProxyMaintSearchNam.nam$b_name + ProxyMaintSearchNam.nam$b_type + ProxyMaintSearchNam.nam$b_ver; status = sys$qio (EfnNoWait, cfqptr->AcpChannel, IO$_ACCESS, &cfqptr->IOsb, &ProxyMaintAcpInfoAst, 0, &cfqptr->FibDsc, &cfqptr->FileNameDsc, 0, 0, &cfqptr->FileAtr, 0); } /****************************************************************************/ /* AST from ACP QIO. Calculate the relevant file information and determine if it should be purged (deleted). If not then just queue another search. If it should be then initialize the deletion RMS structures ready for sys$erase(). */ ProxyMaintAcpInfoAst () { int status, AccessHours, AccessSeconds; unsigned long AllocatedVbn, EndOfFileVbn; unsigned long CurrentTime6464 [2], ResultTime64 [2]; PROXY_CACHE_FILE_QIO *cfqptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintAcpInfoAst() !&F !&X", &ProxyMaintAcpInfoAst, ProxyMaintCacheFileQio.IOsb.Status); cfqptr = &ProxyMaintCacheFileQio; if (VMSnok (status = cfqptr->IOsb.Status)) { /*************/ /* ACP error */ /*************/ FaoToStdout ("%HTTPD-W-PROXYMAINT, \ file ACP error (!AZ !UL)\n-!&M\n \\!AZ\\\n", FI_LI, status, ProxyMaintResultFileName); /* file probably deleted during search, just continue searching */ ProxyMaintScanSearch (); return; } /**************/ /* ACP QIO OK */ /**************/ AllocatedVbn = ((cfqptr->RecAttr.fat$l_hiblk & 0xffff) << 16) | ((cfqptr->RecAttr.fat$l_hiblk & 0xffff0000) >> 16); EndOfFileVbn = ((cfqptr->RecAttr.fat$l_efblk & 0xffff) << 16) | ((cfqptr->RecAttr.fat$l_efblk & 0xffff0000) >> 16); if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "AllocatedVbn:!UL EndOfFileVbn:!UL FirstFreeByte:!UL", AllocatedVbn, EndOfFileVbn, cfqptr->RecAttr.fat$w_ffbyte); ProxyMaintAllocBlocks += ProxyMaintFileAllocBlocks = AllocatedVbn; if (EndOfFileVbn >= 1 && cfqptr->RecAttr.fat$w_ffbyte) ProxyMaintUsedBlocks += ProxyMaintFileUsedBlocks = EndOfFileVbn; else ProxyMaintFileUsedBlocks = 0; switch (ProxyMaintScanType) { case PROXY_MAINT_SCAN_STATISTICS : /* got the stats, just search for next */ ProxyMaintScanSearch (); return; case PROXY_MAINT_SCAN_BCKGRND : case PROXY_MAINT_SCAN_REACTIVE : case PROXY_MAINT_SCAN_ROUTINE : sys$gettim (&CurrentTime6464); /* if a v6.0 cache file, deal gracefully with the situation */ if (QUAD_ZERO(cfqptr->BdtTime64)) { /* check how long ago the file was last accessed */ AccessSeconds = ProxyCacheDeltaSeconds (&CurrentTime6464, &cfqptr->EdtTime64); AccessHours = AccessSeconds / 3600; /* break to drop through and delete the file */ if (AccessHours >= ProxyMaintPurgeAtHour) break; /* search for next */ ProxyMaintScanSearch (); return; } if (QUAD_NOT_ZERO(cfqptr->EdtTime64)) { /* status will be LIB$_NEGTIM if expired */ status = lib$sub_times (&cfqptr->EdtTime64, &CurrentTime6464, &ResultTime64); /* break to drop through and delete the file */ if (VMSnok (status)) break; } /* check how long ago the file was last accessed */ AccessSeconds = ProxyCacheDeltaSeconds (&CurrentTime6464, &cfqptr->RdtTime64); AccessHours = AccessSeconds / 3600; /* break to drop through and delete the file */ if (AccessHours >= ProxyMaintPurgeAtHour) break; /* search for next */ ProxyMaintScanSearch (); return; default : ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); } /***************/ /* delete file */ /***************/ status = sys$qio (EfnNoWait, cfqptr->AcpChannel, IO$_DELETE | IO$M_DELETE, &cfqptr->IOsb, &ProxyMaintDeleteAst, 0, &cfqptr->FibDsc, &cfqptr->FileNameDsc, 0, 0, 0, 0); if (VMSnok (status)) { /* let the AST routine handle it! */ cfqptr->IOsb.Status = status; SysDclAst (&ProxyMaintDeleteAst, 0); } } /****************************************************************************/ /* AST from QIO IO$_DELETE. */ ProxyMaintDeleteAst () { int status; PROXY_CACHE_FILE_QIO *cfqptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_PROXY)) WatchThis (WATCHALL, WATCH_MOD_PROXY, "ProxyMaintDeleteAst() !&F !&X", &ProxyMaintDeleteAst); cfqptr = &ProxyMaintCacheFileQio; if (VMSok (status = cfqptr->IOsb.Status)) { ProxyMaintDeletedCount++; ProxyMaintDeletedAllocBlocks += ProxyMaintFileAllocBlocks; ProxyMaintDeletedUsedBlocks += ProxyMaintFileUsedBlocks; } else { FaoToStdout ("%HTTPD-W-PROXYMAINT, \ file erase error (!AZ !UL)\n-!&M\n \\!AZ\\\n", FI_LI, status, ProxyMaintEraseFileName); } /* search next */ ProxyMaintScanSearch (); } /*****************************************************************************/ /* Return a report and control menu related proxy serving. */ ProxyMaintReport (REQUEST_STRUCT *rqptr) { static char CacheDeviceFao [] = "

\n\ \n\ \n\
Cache!AZ
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Device:!AZ!&@\n\
!UL  error!%s\n\
!UL  blocks  (!ULMB)\n\
!UL  used  (!ULMB !UL%)\n\
!UL  free  (!ULMB !UL%)\n\
Free Space:!AZ
In-Progress:!AZ
Statistics Scan:!AZ
!AZ:!AZ
Reactive Purge:!AZ
!AZ:!AZ
\n\ \n\ \n\
\n\
\n\ \n\
\n\
\n\
\n\ \n\
\n\
\n\
\n\ \n\
\n\
\n\
\n\ \n\
\n\
\n\
\n\ \n\
\n\
\n\
\n\
\n\ !AZ\ \n\ \n"; int status, ErrorCount, FreeBlocks, FreeMBytes, FreePercent, TotalMBytes, TotalBlocks, UsedBlocks, UsedMBytes, UsedPercent; unsigned short Length; unsigned long FaoVector [64]; unsigned long *vecptr; char *DevNamePtr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_PROXY)) WatchThis (WATCHITM(rqptr), WATCH_MOD_PROXY, "ProxyMaintReport()"); AdminPageTitle (rqptr, "Proxy Report"); status = ProxyMaintStatisticsReport (rqptr, true); if (VMSnok (status)) { rqptr->rqResponse.ErrorTextPtr = "ProxyMaintStatisticsReport()"; ErrorVmsStatus (rqptr, status, FI_LI); AdminEnd (rqptr); return; } status = ProxyMaintFunctionReport (rqptr); if (VMSnok (status)) { rqptr->rqResponse.ErrorTextPtr = "ProxyMaintFunctionReport()"; ErrorVmsStatus (rqptr, status, FI_LI); AdminEnd (rqptr); return; } status = ProxyMaintDeviceStats (&DevNamePtr, &TotalBlocks, &UsedBlocks, &FreeBlocks, &ErrorCount); if (VMSok (status)) { TotalMBytes = PROXY_MAINT_DEVICE_MBYTES(TotalBlocks); UsedMBytes = PROXY_MAINT_DEVICE_MBYTES(UsedBlocks); FreeMBytes = PROXY_MAINT_DEVICE_MBYTES(FreeBlocks); UsedPercent = PercentOf(UsedBlocks,TotalBlocks); FreePercent = PercentOf(FreeBlocks,TotalBlocks); } else TotalBlocks = TotalMBytes = UsedBlocks = UsedMBytes = UsedPercent = FreeBlocks = FreeMBytes = FreePercent = 0; vecptr = FaoVector; if (ProxyServingEnabled && ProxyCacheEnabled) *vecptr++ = ""; else *vecptr++ = " ... DISABLED"; *vecptr++ = DevNamePtr; if (VMSok (status)) *vecptr++ = ""; else { *vecptr++ = " %!&M"; *vecptr++ = status; } *vecptr++ = ErrorCount; *vecptr++ = TotalBlocks; *vecptr++ = TotalMBytes; *vecptr++ = UsedBlocks; *vecptr++ = UsedMBytes; *vecptr++ = UsedPercent; *vecptr++ = FreeBlocks; *vecptr++ = FreeMBytes; *vecptr++ = FreePercent; if (ProxyCacheEnabled) { if (ProxyCacheFreeSpaceAvailable) *vecptr++ = "AVAILABLE"; else *vecptr++ = "NOT AVAILABLE"; } else *vecptr++ = "n/a"; switch (ProxyMaintScanType) { case PROXY_MAINT_SCAN_STATISTICS : *vecptr++ = "STATISTICS SCAN"; break; case PROXY_MAINT_SCAN_REACTIVE : *vecptr++ = "REACTIVE PURGE"; break; case PROXY_MAINT_SCAN_ROUTINE : *vecptr++ = "ROUTINE PURGE"; break; case PROXY_MAINT_SCAN_BCKGRND : *vecptr++ = "BACKGROUND PURGE"; break; default : if (ProxyCacheEnabled) *vecptr++ = "none"; else *vecptr++ = "n/a"; } *vecptr++ = ProxyMaintStatusStringStatScan; if (ProxyCacheRoutineHourOfDay == 24) *vecptr++ = "Background Purge"; else *vecptr++ = "Background Purge"; *vecptr++ = ProxyMaintStatusStringBckGrnd; *vecptr++ = ProxyMaintStatusStringReactive; if (ProxyCacheRoutineHourOfDay >= 0 && ProxyCacheRoutineHourOfDay <= 23) *vecptr++ = "Routine Purge"; else *vecptr++ = "Routine Purge"; *vecptr++ = ProxyMaintStatusStringRoutine; *vecptr++ = ADMIN_CONTROL_PROXY_STATISTICS; *vecptr++ = ADMIN_CONTROL_PROXY_PURGE_BCKGRND; *vecptr++ = ADMIN_CONTROL_PROXY_PURGE_REACTIVE; *vecptr++ = ADMIN_CONTROL_PROXY_PURGE_ROUTINE; *vecptr++ = ADMIN_CONTROL_PROXY_STOP_SCAN; *vecptr++ = AdminRefresh(); status = FaolToNet (rqptr, CacheDeviceFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc); AdminEnd (rqptr); } /*****************************************************************************/ /* Return a report on proxy serving. */ ProxyMaintStatisticsReport ( REQUEST_STRUCT *rqptr, BOOL StatisticsReport ) { static char ResponseFao [] = "

\n\ \n\ \n\
!AZ!AZ
\n\ \n\ \n\ \ \ \ \n\ \ \ \ \n\
\n\ \n\ \ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Cache
Read:!&L(!UL%)
304:!&L(!UL%)
Write:!&L(!UL%)
Cannot  /Request:!&L(!UL%)
/Response:!&L(!UL%)
/Bytes:!&,@SQ(!UL%)
Rx:!&,@SQ(!UL%)
Tx:!&,@SQ
1nn:!&L
2nn:!&L
3nn:!&L
4nn:!&L
5nn:!&L
none:!&L
 
Method
CONNECT:!&L
DELETE:!&L
GET:!&L
HEAD:!&L
OPTIONS:!&L
POST:!&L
PUT:!&L
TRACE:!&L
WebDAV:!&L
Extension:!&L
(SSH):!&L
\n\
 \n\ \n\ \n\ \ \n\ \n\ \n\ \ !&@\n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \ \ \n\ \n\ \n\ \n\ \ \n\ \ \ \n\ \n\
Network
Requested:!&L(!UL%)
IPv4:!&L(!UL%)
IPv6:!&L(!UL%)
Persistent  /Current!&L
/Peak!&L
/Count!&L(!UL%)
Rx:!&,@SQ(!UL%)
Tx:!&,@SQ
1nn:!&L
2nn:!&L
3nn:!&L
4nn:!&L
5nn:!&L
none:!&L
 
Host Resolution
Literal:!&L
DNS:!&L(!UL%)
Cache:!&L
Error:!&L
 
Proxy Total
Requests:!&L
Bytes:!&,@SQ
\n\
\n\
\n"; int status, ConnectCountNetwork, PercentBytesCache, PercentBytesNetwork, PercentBytesCannotCache, PercentCountCache304, PercentCountCacheRead, PercentCountCacheWrite, PercentCountRequestCannotCache, PercentCountResponseCannotCache, PercentCountIpv4, PercentCountIpv6, PercentCountNetwork, PercentCountPersist, PercentDnsName, TotalCount; unsigned short Length; unsigned long FaoVector [64], BytesCache [2], BytesCannotCache [2], BytesRaw [2], BytesRawRx [2], BytesRawTx [2], BytesCacheRx [2], BytesCacheTx [2], BytesTotal [2]; unsigned long *vecptr; float FloatBytesCache, FloatBytesCannotCache, FloatBytesNetwork, FloatBytesTotal, FloatCountCache304, FloatCountCacheRead, FloatCountCacheWrite, FloatCountIpv4, FloatCountIpv6, FloatCountRequestCannotCache, FloatCountResponseCannotCache, FloatCountNetwork, FloatCountTotal, FloatNetworkCount, FloatPercent; char Buffer [2048]; $DESCRIPTOR (BufferDsc, Buffer); /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_PROXY)) WatchThis (WATCHITM(rqptr), WATCH_MOD_PROXY, "ProxyMaintStatisticsReport()"); if (!ProxyServingEnabled && !StatisticsReport) return; InstanceMutexLock (INSTANCE_MUTEX_HTTPD); /*********/ /* bytes */ /*********/ PLUS_QUAD_QUAD (ProxyAccountingPtr->BytesCacheRx, ProxyAccountingPtr->BytesCacheTx, BytesCache); PLUS_QUAD_QUAD (ProxyAccountingPtr->BytesCannotCacheRx, ProxyAccountingPtr->BytesCannotCacheTx, BytesCannotCache); PLUS_QUAD_QUAD (ProxyAccountingPtr->BytesRawRx, ProxyAccountingPtr->BytesRawTx, BytesRaw); PLUS_QUAD_QUAD (BytesCache, BytesRaw, BytesTotal); FloatBytesCache = (float)BytesCache[0] + (float)BytesCache[1] * 4294967296.0; /********************/ /* bytes percentage */ /********************/ FloatBytesCannotCache = (float)BytesCannotCache[0] + (float)BytesCannotCache[1] * 4294967296.0; FloatBytesNetwork = (float)BytesRaw[0] + (float)BytesRaw[1] * 4294967296.0; FloatBytesTotal = (float)BytesTotal[0] + (float)BytesTotal[1] * 4294967296.0; if (FloatBytesTotal > 0.0) { PercentBytesCache = (int)(FloatPercent = FloatBytesCache * 100.0 / FloatBytesTotal); if (FloatPercent - (float)PercentBytesCache >= 0.5) PercentBytesCache++; PercentBytesCannotCache = (int)(FloatPercent = FloatBytesCannotCache * 100.0 / FloatBytesTotal); if (FloatPercent - (float)PercentBytesCannotCache >= 0.5) PercentBytesCannotCache++; PercentBytesNetwork = (int)(FloatPercent = FloatBytesNetwork * 100.0 / FloatBytesTotal); if (FloatPercent - (float)PercentBytesNetwork >= 0.5) PercentBytesNetwork++; } else PercentBytesCache = PercentBytesCannotCache = PercentBytesNetwork = 0; /*********************/ /* counts percentage */ /*********************/ FloatCountRequestCannotCache = ProxyAccountingPtr->RequestCannotCacheCount; FloatCountResponseCannotCache = ProxyAccountingPtr->ResponseCannotCacheCount; ConnectCountNetwork = ProxyAccountingPtr->ConnectIpv4Count + ProxyAccountingPtr->ConnectIpv6Count; FloatCountIpv4 = (float)ProxyAccountingPtr->ConnectIpv4Count; FloatCountIpv6 = (float)ProxyAccountingPtr->ConnectIpv6Count; FloatCountNetwork = FloatCountIpv4 + FloatCountIpv6; FloatCountCache304 = ProxyAccountingPtr->CacheRead304Count; FloatCountCacheRead = ProxyAccountingPtr->CacheReadCount; FloatCountCacheWrite = ProxyAccountingPtr->CacheWriteCount; FloatCountTotal = FloatCountNetwork + FloatCountCacheRead; if (FloatCountTotal > 0.0) { PercentCountNetwork = (int)(FloatPercent = FloatCountNetwork * 100.0 / FloatCountTotal); if (FloatPercent - (float)PercentCountNetwork >= 0.5) PercentCountNetwork++; PercentCountIpv4 = (int)(FloatPercent = FloatCountIpv4 * 100.0 / FloatCountTotal); if (FloatPercent - (float)PercentCountIpv4 >= 0.5) PercentCountIpv4++; PercentCountIpv6 = (int)(FloatPercent = FloatCountIpv6 * 100.0 / FloatCountTotal); if (FloatPercent - (float)PercentCountIpv6 >= 0.5) PercentCountIpv6++; PercentCountCacheRead = (int)(FloatPercent = FloatCountCacheRead * 100.0 / FloatCountTotal); if (FloatPercent - (float)PercentCountCacheRead >= 0.5) PercentCountCacheRead++; PercentCountCache304 = (int)(FloatPercent = FloatCountCache304 * 100.0 / FloatCountTotal); if (FloatPercent - (float)PercentCountCache304 >= 0.5) PercentCountCache304++; PercentCountRequestCannotCache = (int)(FloatPercent = FloatCountRequestCannotCache * 100.0 / FloatCountTotal); if (FloatPercent - (float)PercentCountRequestCannotCache >= 0.5) PercentCountRequestCannotCache++; } else PercentCountCache304 = PercentCountCacheRead = PercentCountRequestCannotCache = PercentCountNetwork = PercentCountIpv4 = PercentCountIpv6 = 0; if (FloatCountNetwork > 0.0) { PercentCountCacheWrite = (int)(FloatPercent = FloatCountCacheWrite * 100.0 / FloatCountNetwork); if (FloatPercent - (float)PercentCountCacheWrite >= 0.5) PercentCountCacheWrite++; PercentCountResponseCannotCache = (int)(FloatPercent = FloatCountResponseCannotCache * 100.0 / FloatCountNetwork); if (FloatPercent - (float)PercentCountResponseCannotCache >= 0.5) PercentCountResponseCannotCache++; } else PercentCountCacheWrite = PercentCountResponseCannotCache = 0; if (FloatCountNetwork > 0.0) PercentCountPersist = (int)(((float)ProxyAccountingPtr->ConnectPersistCount * 100) / FloatCountNetwork); else PercentCountPersist = 0; /* get these values because of the locking requirements */ PUT_QUAD_QUAD (ProxyAccountingPtr->BytesRawRx, BytesRawRx); PUT_QUAD_QUAD (ProxyAccountingPtr->BytesRawTx, BytesRawTx); PUT_QUAD_QUAD (ProxyAccountingPtr->BytesCacheRx, BytesCacheRx); PUT_QUAD_QUAD (ProxyAccountingPtr->BytesCacheTx, BytesCacheTx); TotalCount = AccountingPtr->LookupDnsNameCount + AccountingPtr->LookupCacheNameCount; if (TotalCount) PercentDnsName = AccountingPtr->LookupDnsNameCount * 100 / TotalCount; else PercentDnsName = 0; /***********/ /* display */ /***********/ vecptr = FaoVector; *vecptr++ = StatisticsReport ? "Statistics" : "Proxy"; if (ProxyServingEnabled) *vecptr++ = ""; else *vecptr++ = " ... DISABLED"; *vecptr++ = ProxyAccountingPtr->CacheReadCount; *vecptr++ = PercentCountCacheRead; *vecptr++ = ProxyAccountingPtr->CacheRead304Count; *vecptr++ = PercentCountCache304; *vecptr++ = ProxyAccountingPtr->CacheWriteCount; *vecptr++ = PercentCountCacheWrite; *vecptr++ = ProxyAccountingPtr->RequestCannotCacheCount; *vecptr++ = PercentCountRequestCannotCache; *vecptr++ = ProxyAccountingPtr->ResponseCannotCacheCount; *vecptr++ = PercentCountResponseCannotCache; *vecptr++ = &BytesCannotCache; *vecptr++ = PercentBytesCannotCache; *vecptr++ = &BytesCacheRx; *vecptr++ = PercentBytesCache; *vecptr++ = &BytesCacheTx; *vecptr++ = ProxyAccountingPtr->CacheStatusCodeCount[1]; *vecptr++ = ProxyAccountingPtr->CacheStatusCodeCount[2]; *vecptr++ = ProxyAccountingPtr->CacheStatusCodeCount[3]; *vecptr++ = ProxyAccountingPtr->CacheStatusCodeCount[4]; *vecptr++ = ProxyAccountingPtr->CacheStatusCodeCount[5]; *vecptr++ = ProxyAccountingPtr->CacheStatusCodeCount[0]; *vecptr++ = ProxyAccountingPtr->MethodConnectCount; *vecptr++ = ProxyAccountingPtr->MethodDeleteCount; *vecptr++ = ProxyAccountingPtr->MethodGetCount; *vecptr++ = ProxyAccountingPtr->MethodHeadCount; *vecptr++ = ProxyAccountingPtr->MethodOptionsCount; *vecptr++ = ProxyAccountingPtr->MethodPostCount; *vecptr++ = ProxyAccountingPtr->MethodPutCount; *vecptr++ = ProxyAccountingPtr->MethodTraceCount; *vecptr++ = ProxyAccountingPtr->MethodWebDavCopyCount + ProxyAccountingPtr->MethodWebDavLockCount + ProxyAccountingPtr->MethodWebDavMkColCount + ProxyAccountingPtr->MethodWebDavMoveCount + ProxyAccountingPtr->MethodWebDavPropFindCount + ProxyAccountingPtr->MethodWebDavPropPatchCount + ProxyAccountingPtr->MethodWebDavUnLockCount; *vecptr++ = ProxyAccountingPtr->MethodExtensionCount; *vecptr++ = ProxyAccountingPtr->MethodSshCount; *vecptr++ = ConnectCountNetwork; *vecptr++ = PercentCountNetwork; *vecptr++ = ProxyAccountingPtr->ConnectIpv4Count; *vecptr++ = PercentCountIpv4; *vecptr++ = ProxyAccountingPtr->ConnectIpv6Count; *vecptr++ = PercentCountIpv6; *vecptr++ = ProxyNetConnectCount; if (StatisticsReport) { *vecptr++ = "[Report]"; *vecptr++ = ADMIN_REPORT_PROXY_PERSISTENT; } else *vecptr++ = ""; *vecptr++ = ProxyAccountingPtr->ConnectPersistPeak; *vecptr++ = ProxyAccountingPtr->ConnectPersistCount; *vecptr++ = PercentCountPersist; *vecptr++ = &BytesRawRx; *vecptr++ = PercentBytesNetwork; *vecptr++ = &BytesRawTx; *vecptr++ = ProxyAccountingPtr->NetStatusCodeCount[1]; *vecptr++ = ProxyAccountingPtr->NetStatusCodeCount[2]; *vecptr++ = ProxyAccountingPtr->NetStatusCodeCount[3]; *vecptr++ = ProxyAccountingPtr->NetStatusCodeCount[4]; *vecptr++ = ProxyAccountingPtr->NetStatusCodeCount[5]; *vecptr++ = ProxyAccountingPtr->NetStatusCodeCount[0]; *vecptr++ = AccountingPtr->LookupLiteralCount; *vecptr++ = AccountingPtr->LookupDnsNameCount; *vecptr++ = PercentDnsName; *vecptr++ = AccountingPtr->LookupCacheNameCount; *vecptr++ = AccountingPtr->LookupDnsNameErrorCount; *vecptr++ = AccountingPtr->DoProxyCount; *vecptr++ = &BytesRaw; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); status = FaolToNet (rqptr, ResponseFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return (status); } /*****************************************************************************/ /* Return a report on proxy special functionality. */ ProxyMaintFunctionReport (REQUEST_STRUCT *rqptr) { static char ResponseFao [] = "

\n\ \n\ \n\
Function!AZ
\n\ \n\ \n\ \ \ \ \n\ \ \ \ \n\ \n\ \n\ \ \ \ \n\ \ \n\ \ \n\
\n\ \n\ \n\ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\
Gateway
Out \\ In:HTTPHTTPS
HTTP!&L!&L
HTTPS!&L!&L
FTP!&L!&L
Out \\ In:IPv4IPv6
IPv4!&L!&L
IPv6!&L!&L
\n\
  \n\ \n\ \n\ \ \ \ \ \n\ \ \ \ \ \ \n\ \ \ \ \ \ \n\ \ \ \ \ \ \n\ \ \ \ \ \ \n\ \n\ \n\
Tunnel
Out \\ In:CONNECTFirewallRaw
CONNECT!&L!&L!&L
HTTP!&L!&L!&L
HTTPS!&L!&L!&L
Raw!&L!&L!&L
Current:!&L
\n\
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
FTP
Total:!&LDELE:!&LDOS:!&L
Login Fail:!&LLIST:!&LUnix:!&L
RETR:!&LVMS:!&L
STOR:!&L?:!&L
\n\
  \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Verify
Max:!&LFull:!&L
Current:!&L200:!&L
Set:!&L403:!&L
Find:!&L404:!&L
\n\
\n\
\n"; int in, out, status; unsigned short Length; unsigned long FaoVector [64]; unsigned long *vecptr; char Buffer [2048]; $DESCRIPTOR (BufferDsc, Buffer); /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_PROXY)) WatchThis (WATCHITM(rqptr), WATCH_MOD_PROXY, "ProxyMaintFunctionReport()"); InstanceMutexLock (INSTANCE_MUTEX_HTTPD); vecptr = FaoVector; if (ProxyServingEnabled) *vecptr++ = ""; else *vecptr++ = " ... DISABLED"; /* [http=0,https=1,ftp=2][http=0,https=1] */ *vecptr++ = ProxyAccountingPtr->GatewaySchemeCount[0][0]; *vecptr++ = ProxyAccountingPtr->GatewaySchemeCount[1][0]; *vecptr++ = ProxyAccountingPtr->GatewaySchemeCount[0][1]; *vecptr++ = ProxyAccountingPtr->GatewaySchemeCount[1][1]; *vecptr++ = ProxyAccountingPtr->GatewaySchemeCount[0][2]; *vecptr++ = ProxyAccountingPtr->GatewaySchemeCount[1][2]; /* [ipv4=0,ipv6=1][ipv4=0,ipv6=1] */ *vecptr++ = ProxyAccountingPtr->GatewayIpvCount[0][0]; *vecptr++ = ProxyAccountingPtr->GatewayIpvCount[1][0]; *vecptr++ = ProxyAccountingPtr->GatewayIpvCount[0][1]; *vecptr++ = ProxyAccountingPtr->GatewayIpvCount[1][1]; for (out = 0; out < TUNNEL_COUNT_MAX; out++) { if (out+1 == PROXY_TUNNEL_FIREWALL) continue; for (in = 0; in < TUNNEL_COUNT_MAX; in++) { if (in+1 == PROXY_TUNNEL_HTTP || in+1 == PROXY_TUNNEL_HTTPS) continue; *vecptr++ = ProxyAccountingPtr->TunnelCount[in][out]; } } *vecptr++ = ProxyAccountingPtr->TunnelCurrent; *vecptr++ = ProxyAccountingPtr->FtpCount; *vecptr++ = ProxyAccountingPtr->FtpDeleCount; *vecptr++ = ProxyAccountingPtr->FtpDosCount; *vecptr++ = ProxyAccountingPtr->FtpLoginFailCount; *vecptr++ = ProxyAccountingPtr->FtpListCount; *vecptr++ = ProxyAccountingPtr->FtpUnixCount; *vecptr++ = ProxyAccountingPtr->FtpRetrCount; *vecptr++ = ProxyAccountingPtr->FtpVmsCount; *vecptr++ = ProxyAccountingPtr->FtpStorCount; *vecptr++ = ProxyAccountingPtr->FtpUnknownCount; *vecptr++ = ProxyVerifyRecordMax; *vecptr++ = ProxyAccountingPtr->VerifyFullCount; *vecptr++ = ProxyAccountingPtr->VerifyCurrentCount; *vecptr++ = ProxyAccountingPtr->Verify200Count; *vecptr++ = ProxyAccountingPtr->VerifySetRecordCount; *vecptr++ = ProxyAccountingPtr->Verify403Count; *vecptr++ = ProxyAccountingPtr->VerifyFindRecordCount; *vecptr++ = ProxyAccountingPtr->Verify404Count; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); status = FaolToNet (rqptr, ResponseFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return (status); } /*****************************************************************************/ /* Return a ontrol menu for dynamically adjusting proxy serving. */ ProxyMaintAdjust (REQUEST_STRUCT *rqptr) { static char ResponseFao [] = "!AZ\ \n\ \n\ !AZ\ !AZ\ WASD !AZ ... Proxy Report/Maintenance\n\ \n\ !AZ\n\

\n\

WASD !AZ

\n\

Proxy Report/Maintenance

\n\ !20&W\n\ \
\n\ \

\n\ \n\ \n\
Adjust Executing Server
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Serving:\n\ enabled\n\ disabled\n\
Cache:\n\ enabled\n\ disabled\n\
Unknown Request Fields:\n\ enabled\n\ disabled\n\
Add "Forwarded: by":\n\ \n\
Add "X-Forwarded-For:":\n\ \n\
Report To Log:\n\ enabled\n\ disabled\n\
Report Cache To Log:\n\ enabled\n\ disabled\n\
Host Name Lookup Retry:\n\ \n\ attempts
Connect Timeout Seconds:\n\ \n\ hh:mm:ss
Connect Persist Max:\n\ \n\ connections
Connect Persist Seconds:\n\ \n\ hh:mm:ss
Maximum Load Size:\n\ \n\ kBytes
Negative:\n\ \n\ hh:mm:ss
No Reload:\n\ \n\ hh:mm:ss
Reload List:\n\ \n\ hours
Routine Purge:\n\ \n\ hour-of-day (00-23)
Purge List:\n\ \n\ hours
Device Usage Check:\n\ \n\ minutes
Device Usage Max:\n\ \n\ percent
Device Reduce By:\n\ \n\ percent

\n\ \n\ \n\
\n\
\n\ \

\n\ \ \n\ \n"; #define REPBOOL(b)\ if (b)\ {\ *vecptr++ = RadioButtonChecked;\ *vecptr++ = RadioButtonUnchecked;\ }\ else\ {\ *vecptr++ = RadioButtonUnchecked;\ *vecptr++ = RadioButtonChecked;\ } static char RadioButtonChecked [] = " CHECKED", RadioButtonUnchecked [] = ""; int status; unsigned long FaoVector [64]; unsigned long *vecptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_PROXY)) WatchThis (WATCHITM(rqptr), WATCH_MOD_PROXY, "ProxyMaintAdjustMenu()"); vecptr = FaoVector; *vecptr++ = WASD_DOCTYPE; *vecptr++ = HtmlMetaInfo (rqptr, NULL); *vecptr++ = AdminWasdCss (); *vecptr++ = ServerHostPort; *vecptr++ = ADMIN_BODY_TAG; *vecptr++ = ServerHostPort; *vecptr++ = &rqptr->rqTime.BeginTime64; *vecptr++ = ADMIN_CONTROL_PROXY_ADJUST_NOW; REPBOOL (ProxyServingEnabled) REPBOOL (ProxyCacheEnabled) REPBOOL (ProxyUnknownRequestFields) if (ProxyForwardedBy == PROXY_FORWARDED_BY) *vecptr++ = "BY"; else if (ProxyForwardedBy == PROXY_FORWARDED_FOR) *vecptr++ = "FOR"; else *vecptr++ = "disabled"; if (ProxyXForwardedFor == PROXY_XFORWARDEDFOR_ENABLED) *vecptr++ = "ENABLED"; else if (ProxyXForwardedFor == PROXY_XFORWARDEDFOR_ADDRESS) *vecptr++ = "ADDRESS"; else if (ProxyXForwardedFor == PROXY_XFORWARDEDFOR_UNKNOWN) *vecptr++ = "UNKNOWN"; else *vecptr++ = "disabled"; REPBOOL (ProxyReportLog) REPBOOL (ProxyReportCacheLog) *vecptr++ = ProxyHostLookupRetryCount; *vecptr++ = MetaConShowSeconds (rqptr, ProxyConnectTimeoutSeconds); *vecptr++ = ProxyConnectPersistMax; *vecptr++ = MetaConShowSeconds (rqptr, ProxyConnectPersistSeconds); *vecptr++ = ProxyCacheFileKBytesMax; *vecptr++ = MetaConShowSeconds (rqptr, ProxyCacheNegativeSeconds); *vecptr++ = MetaConShowSeconds (rqptr, ProxyCacheNoReloadSeconds); *vecptr++ = ProxyCacheReloadListPtr; if (ProxyCacheRoutineHourOfDay >= 0) { *vecptr++ = "!UL"; *vecptr++ = ProxyCacheRoutineHourOfDay; } else *vecptr++ = ""; *vecptr++ = ProxyCachePurgeListPtr; *vecptr++ = ProxyCacheDeviceCheckMinutes; *vecptr++ = ProxyCacheDeviceMaxPercent; *vecptr++ = ProxyCacheDevicePurgePercent; status = FaolToNet (rqptr, ResponseFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc); AdminEnd (rqptr); } /*****************************************************************************/ /* */ ProxyMaintControl (REQUEST_STRUCT *rqptr) { BOOL MakeChanges; int status; unsigned short Length; char *cptr, *qptr, *sptr, *zptr; char FieldName [128], FieldValue [256], ProxyCachePurgeList [64], ProxyCacheReloadList [64]; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_PROXY)) WatchThis (WATCHITM(rqptr), WATCH_MOD_PROXY, "ProxyMaintControl()"); MakeChanges = false; /**********************/ /* parse content body */ /**********************/ if (rqptr->rqHeader.Method == HTTP_METHOD_POST) { if (!rqptr->rqBody.DataPtr) { /* read all the request body (special case) then AST back */ BodyReadBegin (rqptr, &ProxyMaintControl, &BodyProcessReadAll); return; } qptr = rqptr->rqBody.DataPtr; } else qptr = rqptr->rqHeader.QueryStringPtr; while (*qptr) { status = StringParseQuery (&qptr, FieldName, sizeof(FieldName), FieldValue, sizeof(FieldValue)); if (VMSnok (status)) { /* error occured */ if (status == SS$_IVCHAR) rqptr->rqResponse.HttpStatus = 400; rqptr->rqResponse.ErrorTextPtr = "parsing query string"; ErrorVmsStatus (rqptr, status, FI_LI); AdminEnd (rqptr); return; } /************************/ /* action button fields */ /************************/ if (strsame (FieldName, "hostname", -1)) { TcpIpHostCacheSupervisor ((unsigned int)-1); ReportSuccess (rqptr, "Server !AZ host name cache purged.", ServerHostPort); } else if (strsame (FieldName, "makechanges", -1)) MakeChanges = true; else if (strsame (FieldName, "ProxyForwarded", -1)) { if (TOUP(FieldValue[0]) == 'B') ProxyForwardedBy = PROXY_FORWARDED_BY; else if (TOUP(FieldValue[0]) == 'F') ProxyForwardedBy = PROXY_FORWARDED_FOR; else ProxyForwardedBy = PROXY_FORWARDED_DISABLED; } else if (strsame (FieldName, "ProxyXForwardedFor", -1)) { if (TOUP(FieldValue[0]) == 'A') ProxyXForwardedFor = PROXY_XFORWARDEDFOR_ADDRESS; else if (TOUP(FieldValue[0]) == 'E') ProxyXForwardedFor = PROXY_XFORWARDEDFOR_ENABLED; else if (TOUP(FieldValue[0]) == 'U') ProxyXForwardedFor = PROXY_XFORWARDEDFOR_UNKNOWN; else ProxyXForwardedFor = PROXY_XFORWARDEDFOR_DISABLED; } else if (strsame (FieldName, "ProxyServingEnabled", -1)) { InstanceMutexLock (INSTANCE_MUTEX_HTTPD); if (TOUP(FieldValue[0]) == 'E') ProxyServingEnabled = ProxyAccountingPtr->ServingEnabled = true; else if (TOUP(FieldValue[0]) == 'D') ProxyServingEnabled = ProxyAccountingPtr->ServingEnabled = false; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } else if (strsame (FieldName, "ProxyCacheEnabled", -1)) { InstanceMutexLock (INSTANCE_MUTEX_HTTPD); if (TOUP(FieldValue[0]) == 'E') ProxyCacheEnabled = ProxyAccountingPtr->CacheEnabled = true; else if (TOUP(FieldValue[0]) == 'D') ProxyCacheEnabled = ProxyAccountingPtr->CacheEnabled = false; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); } else if (strsame (FieldName, "ProxyHostLookupRetryCount", -1)) { ProxyHostLookupRetryCount = atoi(FieldValue); if (ProxyHostLookupRetryCount < 0 || ProxyHostLookupRetryCount > 100) ProxyHostLookupRetryCount = 0; } else if (strsame (FieldName, "ProxyCacheFileKBytesMax", -1)) ProxyCacheFileKBytesMax = atoi(FieldValue); else if (strsame (FieldName, "ProxyCacheReloadList", -1)) { zptr = (sptr = ProxyCacheReloadList) + sizeof(ProxyCacheReloadList); for (cptr = FieldValue; *cptr && sptr < zptr; *sptr++ = *cptr++); if (sptr >= zptr) { ErrorGeneralOverflow (rqptr, FI_LI); return; } *sptr = '\0'; ProxyCacheReloadListPtr = ProxyCacheReloadList; } else if (strsame (FieldName, "ProxyCacheRoutineHourOfDay", -1)) { if (isdigit(FieldValue[0])) ProxyCacheRoutineHourOfDay = atoi(FieldValue); else ProxyCacheRoutineHourOfDay = -1; } else if (strsame (FieldName, "ProxyCacheDeviceCheckMinutes", -1)) ProxyCacheDeviceCheckMinutes = atoi(FieldValue); else if (strsame (FieldName, "ProxyCacheDeviceMaxPercent", -1)) ProxyCacheDeviceMaxPercent = atoi(FieldValue); else if (strsame (FieldName, "ProxyCacheDevicePurgePercent", -1)) ProxyCacheDevicePurgePercent = atoi(FieldValue); else if (strsame (FieldName, "ProxyCacheNegativeSeconds", -1)) ProxyCacheNegativeSeconds = MetaConSetSeconds (NULL, FieldValue, 1); else if (strsame (FieldName, "ProxyCacheNoReloadSeconds", -1)) ProxyCacheNoReloadSeconds = MetaConSetSeconds (NULL, FieldValue, 1); else if (strsame (FieldName, "ProxyCachePurgeList", -1)) { zptr = (sptr = ProxyCachePurgeList) + sizeof(ProxyCachePurgeList); for (cptr = FieldValue; *cptr && sptr < zptr; *sptr++ = *cptr++); if (sptr >= zptr) { ErrorGeneralOverflow (rqptr, FI_LI); return; } *sptr = '\0'; ProxyCachePurgeListPtr = ProxyCachePurgeList; } else if (strsame (FieldName, "ProxyConnectPersistMax", -1)) ProxyConnectPersistMax = atoi(FieldValue); else if (strsame (FieldName, "ProxyConnectPersistSeconds", -1)) ProxyConnectPersistSeconds = MetaConSetSeconds (NULL, FieldValue, 1); else if (strsame (FieldName, "ProxyConnectTimeoutSeconds", -1)) ProxyConnectTimeoutSeconds = MetaConSetSeconds (NULL, FieldValue, 1); else if (strsame (FieldName, "ProxyReportLog", -1)) { if (TOUP(FieldValue[0]) == 'E') ProxyReportLog = true; else if (TOUP(FieldValue[0]) == 'D') ProxyReportLog = false; } else if (strsame (FieldName, "ProxyReportCacheLog", -1)) { if (TOUP(FieldValue[0]) == 'E') ProxyReportCacheLog = true; else if (TOUP(FieldValue[0]) == 'D') ProxyReportCacheLog = false; } else if (strsame (FieldName, "ProxyUnknownRequestFields", -1)) { if (TOUP(FieldValue[0]) == 'E') ProxyUnknownRequestFields = true; else if (TOUP(FieldValue[0]) == 'D') ProxyUnknownRequestFields = false; } else { /***********/ /* unknown */ /***********/ ErrorGeneral (rqptr, "Unknown query field.", FI_LI); return; } } if (MakeChanges) { ProxyCacheInitValues (); ProxyMaintInit (); ProxyNetInit (); ReportSuccess (rqptr, "Server !AZ new proxy values loaded.", ServerHostPort); } AdminEnd (rqptr); } /****************************************************************************/