qmgr: Add infrastructure for background file transferring.

This commit is contained in:
Dan Hipschman 2008-03-13 15:54:01 -07:00 committed by Alexandre Julliard
parent a7ebdf2eba
commit 374fea0a71
4 changed files with 82 additions and 3 deletions

View File

@ -139,6 +139,7 @@ static HRESULT WINAPI BITS_IBackgroundCopyJob_Resume(
&& This->state != BG_JOB_STATE_TRANSFERRING)
{
This->state = BG_JOB_STATE_QUEUED;
SetEvent(globalMgr.jobEvent);
}
LeaveCriticalSection(&globalMgr.cs);

View File

@ -130,6 +130,7 @@ static const IBackgroundCopyManagerVtbl BITS_IBackgroundCopyManager_Vtbl =
BackgroundCopyManagerImpl globalMgr = {
&BITS_IBackgroundCopyManager_Vtbl,
{ NULL, -1, 0, 0, 0, 0 },
NULL,
LIST_INIT(globalMgr.jobs)
};
@ -140,3 +141,59 @@ HRESULT BackgroundCopyManagerConstructor(IUnknown *pUnkOuter, LPVOID *ppObj)
*ppObj = (IBackgroundCopyManager *) &globalMgr;
return S_OK;
}
DWORD WINAPI fileTransfer(void *param)
{
BackgroundCopyManagerImpl *qmgr = &globalMgr;
HANDLE events[2];
events[0] = stop_event;
events[1] = qmgr->jobEvent;
for (;;)
{
BackgroundCopyJobImpl *job, *jobCur;
BOOL haveJob = FALSE;
/* Check if it's the stop_event */
if (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0)
return 0;
/* Note that other threads may add files to the job list, but only
this thread ever deletes them so we don't need to worry about jobs
magically disappearing from the list. */
EnterCriticalSection(&qmgr->cs);
LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
{
if (job->state == BG_JOB_STATE_ACKNOWLEDGED || job->state == BG_JOB_STATE_CANCELLED)
{
list_remove(&job->entryFromQmgr);
IBackgroundCopyJob_Release((IBackgroundCopyJob *) job);
}
else if (job->state == BG_JOB_STATE_QUEUED)
{
haveJob = TRUE;
break;
}
else if (job->state == BG_JOB_STATE_CONNECTING
|| job->state == BG_JOB_STATE_TRANSFERRING)
{
ERR("Invalid state for job %p: %d\n", job, job->state);
}
}
if (!haveJob)
ResetEvent(qmgr->jobEvent);
LeaveCriticalSection(&qmgr->cs);
if (haveJob)
{
FIXME("Actually process job %p; setting error state\n", job);
EnterCriticalSection(&qmgr->cs);
job->state = BG_JOB_STATE_ERROR;
LeaveCriticalSection(&qmgr->cs);
}
}
}

View File

@ -81,8 +81,9 @@ typedef struct
typedef struct
{
const IBackgroundCopyManagerVtbl *lpVtbl;
/* Protects job list and job states */
/* Protects job list, job states, and jobEvent */
CRITICAL_SECTION cs;
HANDLE jobEvent;
struct list jobs;
} BackgroundCopyManagerImpl;
@ -91,6 +92,7 @@ typedef struct
const IClassFactoryVtbl *lpVtbl;
} ClassFactoryImpl;
extern HANDLE stop_event;
extern ClassFactoryImpl BITS_ClassFactory;
extern BackgroundCopyManagerImpl globalMgr;
@ -104,6 +106,7 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
LPVOID *ppObj);
HRESULT EnumBackgroundCopyFilesConstructor(LPVOID *ppObj,
IBackgroundCopyJob* copyJob);
DWORD WINAPI fileTransfer(void *param);
/* Little helper functions */
static inline char *

View File

@ -28,10 +28,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
HANDLE stop_event = NULL;
static WCHAR qmgr_nameW[] = {'B','I','T','S',0};
static SERVICE_STATUS_HANDLE status_handle;
static SERVICE_STATUS status;
static HANDLE stop_event = NULL;
static VOID
UpdateStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
@ -108,6 +109,8 @@ StartCount(void)
VOID WINAPI
ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
{
HANDLE fileTxThread;
DWORD threadId;
TRACE("\n");
stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
@ -129,9 +132,24 @@ ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
return;
}
globalMgr.jobEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!globalMgr.jobEvent) {
ERR("Couldn't create event: error %d\n", GetLastError());
UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
return;
}
fileTxThread = CreateThread(NULL, 0, fileTransfer, NULL, 0, &threadId);
if (!fileTxThread)
{
ERR("Failed starting file transfer thread\n");
UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
return;
}
UpdateStatus(SERVICE_RUNNING, NO_ERROR, 0);
WaitForSingleObject(stop_event, INFINITE);
WaitForSingleObject(fileTxThread, INFINITE);
UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
CloseHandle(stop_event);
TRACE("service stoped\n");