📄 filereaderthread.cpp
字号:
bUseTimeout = TRUE;
}
else
{
fch = FindFirstChangeNotification (szNewPath, FALSE, FILE_NOTIFY_CHANGE_SIZE);
// fch = FindFirstChangeNotification (szNewPath, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);
if (fch == INVALID_HANDLE_VALUE)
{
LogMessage ("Could not register file change notification on '%s'. "
"The file may not be on a local filesystem - using polling to "
"detect file changes.", parms->szFileName);
bUseTimeout = FALSE;
}
else
{
LogMessage ("Using file change notification on '%s' to detect file changes. (fch = %08x)", parms->szFileName, fch);
}
}
if (!(hDie = OpenEvent (EVENT_ALL_ACCESS, FALSE, parms->szDieEvent)))
{
hDie = CreateEvent (NULL, TRUE, FALSE, parms->szDieEvent);
}
if (hDie == NULL)
{
LogDebugMessage ("CreateEvent (hDie) failed");
}
else
{
LogMessage ("Debug: CreateEvent (hDie) succeeded");
}
if (!(hReload = OpenEvent (EVENT_ALL_ACCESS, FALSE, parms->szReloadEvent)))
{
hReload = CreateEvent (NULL, TRUE, FALSE, parms->szReloadEvent);
}
if (hReload == NULL)
{
LogDebugMessage ("CreateEvent (hReload) failed");
}
else
{
LogMessage ("Debug: CreateEvent (hReload) succeeded");
}
#ifndef NO_HANDLER_THREAD
// Create the handler thread.
memset (&stFileHandlerParams, 0, sizeof (FILE_HANDLER_PARAMS));
stFileHandlerParams.pView = pView;
stFileHandlerParams.pdwOldFileSize = &dwOldFileSize;
stFileHandlerParams.pdwNewFileSize = &dwNewFileSize;
sprintf (stFileHandlerParams.szDieEvent, "HANDLER_%s_DIE", parms->szDieEvent);
sprintf (stFileHandlerParams.szGoEvent, "HANDLER_%s_GO", parms->szDieEvent);
stFileHandlerParams.pbFirst = &bFirst;
stFileHandlerParams.pbIgnoreHotStartup = &bIgnoreHotStartup;
stFileHandlerParams.hwndEdit = parms->hEdit;
strcpy (stFileHandlerParams.szFileName, parms->szFileName);
if (!AfxBeginThread ((AFX_THREADPROC) FileHandlerThread, (LPVOID) &stFileHandlerParams))
{
LogMessage ("Could not create handler thread.");
::AfxMessageBox ("Could not create handler thread.");
return 1;
}
#endif // #ifndef NO_HANDLER_THREAD
bDebug = parms->bDebug;
bPaused = parms->bPaused;
nTimeout = parms->nTimeout;
hwndEdit = parms->hEdit;
strcpy (szFileName, parms->szFileName);
// Set up the wait event array.
haEvents[0] = hDie;
haEvents[1] = fch;
haEvents[2] = hReload;
// The main loop.
// Keep going 'til we get told to go away.
while (1)
{
if (!bFirst)
{
if (bUseTimeout)
{
// Use different array for non-local (polled) files.
haEvents[0] = hDie;
haEvents[1] = hReload;
dwRtn = WaitForMultipleObjects (2, haEvents, FALSE, nTimeout);
if (dwRtn == WAIT_FAILED)
{
LogDebugMessage ("WaitForMultipleObjects failed - returned %ld", dwRtn);
}
else if (dwRtn == WAIT_OBJECT_DIE)
{
LogDebugMessage ("WaitForMultipleObjects triggered from die event", dwRtn);
}
else if (dwRtn == WAIT_TIMEOUT)
{
LogMessage ("Debug: WaitForMultipleObjects triggered from polling interval timeout", dwRtn);
}
else if (dwRtn == WAIT_OBJECT_POLL_RELOAD)
{
LogMessage ("Debug: WaitForMultipleObjects triggered from keyword reload event", dwRtn);
ReloadKeywords (pView);
}
// We've been killed.
if (dwRtn == WAIT_OBJECT_DIE)
{
CloseHandle (hDie);
#ifndef NO_HANDLER_THREAD
// Kill the handler thread.
HANDLE hHandlerDie;
hHandlerDie = OpenEvent (EVENT_ALL_ACCESS, FALSE, stFileHandlerParams.szDieEvent);
// Release the threads and then reset the event automatically.
PulseEvent (hHandlerDie);
CloseHandle (hHandlerDie);
#endif // #ifndef NO_HANDLER_THREAD
return 0;
}
LogMessage ("Debug: WaitForSingleObject (polling) fired");
dwRtn = WAIT_OBJECT_FILEUPDATE;
}
else
{
LogMessage ("Debug: Waiting for file change...");
// Wait for the *directory* change or die event to occur.
dwRtn = WaitForMultipleObjects (3, haEvents, FALSE, INFINITE);
if (dwRtn == WAIT_FAILED)
{
LogDebugMessage ("WaitForMultipleObjects failed - returned %ld", dwRtn);
}
else
{
if (dwRtn == WAIT_OBJECT_DIE)
{
LogDebugMessage ("WaitForMultipleObjects triggered from die event", dwRtn);
}
else if (dwRtn == (WAIT_OBJECT_FILEUPDATE))
{
LogMessage ("Debug: WaitForMultipleObjects triggered from file wait event", dwRtn);
}
else if (dwRtn == (WAIT_OBJECT_RELOAD))
{
LogMessage ("Debug: WaitForMultipleObjects triggered from keyword reload event", dwRtn);
ReloadKeywords (pView);
}
}
}
switch (dwRtn)
{
case WAIT_TIMEOUT:
// Wait got bored, start waiting again.
if (bDebug)
{
LogMessage ("Debug: Wait timed out.");
}
continue;
case WAIT_OBJECT_DIE:
// We're dead.
LogMessage ("Debug: Received kill event.");
if (!bUseTimeout)
{
bRtn = FindCloseChangeNotification (fch);
if (bDebug)
{
if (!bRtn)
{
LogDebugMessage ("FindCloseChangeNotification failed - returned %ld", bRtn);
}
else
{
LogDebugMessage ("FindCloseChangeNotification returned %ld", bRtn);
}
}
}
bRtn = CloseHandle (hDie);
if (bDebug)
{
if (!bRtn)
{
LogDebugMessage ("CloseHandle (hDie) failed - returned %ld", bRtn);
}
else
{
LogDebugMessage ("CloseHandle (hDie) succeeded - returned %ld", bRtn);
}
}
#ifndef NO_HANDLER_THREAD
hHandlerDie = OpenEvent (EVENT_ALL_ACCESS, FALSE, stFileHandlerParams.szDieEvent);
// Release the threads and then reset the event automatically.
PulseEvent (hHandlerDie);
CloseHandle (hHandlerDie);
#endif // #ifndef NO_HANDLER_THREAD
return 0;
case WAIT_ABANDONED:
case WAIT_ABANDONED + 1:
::MessageBox (hwndEdit, "Wait abandoned!", "Tail for Win32", MB_OK | MB_ICONSTOP);
LogMessage ("Wait abandoned!");
if (!bUseTimeout)
{
FindCloseChangeNotification (fch);
}
CloseHandle (hDie);
return 1;
default:
LogMessage ("Debug: Received change event (or polled).");
break;
}
if ((dwRtn != WAIT_OBJECT_FILEUPDATE) && (dwRtn != WAIT_OBJECT_RELOAD))
{
LogDebugMessage ("WaitForMultipleObjects returned %ld. In a pickle.", dwRtn);
::MessageBox (hwndEdit, "WaitForMultipleObjects in a pickle!!", "Tail for Win32", MB_OK | MB_ICONSTOP);
if (!bUseTimeout)
{
FindCloseChangeNotification (fch);
}
CloseHandle (hDie);
return 1;
}
} /* End if (!bFirst) */
// Open the file we're interested in to see if it has changed size.
dwNewFileSize = GetFileSizeBytes (szFileName);
// Save away the old file size.
dwOldFileSize = dwFileSize;
// If the file has changed size, update the view.
if (dwNewFileSize != dwOldFileSize)
{
// Save the new size.
dwFileSize = dwNewFileSize;
LogMessage ("Debug: File has changed size (was %ld, now %ld)", dwOldFileSize, dwNewFileSize);
#ifndef NO_HANDLER_THREAD
hHandlerGo = OpenEvent (EVENT_ALL_ACCESS, FALSE, stFileHandlerParams.szGoEvent);
// Release the threads and then reset the event automatically.
PulseEvent (hHandlerGo);
CloseHandle (hHandlerGo);
#endif
#ifdef NO_HANDLER_THREAD
hFile = CreateFile (szFileName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ((hFile == INVALID_HANDLE_VALUE) && !bFileGone)
{
::AfxMessageBox ("Hmmm... Looks like the file has been deleted. I'll wait.");
bFileGone = TRUE;
UpdateStatusBar (pView, "Waiting for file...");
continue;
}
if (bFileGone)
{
// We're now here, so the file must have come back.
bFileGone = FALSE;
}
// Work out the size of the buffer needed to hold the changed lines.
// if (bFirst && bIgnoreHotStartup) // Warlock, commented out, changed below
if (bFirst) // Warlock, still load when bIgnoreHotStartup is on
{
// See if the file is larger than the maximum size.
// If so, only bite off the last few lines to save memory.
// PP: This logic will need to change for cases where the file has
// been truncated and the initial contents are still huge.
if (dwNewFileSize > dwMaxInitFileSize)
{
bLastChunk = TRUE;
dwBufferSize = dwInitFileSize;
}
else
{
// Org.
dwBufferSize = dwNewFileSize + 1;
}
}
else // Most times - just load the changed lines.
{
if (dwNewFileSize > dwOldFileSize)
{
dwBufferSize = (dwNewFileSize - dwOldFileSize) + 1;
}
else
{
// File has been truncated.
LogMessage ("Debug: File has been truncated.");
dwBufferSize = dwNewFileSize + 1;
// dwOldFileSize = 0;
dwChangeType = CHANGE_FULL;
}
}
LogMessage ("Debug: Allocating %ld bytes for buffer", dwBufferSize);
pszBuffer = (char*) malloc (dwBufferSize);
if (pszBuffer == NULL)
{
::MessageBox (AfxGetMainWnd()->GetSafeHwnd(), "Could not allocate memory for file!",
"Tail for Win32", MB_OK | MB_ICONSTOP);
CloseHandle (hDie);
if (!bUseTimeout)
{
bRtn = FindCloseChangeNotification (fch);
}
return 1;
}
memset ((void*) pszBuffer, 0, dwBufferSize);
if (bLastChunk)
{
DWORD rtn;
LogMessage ("Debug: File is larger than %ld, only reading last %ld bytes.", dwMaxInitFileSize, dwBufferSize);
rtn = SetFilePointer (hFile, 1 - dwBufferSize, NULL, FILE_END);
LogMessage ("Debug: File pointer now set to %ld", rtn);
}
else
{
if (bFirst && (dwNewFileSize > dwMaxInitFileSize))
{
LogMessage ("Debug: File is larger than %ld, only reading last %ld bytes.", dwMaxInitFileSize, dwBufferSize);
SetFilePointer (hFile, dwBufferSize, NULL, FILE_END);
}
else
{
if (dwNewFileSize < dwOldFileSize)
{
SetFilePointer (hFile, 0, NULL, FILE_BEGIN);
}
else
{
// Org.
SetFilePointer (hFile, dwOldFileSize, NULL, FILE_BEGIN);
}
}
}
bReadOK = ReadFile (hFile, (LPVOID) pszBuffer, dwBufferSize - 1, &dwBytesRead, NULL);
CloseHandle (hFile);
if (bReadOK)
{
if (bLastChunk)
{
GetChangedLines (pszBuffer, &pszNewLines, dwOldFileSize, dwBufferSize, &dwChangeType, FALSE);
bLastChunk = FALSE;
if (bFirst && (dwNewFileSize > dwMaxInitFileSize)) // Warlock, neat: skip/blank the chopped line.
{
pszNewLinesSkip = strchr( pszNewLines, '\n' );
LogMessage ("Debug: Skipping chopped line, jumping forward %ld Bytes.", pszNewLinesSkip - pszNewLines);
pszNewLines = pszNewLinesSkip;
}
}
else
{
if (dwNewFileSize < dwOldFileSize)
{
pszNewLines = pszBuffer;
}
else
{
// Org.
GetChangedLines (pszBuffer, &pszNewLines, dwOldFileSize, dwNewFileSize, &dwChangeType, FALSE);
}
}
// Clear the window down first.
if (dwChangeType == CHANGE_FULL)
{
::SetWindowText (hwndEdit, "");
}
bMatch = FALSE;
// Update the window, doing syntax highlighting, setting counters if matches found.
bUpdated = InsertText (pView, pszNewLines, !(bFirst && bIgnoreHotStartup), &lMatches, &bMatch);
}
free ((void*) pszBuffer);
#endif // #ifdef NO_HANDLER_THREAD
} // if (dwNewFileSize != dwOldFileSize)
if (!bUseTimeout)
{
bRtn = FindNextChangeNotification (fch);
if (!bRtn)
{
LogDebugMessage ("FindNextChangeNotification failed - returned %ld", bRtn);
}
else
{
LogMessage ("Debug: FindNextChangeNotification returned %ld", bRtn);
}
}
bFirst = FALSE;
} // Go back and wait for another change.
// Close the notification handle.
if (!bUseTimeout)
{
bRtn = FindCloseChangeNotification (fch);
if (bRtn)
{
LogMessage ("Final FindCloseChangeNotification returned %ld", bRtn);
}
else
{
LogDebugMessage ("Final FindCloseChangeNotification falied - returned %ld", bRtn);
}
}
CloseHandle (hDie);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -