2025-04-27 07:49:33 -04:00

540 lines
13 KiB
C++

// wtmsload.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "errcodes.h"
#include <Afxtempl.h>
#include "guidestore.h"
#include "services.h"
#include "channels.h"
#include "programs.h"
#include "schedules.h"
#include "tmsparse.h"
#include "servchan.h"
#include "progschd.h"
#include "wtmsload.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// Note!
//
// If this DLL is dynamically linked against the MFC
// DLLs, any functions exported from this DLL which
// call into MFC must have the AFX_MANAGE_STATE macro
// added at the very beginning of the function.
//
// For example:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // normal function body here
// }
//
// It is very important that this macro appear in each
// function, prior to any calls into MFC. This means that
// it must appear as the first statement within the
// function, even before any object variable declarations
// as their constructors may generate calls into the MFC
// DLL.
//
// Please see MFC Technical Notes 33 and 58 for additional
// details.
//
/////////////////////////////////////////////////////////////////////////////
// CWtmsloadApp
BEGIN_MESSAGE_MAP(CWtmsloadApp, CWinApp)
//{{AFX_MSG_MAP(CWtmsloadApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWtmsloadApp construction
CWtmsloadApp::CWtmsloadApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CWtmsloadApp object
CWtmsloadApp theApp;
/////////////////////////////////////////////////////////////////////////
//
// METHOD: InitProcessors
//
// PARAMETERS: [IN] VOID
//
// PURPOSE: Instantiates the guide data record processors (parsers)
//
// RETURNS: SUCCESS/FAILURE
//
/////////////////////////////////////////////////////////////////////////
//
ULONG CWtmsloadApp::InitProcessors(VOID)
{
ULONG ulRet = ERROR_FAIL;
// Open the processors
//
// TODO: Exeception handler
//
m_DataFile = new CDataFileProcessor;
if (NULL == m_DataFile)
{
goto Open_Exit;
}
m_srpHeaders = new CHeaderRecordProcessor;
if (NULL == m_srpHeaders)
{
goto Open_Exit;
}
m_scrpStatChans = new CStatChanRecordProcessor;
if (NULL == m_scrpStatChans)
{
goto Open_Exit;
}
m_etEpTs = new CEpisodeTimeSlotRecordProcessor;
if (NULL == m_etEpTs)
{
goto Open_Exit;
}
ulRet = INIT_SUCCEEDED;
Open_Exit:
return ulRet;
}
/////////////////////////////////////////////////////////////////////////
//
// METHOD: CloseProcessors
//
// PARAMETERS: [IN] VOID
//
// PURPOSE: Frees the guide data record processors (parsers)
//
// RETURNS: SUCCESS/FAILURE
//
/////////////////////////////////////////////////////////////////////////
//
void CWtmsloadApp::CloseProcessors(VOID)
{
// close the processors
//
// TODO: Exeception handler
//
if (NULL != m_DataFile)
{
delete m_DataFile;
m_DataFile = NULL;
}
if (NULL != m_scrpStatChans)
{
delete m_scrpStatChans;
m_scrpStatChans = NULL;
}
if (NULL != m_srpHeaders)
{
delete m_srpHeaders;
m_srpHeaders = NULL;
}
if (NULL != m_etEpTs)
{
delete m_etEpTs;
m_etEpTs = NULL;
}
}
/////////////////////////////////////////////////////////////////////////
//
// METHOD: OpenGuideStore
//
// PARAMETERS: [IN] lpGuideStoreDB - the Guide Store DB File
//
// PURPOSE: Opens the Guide Store -
//
// RETURNS: SUCCESS/FAILURE
//
/////////////////////////////////////////////////////////////////////////
//
ULONG CWtmsloadApp::OpenGuideStore(LPCTSTR lpGuideStoreDB)
{
return m_gsp.Init(lpGuideStoreDB);
}
/////////////////////////////////////////////////////////////////////////
//
// METHOD: GetGuideStoreInterfaces
//
// PARAMETERS: [IN] VOID
//
// PURPOSE: Gets all the Guide Store Interfaces needed by the loader
// to import guide data into the store
// 1. Initializes Services collection and related props
// 2. Initializes ChannelLineups collection and related props
// 3. Initializes Programs collection and related props
// 4. Initializes ScheduleEntries collection and related props
// NOTE: The Channels collection and related properties
// are initialized afer the ChannelLineup has been set
// (tmsparse.cpp)
//
// RETURNS: SUCCESS/FAILURE
//
/////////////////////////////////////////////////////////////////////////
//
ULONG CWtmsloadApp::GetGuideStoreInterfaces(VOID)
{
IGuideStorePtr pGuideStore = m_gsp.GetGuideStorePtr();
ULONG ulRet = ERROR_FAIL;
if (NULL != pGuideStore)
{
// Initialize the services collection
//
ulRet = m_pgsServices.Init(pGuideStore);
if (INIT_SUCCEEDED != ulRet)
{
goto Get_Exit;
}
// Initialize the ChannelLineups collection
//
ulRet = m_pgsChannelLineups.Init(pGuideStore);
if (INIT_SUCCEEDED != ulRet)
{
goto Get_Exit;
}
// Initialize the Programs collection
//
ulRet = m_pgsPrograms.Init(pGuideStore);
if (INIT_SUCCEEDED != ulRet)
{
goto Get_Exit;
}
// Initialize the ScheduleEntries collection
//
ulRet = m_pgsScheduleEntries.Init(pGuideStore);
if (INIT_SUCCEEDED != ulRet)
{
goto Get_Exit;
}
}
Get_Exit:
return ulRet;
}
/////////////////////////////////////////////////////////////////////////
//
// METHOD: Init
//
// PARAMETERS: [IN] lpGuideStoreDB - Guide Store DB File
//
// PURPOSE: Performs initializations for the import
// 1. Setups the timezone adjustments
// 2. Opens the Guide data file processors (parsers)
// 3. Opens the guide store
// 4. Sets the Guide store interfaces
//
// RETURNS: SUCCESS/FAILURE
//
/////////////////////////////////////////////////////////////////////////
//
ULONG CWtmsloadApp::InitImport(LPCTSTR lpGuideStoreDB)
{
ULONG ulRet = ERROR_FAIL;
TIME_ZONE_INFORMATION tzi;
DWORD tzrc;
// incoming data is all gmt. set up app class time info
// for conversions
//
tzrc = ::GetTimeZoneInformation(&tzi);
CTimeSpan bias(0, 0, tzi.Bias, 0);
switch (tzrc)
{
case TIME_ZONE_ID_UNKNOWN:
#ifdef _DEBUG
afxDump << "Time Zone Info not set on this machine.\r\nAll db times will be in UTC\r\n";
#endif
break;
case TIME_ZONE_ID_DAYLIGHT:
{
CTimeSpan temp(0, 0, tzi.DaylightBias, 0);
bias += temp;
}
break;
case TIME_ZONE_ID_STANDARD:
{
CTimeSpan temp(0, 0, tzi.StandardBias, 0);
bias += temp;
}
break;
default:
return 1;
break;
}
// Set the time zone adjustments
//
m_odtsTimeZoneAdjust.SetDateTimeSpan(bias.GetDays(), bias.GetHours(), bias.GetMinutes(), bias.GetSeconds());
// Guide store Start time - init to invalid
//
m_codtGuideStartTime.SetStatus(COleDateTime::invalid);
// Guide store End time - init to invalid
//
m_codtGuideEndTime.SetStatus(COleDateTime::invalid);
// Open the guide data file parsers
//
ulRet = InitProcessors();
if (INIT_SUCCEEDED != ulRet)
{
goto INIT_EXIT;
}
// Open the guide store
//
ulRet = OpenGuideStore(lpGuideStoreDB);
if (INIT_SUCCEEDED == ulRet)
{
// Get the guide store interfaces
//
ulRet = GetGuideStoreInterfaces();
}
INIT_EXIT:
return ulRet;
}
void CWtmsloadApp::ExitImport(void)
{
// Cleanup Processing data objects
//
CloseProcessors();
}
ULONG CWtmsloadApp::ProcessInput(LPCTSTR lpGuideDataFile)
{
ULONG ulRet = IMPORT_SUCCEEDED;
CDataFileProcessor cdfGuideDataProcessor;
// TODO: Profile
COleDateTime m_odtStart(COleDateTime::GetCurrentTime());
m_covNow = m_odtStart + m_odtsTimeZoneAdjust;
HANDLE hFile = CreateFile(lpGuideDataFile, GENERIC_READ, 0,
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
#ifdef _DEBUG
afxDump << "\r\nCreateFile failed: " << GetLastError() << "\r\n";
#endif
return ERROR_FILE_OPEN;
}
// Try to get the file's modification time. If we can't then just use
// the current time
FILETIME ftModificationTime;
if (GetFileTime(hFile, NULL, NULL, &ftModificationTime))
{
CTime ctModificationTime = CTime(ftModificationTime);
}
else
{
CTime ctCurrentTime = CTime::GetCurrentTime();
#ifdef _DEBUG
afxDump << "\r\nGetFileTime failed: " << GetLastError() << "\r\n";
#endif
}
HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
SYSTEM_INFO si;
GetSystemInfo(&si);
BYTE *pbFile = NULL;
DWORD dwBytesInBlock = 0;
int nUpdateErr = ERROR_FAIL;
// TODO: Profile
if (hFileMapping == NULL)
{
// do regular I/O
BOOL fReadResult;
pbFile = new BYTE[si.dwAllocationGranularity];
do
{
// Attempt to read the file
//
fReadResult = ReadFile(hFile, pbFile,
si.dwAllocationGranularity, &dwBytesInBlock, NULL);
#ifdef _DUMP_LOADER
wsprintf(szDiagBuff, "Writing Guide Data: %d\r\n", dwBytesInBlock);
if (NULL != hDiagFile)
{
WriteFile(hDiagFile, szDiagBuff, lstrlen(szDiagBuff), &dwBytesWritten, 0);
}
#endif
if (0 < dwBytesInBlock)
{
// Parse the guide data file and update the store
//
nUpdateErr = cdfGuideDataProcessor.m_Process((LPCTSTR) pbFile, dwBytesInBlock);
if (STATE_RECORDS_FAIL == nUpdateErr)
{
ulRet = ERROR_STORE_UPDATE;
break;
}
}
}
while (fReadResult && dwBytesInBlock);
delete[] pbFile;
}
else
{
// do memory-mapped file I/O
DWORD dwFileSizeHigh;
__int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
qwFileSize += (((__int64) dwFileSizeHigh) << 32);
__int64 qwFileOffset = 0;
while (0 < qwFileSize)
{
if (qwFileSize < si.dwAllocationGranularity)
dwBytesInBlock = (DWORD) qwFileSize;
else
dwBytesInBlock = si.dwAllocationGranularity;
pbFile = (BYTE *) MapViewOfFile(hFileMapping, FILE_MAP_READ,
(DWORD) (qwFileOffset >> 32),
(DWORD) (qwFileOffset & 0xFFFFFFFF),
dwBytesInBlock);
if (NULL != pbFile)
{
#ifdef _DUMP_LOADER
wsprintf(szDiagBuff, "Writing Guide Data: %d\r\n", dwBytesInBlock);
if (NULL != hDiagFile)
{
WriteFile(hDiagFile, szDiagBuff, lstrlen(szDiagBuff), &dwBytesWritten, 0);
}
#endif
// Parse the guide data file and update the store
//
nUpdateErr = cdfGuideDataProcessor.m_Process((LPCTSTR) pbFile, dwBytesInBlock);
if (STATE_RECORDS_FAIL == nUpdateErr)
{
ulRet = ERROR_STORE_UPDATE;
break;
}
UnmapViewOfFile(pbFile);
}
qwFileOffset += dwBytesInBlock;
qwFileSize -= dwBytesInBlock;
}
CloseHandle(hFileMapping);
}
// TODO: Profile
CloseHandle(hFile);
// TODO: Profile
return ulRet;
}
/////////////////////////////////////////////////////////////////////////
//
// METHOD: ImportProgramListings
//
// PARAMETERS: [IN] lpGuideDataFile - The input guide data file
// [IN] lpGuideStoreDB - The Guide Store DB file
//
// PURPOSE: ImportProgramListings Performs the following tasks:
// 1. Initializes the import by opening the GuideStore
// and setting up all the primary interfaces
// 2. Starting the import of the guide data file into the
// GuideStore
//
// RETURNS: SUCCESS/FAILURE
//
/////////////////////////////////////////////////////////////////////////
//
ULONG ImportProgramListings(LPCTSTR lpGuideDataFile, LPCTSTR lpGuideStoreDB)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ULONG ulRet = S_OK;
if (NULL == lpGuideDataFile)
{
return ERROR_INVALID_PARAMETER;
}
// Initialize the import
//
ulRet = theApp.InitImport(lpGuideStoreDB);
if (INIT_SUCCEEDED == ulRet)
{
// Import all the program guide records into the
// guide store
//
ulRet = theApp.ProcessInput(lpGuideDataFile);
}
return ulRet;
}