DateLogHandleHasChanged

Check if a date log collection has been modified

Overview

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.

Purpose

This function enables applications to:

Key Characteristics

Function Signature

BOOL _Check_return_ DateLogHandleHasChanged(
    _In_ DATE_COLLECTION_HANDLE hDateLogHandle
);

Calling Convention

Standard C calling convention. The function is exported via MDTSAPI macro.

SAL Annotations

Parameters

hDateLogHandle

[In] DATE_COLLECTION_HANDLE

Handle to the date collection to query for changes.

  • Can be a DATE_LOG_HANDLE obtained from InitializeDateLogHandle()
  • Can be a DATE_RANGE_HANDLE created via NewDateLogHandle()
  • Can be a HOLIDAYS_HANDLE from GetDateLogHolidayHandle()
  • Should represent a valid collection (recommended: validate before calling)
  • If NULL or invalid, function safely returns FALSE

Return Values

Return Value Semantics

TRUE - The date collection has been modified since creation or last operation
  • New dates were added via LoadDateLogHandle()
  • Dates were generated via GenerateDateItemRangeCore()
  • Data was merged via MergeDateLogHandle()
  • File persistence is recommended if changes should be saved

FALSE Cases

FALSE - No changes detected

Returned when:

Return Value Checking Pattern


// 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");
}
            

Behavior and State Management

State Tracking Diagram

Initialize Handle
bHasChanged = FALSE


Load/Generate/Merge
bHasChanged = TRUE


Query Status
Return TRUE/FALSE

When bHasChanged is Set to TRUE

The internal bHasChanged flag is set to TRUE by:

  1. LoadDateLogHandle(): After successfully parsing a date log file or generating a date range
  2. MergeDateLogHandle(): After successfully merging source dates into destination
  3. GenerateDateItemRangeCore(): After generating dates within a specified range

Initial State

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.

State Persistence

Handle Validation

This function performs minimal validation:

Recommendation: Consider calling IsValidDateLogHandle() before DateLogHandleHasChanged() if the handle comes from untrusted sources or if handle validity is uncertain.

Usage Examples

Example 1: Check After Loading File


// 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);
}
            

Example 2: Determine File Persistence Strategy


// 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");
            

Example 3: Track Changes Across Operations


// 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
            

Example 4: Transactional Pattern with Change Detection


// 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;
}
            

Remarks and Best Practices

Thread Safety

This function is thread-safe for read operations:

Performance Considerations

Common Pitfalls

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

API Contract Notes

Important:
  • The function parameter is typed as DATE_COLLECTION_HANDLE (generic void pointer)
  • Accepts DATE_LOG_HANDLE, DATE_RANGE_HANDLE, or HOLIDAYS_HANDLE
  • All three types share the same underlying context structure
  • Return value indicates whether ANY changes occurred to the collection

Integration with Other Functions