Check if a date log collection has been modified
DateLogHandleHasChanged queries whether a date log collection has been modified since its creation or last reset. This function is commonly used to determine if the underlying date log file needs to be persisted to disk or if the collection has been updated with new dates or merged data.
This function enables applications to:
LoadDateLogHandle(), MergeDateLogHandle(), or GenerateDateItemRangeCore()BOOL _Check_return_ DateLogHandleHasChanged(
_In_ DATE_COLLECTION_HANDLE hDateLogHandle
);
Standard C calling convention. The function is exported via MDTSAPI macro.
_Check_return_ - Return value must be inspected by caller_In_ - Input parameter; must not be modifiedDATE_COLLECTION_HANDLE - Generic handle type (accepts DATE_LOG_HANDLE, DATE_RANGE_HANDLE, or HOLIDAYS_HANDLE)[In] DATE_COLLECTION_HANDLE
Handle to the date collection to query for changes.
InitializeDateLogHandle()NewDateLogHandle()GetDateLogHolidayHandle()LoadDateLogHandle()GenerateDateItemRangeCore()MergeDateLogHandle()Returned when:
hDateLogHandle is NULL
// Recommended usage pattern
DATE_LOG_HANDLE hLog = /* ... */;
if (DateLogHandleHasChanged(hLog)) {
// Collection has been modified
printf("Date log has changes that need persistence\n");
// Example: Save to file
// hr = SaveDateLogToFile(hLog, "mylog.dat");
} else {
// No changes detected
printf("Date log is unchanged; no save needed\n");
}
The internal bHasChanged flag is set to TRUE by:
When a new date collection handle is created via InitializeDateLogHandle(),
the bHasChanged flag is initialized to FALSE. The handle is considered "clean"
until data is loaded or modified.
DATE_CONTEXT)DuplicateDateLogHandle() share the same stateThis function performs minimal validation:
hDateLogHandle is NULL (returns FALSE if so)IsValidDateLogHandle()
before DateLogHandleHasChanged() if the handle comes from untrusted sources
or if handle validity is uncertain.
// Load a date log from file
DATE_LOG_HANDLE hLog = NULL;
HRESULT hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hLog, HandleIsForDatelog);
if (SUCCEEDED(hr)) {
hr = LoadDateLogHandle(pFileInfo, NULL, NULL, hLog, NULL, 0);
if (SUCCEEDED(hr)) {
// Check if loading resulted in changes
if (DateLogHandleHasChanged(hLog)) {
printf("Loaded %d dates from file\n", GetDateCollectionLength(hLog));
}
}
CloseDateLogHandle(hLog);
}
// Optimize file I/O based on change status
void OptimizeDateLogPersistence(DATE_LOG_HANDLE hLog, const char* filepath)
{
if (DateLogHandleHasChanged(hLog)) {
printf("Changes detected; writing to %s...\n", filepath);
// TODO: Implement file write
// HRESULT hr = WriteDateLogToFile(hLog, filepath);
} else {
printf("No changes; skipping file write for %s\n", filepath);
}
}
// Usage
OptimizeDateLogPersistence(hMyLog, "market_dates.bin");
// Monitor state through multiple operations
DATE_LOG_HANDLE hLog = /* initialized */;
printf("Initial state: %s\n", DateLogHandleHasChanged(hLog) ? "Changed" : "Clean");
// Output: Clean
// Load data
hr = LoadDateLogHandle(pFileInfo, NULL, NULL, hLog, NULL, 0);
printf("After load: %s\n", DateLogHandleHasChanged(hLog) ? "Changed" : "Clean");
// Output: Changed
// Merge additional data
hr = MergeDateLogHandle(hLog, hSourceRange, DATE_RANGE_MERGE_FAVOR_SOURCE);
printf("After merge: %s\n", DateLogHandleHasChanged(hLog) ? "Changed" : "Clean");
// Output: Changed
// Implement a "save-only-if-changed" pattern
HRESULT UpdateAndSaveDateLog(DATE_LOG_HANDLE hLog, PFILE_CONTEXT pNewData)
{
HRESULT hr = S_OK;
// Record initial state
BOOL bInitiallyChanged = DateLogHandleHasChanged(hLog);
// Perform updates
hr = LoadDateLogHandle(pNewData, NULL, NULL, hLog, NULL, 0);
if (FAILED(hr)) {
return hr;
}
// Only save if changes occurred during this operation
if (!bInitiallyChanged && DateLogHandleHasChanged(hLog)) {
printf("New changes detected; persisting to disk...\n");
// hr = PersistDateLogToDisk(hLog);
}
return hr;
}
This function is thread-safe for read operations:
bHasChanged flag is read from the shared context| Pitfall | Impact | Mitigation |
|---|---|---|
| Not checking return value | Silent logic errors in persistence logic | Always use if statement or ternary operator |
| Ignoring NULL returns | Incorrect change detection with invalid handles | Validate handle before calling; function returns FALSE safely |
| Race conditions (multi-threaded) | State may change between check and use | Use atomic operations or synchronize caller's logic |
| Assuming state is reset | Stale state prevents re-saves | No reset function; create new handle if needed |
DATE_COLLECTION_HANDLE (generic void pointer)bHasChanged = TRUE on successbHasChanged = TRUE after mergebHasChanged = FALSEbHasChanged with source handle