Using the Paging Methods
The ICluster interface contains several methods that let you page through the output that the method generates. These methods are useful if the method might generate a large volume of output and you want to present the data in a user interface as it is generated, instead of waiting until all the data is returned.
The following ICluster methods provide paging:
- ExecuteCommandWithPaging
- ListAllJobsWithPaging
- ListJobsWithPaging
- ListTasksWithPaging
- WaitForCommandWithPaging
The paging methods are meant to be called in a loop. The first call takes a snapshot of the output and returns the first page of the output. For ListAllJobsWithPaging, ListJobsWithPaging, and ListTasksWithPaging, be sure to set the Timestamp and Version parameters to NULL on the first call and do not change their values on subsequent calls. The loop ends when the enumerable object is empty.
To reset the enumerable object to the beginning, set Timestamp to NULL and leave the Version value unchanged.
For the methods that list jobs and tasks, you can set Version to NULL and leave the Timestamp value unchanged to get jobs or tasks that were added or whose state has changed since the last snapshot.
The following example shows how to use the ListAllJobsWithPaging method to list all jobs in the cluster.
#define PAGE_SIZE 500 // Number of jobs to return in each page
long g_JobCount = 0; // Counts the total number of jobs returned
ListAllJobsInCluster(pCluster, PAGE_SIZE);
wprintf(L"Total number of jobs, %d\n", g_JobCount);
// List all jobs in the cluster. Use the specified page size to
// page through the results.
void ListAllJobsInCluster(ICluster* pCluster, long PageSize)
{
HRESULT hr = S_OK;
IClusterEnumerable* pJobsCollection = NULL;
IEnumVARIANT* pJobs = NULL;
VARIANT vTimestamp;
VARIANT vVersion;
BOOL fMoreJobs = TRUE;
VariantInit(&vTimestamp);
VariantInit(&vVersion);
while (fMoreJobs)
{
hr = pCluster->ListAllJobsWithPaging(VARIANT_FALSE, &vTimestamp, &vVersion, PageSize, &pJobsCollection);
if (FAILED(hr))
{
wprintf(L"pCluster->ListAllJobs failed.\n");
goto cleanup;
}
hr = pJobsCollection->GetEnumerator(&pJobs);
if (SUCCEEDED(hr))
{
fMoreJobs = ProcessJobs(pJobs);
pJobs->Release();
pJobs = NULL;
pJobsCollection->Release();
pJobsCollection = NULL;
}
else
{
wprintf(L"pJobsCollection->GetEnumerator failed.\n");
goto cleanup;
}
}
cleanup:
if (pJobsCollection)
pJobsCollection->Release();
VariantClear(&vTimestamp);
VariantClear(&vVersion);
return;
}
// Process each job in the collection.
BOOL ProcessJobs(IEnumVARIANT* pJobs)
{
HRESULT hr = S_OK;
IJob* pJob = NULL;
VARIANT var;
long count = 0;
VariantInit(&var);
while (hr = pJobs->Next(1, &var, NULL) == S_OK)
{
count++; // Used to determine whether the collection is empty.
var.pdispVal->QueryInterface(IID_IJob, reinterpret_cast<void **> (&pJob));
// Do something with the job.
pJob->Release();
pJob = NULL;
VariantClear(&var);
}
g_JobCount += count; // Add to global total job count
return (count) ? TRUE : FALSE; // If FALSE, all pages returned
}
// Set pageSize to an appropriate value for your use. The value
// indicates the number of jobs to return with each page.
int pageSize = 100;
bool hasJobs = true;
object timestamp = null;
object version = null;
while (hasJobs)
{
hasJobs = false;
foreach (IJob job in cluster.ListAllJobsWithPaging(false, ref timestamp, ref version, pageSize))
{
Console.WriteLine(job.Name);
foreach (ITask task in job)
{
if (string.IsNullOrEmpty(task.Name))
Console.WriteLine("\t" + task.Id);
else
Console.WriteLine("\t" + task.Id);
}
hasJobs = true;
}
Console.WriteLine();
}