in src/Storage/SQLiteLocalStorage.cs [503:576]
public void ConditionallyPutRecords(String identityId, String datasetName, List<Record> records, List<Record> localRecords)
{
/*
* Grab an instance of the record from the local store with the remote change's
* key and the snapshot version.
* 1) If both are null the remote change is new and we should save.
* 2) If both exist but the value has changed locally we shouldn't overwrite with the remote changes,
* which will still exist in remote, but should update the sync count to avoid a false-conflict later.
* 3) If both exist and the values have not changed, we should save the remote change.
* 4) If the current check exists but it wasn't in the snapshot, we should save.
*/
Dictionary<string, Record> localRecordMap = new Dictionary<string, Record>();
foreach (Record record in localRecords)
{
localRecordMap[record.Key] = record;
}
foreach (Record record in records)
{
Record oldDatabaseRecord;
localRecordMap.TryGetValue(record.Key, out oldDatabaseRecord);
// locking to ensure that database is not changed between GetRecord and UpdateOrInsertRecord
lock (sqlite_lock)
{
Record databaseRecord = this.GetRecord(identityId, datasetName, record.Key);
if (databaseRecord != null && oldDatabaseRecord != null)
{
if (databaseRecord.SyncCount != oldDatabaseRecord.SyncCount
|| !string.Equals(databaseRecord.LastModifiedBy, oldDatabaseRecord.LastModifiedBy))
{
continue;
}
if (!string.Equals(databaseRecord.Value, oldDatabaseRecord.Value))
{
if (string.Equals(record.Value, oldDatabaseRecord.Value))
{
// The value has changed, so this is a local change during the push record operation.
// Avoid a future conflict by updating the metadata so that it looks like the modifications that
// occurred during the put record operation happened after the put operation completed.
Record resolvedRecord =
new Record(
record.Key,
databaseRecord.Value,
record.SyncCount,
record.LastModifiedDate,
record.LastModifiedBy,
databaseRecord.DeviceLastModifiedDate,
true
);
UpdateOrInsertRecord(identityId, datasetName, resolvedRecord);
}
else
{
continue;
}
}
else
{
UpdateOrInsertRecord(identityId, datasetName, record);
}
}
else
{
UpdateOrInsertRecord(identityId, datasetName, record);
}
}
}
}