NT4/private/windows/spooler/localspl/sizethrd.c
2020-09-30 17:12:29 +02:00

220 lines
5.9 KiB
C

/*++
Copyright (c) 1994 - 1995 Microsoft Corporation
Module Name:
sizethrd.c
Abstract:
The NT server share for downlevel jobs does not set the size whilst
spooling. The SizeDetectionThread periodically wakes walks all the
actively spooling jobs and if necessary updates the size.
Author:
Matthew Felton (mattfe) May 1994
Revision History:
--*/
#include <precomp.h>
#define SIZE_THREAD_WAIT_PERIOD 2.5*1000 // period size thread sleeps
// for polling file sizes
VOID
SizeDetectionThread(
PINISPOOLER pIniSpooler
);
VOID
CheckSizeDetectionThread(
PINISPOOLER pIniSpooler
)
{
DWORD ThreadId;
SplInSem();
if ( ( pIniSpooler->hSizeDetectionThread == INVALID_HANDLE_VALUE ) ||
( pIniSpooler->hSizeDetectionThread == NULL )) {
pIniSpooler->hSizeDetectionThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)SizeDetectionThread,
pIniSpooler,
0,
&ThreadId);
}
}
VOID
SizeDetectionThread(
PINISPOOLER pIniSpooler
)
{
PINIPRINTER pIniPrinter = NULL;
PINIJOB pIniJob = NULL;
PINIJOB pIniNextJob;
WCHAR szFileName[MAX_PATH];
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwFileSize = 0;
DWORD dwOldSize = 0;
BOOL bJobsSpooling = TRUE;
EnterSplSem();
//
// Outer Loop
// This thread stays active until there are no more jobs spooling
//
while ( ( pIniSpooler->hSizeDetectionThread != INVALID_HANDLE_VALUE ) &&
( pIniSpooler->pIniPrinter != NULL ) &&
( bJobsSpooling ) ) {
bJobsSpooling = FALSE;
//
// Middle Loop
// Walk printers
//
pIniPrinter = pIniSpooler->pIniPrinter;
while ( pIniPrinter != NULL ) {
//
// Inner Loop
// Walk all Jobs looking for a Spooling Job
//
pIniJob = pIniPrinter->pIniFirstJob;
INCPRINTERREF(pIniPrinter);
while (pIniJob) {
INCJOBREF(pIniJob);
SplInSem();
if ((pIniJob->Status & JOB_SPOOLING) &&
(pIniJob->Status & JOB_TYPE_ADDJOB)) {
bJobsSpooling = TRUE;
GetFullNameFromId (pIniPrinter,
pIniJob->JobId,
TRUE,
szFileName,
FALSE);
// Increment the reference count so the IniJob doesn't
// go away whilst we are outside CriticalSection
SPLASSERT( pIniJob->signature == IJ_SIGNATURE );
SPLASSERT( pIniPrinter->signature == IP_SIGNATURE );
LeaveSplSem();
SplOutSem();
dwFileSize = 0;
hFile = CreateFile(szFileName, 0, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if ( hFile != INVALID_HANDLE_VALUE ) {
dwFileSize = GetFileSize( hFile, 0 );
CloseHandle( hFile );
}
EnterSplSem();
SplInSem();
SPLASSERT( pIniJob->signature == IJ_SIGNATURE );
if ( pIniJob->Size < dwFileSize ) {
dwOldSize = pIniJob->Size;
pIniJob->Size = dwFileSize;
//
// Wait until Jobs reach our size threshold before
// we schedule them.
//
if (( dwOldSize < dwFastPrintSlowDownThreshold ) &&
( dwFileSize >= dwFastPrintSlowDownThreshold ) &&
( pIniJob->WaitForWrite == INVALID_HANDLE_VALUE )) {
CHECK_SCHEDULER();
}
SetPrinterChange(pIniPrinter,
pIniJob,
NVSpoolJob,
PRINTER_CHANGE_WRITE_JOB,
pIniPrinter->pIniSpooler);
// Support for despooling whilst spooling
// for Down Level jobs
if (pIniJob->WaitForWrite != INVALID_HANDLE_VALUE)
SetEvent( pIniJob->WaitForWrite );
}
}
pIniNextJob = pIniJob->pIniNextJob;
DECJOBREF(pIniJob);
//
// We must protect pIniNextJob immediately,
// since we will may leave critical section in
// DeleteJobCheck (it may call DeleteJob). While out
// of critical section, pIniNextJob may be deleted,
// causing it's next pointer to be bogus. We'll AV
// after we try and process it.
//
if (pIniNextJob) {
INCJOBREF(pIniNextJob);
}
DeleteJobCheck(pIniJob);
if (pIniNextJob) {
DECJOBREF(pIniNextJob);
}
pIniJob = pIniNextJob;
}
DECPRINTERREF(pIniPrinter);
pIniPrinter = pIniPrinter->pNext;
}
LeaveSplSem();
Sleep( (DWORD)SIZE_THREAD_WAIT_PERIOD );
EnterSplSem();
}
SplInSem();
CloseHandle ( pIniSpooler->hSizeDetectionThread );
pIniSpooler->hSizeDetectionThread = INVALID_HANDLE_VALUE;
LeaveSplSem();
ExitThread( 0 );
}