public InfoFormat ( string messageFormat ) : void | ||
messageFormat | string | |
return | void |
/// <summary> /// Wipes all user data cached locally, including identity id, session /// credentials, dataset metadata, and all records. Any data that hasn't been /// synced will be lost. This method is usually used when customer logs out. /// <param name="wipeCredentialsAndID">Wipe Credentials and IdentityID. Defaults as true</param> /// </summary> public void WipeData(bool wipeCredentialsAndID = true) { Local.WipeData(); if (wipeCredentialsAndID) { cognitoCredentials.Clear(); _logger.InfoFormat("All datasets and records have been wiped"); } else { _logger.InfoFormat("All data has been wiped"); } }
/// <summary> /// Sends Mobile Analytics events to server on background thread. /// </summary> private static void DoWork() { while (true) { #if UNITY_EDITOR if (UnityInitializer.IsEditorPlaying && !UnityInitializer.IsEditorPaused) { #endif try { _logger.InfoFormat("Mobile Analytics Manager is trying to deliver events in background thread."); IDictionary <string, MobileAnalyticsManager> instanceDictionary = MobileAnalyticsManager.InstanceDictionary; foreach (string appId in instanceDictionary.Keys) { try { MobileAnalyticsManager manager = MobileAnalyticsManager.GetInstance(appId); manager.BackgroundDeliveryClient.AttemptDelivery(); } catch (System.Exception e) { _logger.Error(e, "An exception occurred in Mobile Analytics Delivery Client."); } } Thread.Sleep(Convert.ToInt32(AWSConfigsMobileAnalytics.BackgroundSubmissionWaitTime) * 1000); } catch (System.Exception e) { _logger.Error(e, "An exception occurred in Mobile Analytics Manager."); } #if UNITY_EDITOR } else if (!UnityInitializer.IsEditorPlaying) { _thread.Abort(); } #endif } }
private async Task RunSyncOperationAsync(int retry, CancellationToken cancellationToken) #endif { long lastSyncCount = Local.GetLastSyncCount(IdentityId, DatasetName); #if !(BCL35 || UNITY) ExceptionDispatchInfo capturedException = null; #endif // if dataset is deleted locally, push it to remote if (lastSyncCount == -1) { try { #if BCL35 || UNITY Remote.DeleteDataset(DatasetName); #else await Remote.DeleteDatasetAsync(DatasetName, cancellationToken).ConfigureAwait(false); #endif } catch (DatasetNotFoundException) { //Ignore the exception here, since the dataset was local only } catch (Exception e) { _logger.InfoFormat("{0} , dataset : {1}", e.Message, this.DatasetName); EndSynchronizeAndCleanup(); #if UNITY FireSyncFailureEvent(e, options); #else FireSyncFailureEvent(e); #endif return; } Local.PurgeDataset(IdentityId, DatasetName); _logger.InfoFormat("OnSyncSuccess: dataset delete is pushed to remote - {0}", this.DatasetName); EndSynchronizeAndCleanup(); #if UNITY FireSyncSuccessEvent(new List <Record>(), options); #else FireSyncSuccessEvent(new List <Record>()); #endif return; } // get latest modified records from remote _logger.InfoFormat("Get latest modified records since {0} for dataset {1}", lastSyncCount, this.DatasetName); DatasetUpdates datasetUpdates = null; try { #if BCL35 || UNITY datasetUpdates = Remote.ListUpdates(DatasetName, lastSyncCount); #else datasetUpdates = await Remote.ListUpdatesAsync(DatasetName, lastSyncCount, cancellationToken).ConfigureAwait(false); #endif } catch (Exception listUpdatesException) { _logger.Error(listUpdatesException, string.Empty); EndSynchronizeAndCleanup(); #if UNITY FireSyncFailureEvent(listUpdatesException, options); #else FireSyncFailureEvent(listUpdatesException); #endif return; } if (datasetUpdates != null && datasetUpdates.MergedDatasetNameList.Count != 0 && this.OnDatasetMerged != null) { bool resume = this.OnDatasetMerged(this, datasetUpdates.MergedDatasetNameList); if (resume) { if (retry == 0) { EndSynchronizeAndCleanup(); #if UNITY FireSyncFailureEvent(new SyncManagerException("Out of retries"), options); #else FireSyncFailureEvent(new SyncManagerException("Out of retries")); #endif } else { #if BCL35 this.RunSyncOperation(--retry); #elif UNITY this.RunSyncOperation(--retry, options); #else await this.RunSyncOperationAsync(--retry, cancellationToken).ConfigureAwait(false); #endif } return; } else { _logger.InfoFormat("OnSyncFailure: Manual Cancel"); EndSynchronizeAndCleanup(); #if UNITY FireSyncFailureEvent(new SyncManagerException("Manual cancel"), options); #else FireSyncFailureEvent(new SyncManagerException("Manual cancel")); #endif return; } } // if the dataset doesn't exist or is deleted, trigger onDelete if (lastSyncCount != 0 && !datasetUpdates.Exists || datasetUpdates.Deleted && this.OnDatasetDeleted != null) { bool resume = this.OnDatasetDeleted(this); if (resume) { // remove both records and metadata Local.DeleteDataset(IdentityId, DatasetName); Local.PurgeDataset(IdentityId, DatasetName); _logger.InfoFormat("OnSyncSuccess"); EndSynchronizeAndCleanup(); #if UNITY FireSyncSuccessEvent(new List <Record>(), options); #else FireSyncSuccessEvent(new List <Record>()); #endif return; } else { _logger.InfoFormat("OnSyncFailure"); EndSynchronizeAndCleanup(); #if UNITY FireSyncFailureEvent(new SyncManagerException("Manual cancel"), options); #else FireSyncFailureEvent(new SyncManagerException("Manual cancel")); #endif return; } } lastSyncCount = datasetUpdates.SyncCount; List <Record> remoteRecords = datasetUpdates.Records; if (remoteRecords.Count != 0) { // if conflict, prompt developer/user with callback List <SyncConflict> conflicts = new List <SyncConflict>(); List <Record> conflictRecords = new List <Record>(); foreach (Record remoteRecord in remoteRecords) { Record localRecord = Local.GetRecord(IdentityId, DatasetName, remoteRecord.Key); // only when local is changed and its value is different if (localRecord != null && localRecord.IsModified && !StringUtils.Equals(localRecord.Value, remoteRecord.Value)) { conflicts.Add(new SyncConflict(remoteRecord, localRecord)); conflictRecords.Add(remoteRecord); } } // retaining only non-conflict records remoteRecords.RemoveAll(t => conflictRecords.Contains(t)); if (conflicts.Count > 0) { _logger.InfoFormat("{0} records in conflict!", conflicts.Count); bool syncConflictResult = false; if (this.OnSyncConflict == null) { // delegate is not implemented so the conflict resolution is applied syncConflictResult = this.ResolveConflictsWithDefaultPolicy(conflicts); } else { syncConflictResult = this.OnSyncConflict(this, conflicts); } if (!syncConflictResult) { _logger.InfoFormat("User cancelled conflict resolution"); EndSynchronizeAndCleanup(); #if UNITY FireSyncFailureEvent(new OperationCanceledException("User cancelled conflict resolution"), options); #else FireSyncFailureEvent(new OperationCanceledException("User cancelled conflict resolution")); #endif return; } } // save to local if (remoteRecords.Count > 0) { _logger.InfoFormat("Save {0} records to local", remoteRecords.Count); Local.PutRecords(IdentityId, DatasetName, remoteRecords); } // new last sync count _logger.InfoFormat("Updated sync count {0}", datasetUpdates.SyncCount); Local.UpdateLastSyncCount(IdentityId, DatasetName, datasetUpdates.SyncCount); } // push changes to remote List <Record> localChanges = this.ModifiedRecords; long minPatchSyncCount = lastSyncCount; foreach (Record r in localChanges) { //track the max sync count if (r.SyncCount < minPatchSyncCount) { minPatchSyncCount = r.SyncCount; } } if (localChanges.Count != 0) { _logger.InfoFormat("Push {0} records to remote", localChanges.Count); try { #if BCL35 || UNITY List <Record> result = Remote.PutRecords(DatasetName, localChanges, datasetUpdates.SyncSessionToken); #else List <Record> result = await Remote.PutRecordsAsync(DatasetName, localChanges, datasetUpdates.SyncSessionToken, cancellationToken).ConfigureAwait(false); #endif // update local meta data Local.ConditionallyPutRecords(IdentityId, DatasetName, result, localChanges); // verify the server sync count is increased exactly by one, aka no // other updates were made during this update. long newSyncCount = 0; foreach (Record record in result) { newSyncCount = newSyncCount < record.SyncCount ? record.SyncCount : newSyncCount; } if (newSyncCount == lastSyncCount + 1) { _logger.InfoFormat("Updated sync count {0}", newSyncCount); Local.UpdateLastSyncCount(IdentityId, DatasetName, newSyncCount); } _logger.InfoFormat("OnSyncSuccess"); EndSynchronizeAndCleanup(); #if UNITY FireSyncSuccessEvent(remoteRecords, options); #else FireSyncSuccessEvent(remoteRecords); #endif return; } catch (DataConflictException e) { _logger.InfoFormat("Conflicts detected when pushing changes to remote: {0}", e.Message); if (retry == 0) { EndSynchronizeAndCleanup(); #if UNITY FireSyncFailureEvent(e, options); #else FireSyncFailureEvent(e); #endif } else { //it's possible there is a local dirty record with a stale sync count this will fix it if (lastSyncCount > minPatchSyncCount) { Local.UpdateLastSyncCount(IdentityId, DatasetName, minPatchSyncCount); } #if BCL35 RunSyncOperation(--retry); } return; } #elif UNITY RunSyncOperation(--retry, options); } return; }
private void SetupDatabase() { lock (sqlite_lock) { SQLiteStatement stmt = null; try { db = new SQLiteDatabase(this.dataPath); string query = "SELECT count(*) as count FROM sqlite_master WHERE type='table' AND name='" + TABLE_DATASETS + "'"; stmt = db.Prepare(query); if (stmt.Read() && stmt.Fields["count"].INTEGER == 0) { _logger.InfoFormat("{0}", @"Cognito Sync - SQLiteStorage - running create dataset"); db.Exec( "CREATE TABLE " + TABLE_DATASETS + "(" + DatasetColumns.IDENTITY_ID + " TEXT NOT NULL," + DatasetColumns.DATASET_NAME + " TEXT NOT NULL," + DatasetColumns.CREATION_TIMESTAMP + " TEXT DEFAULT '0'," + DatasetColumns.LAST_MODIFIED_TIMESTAMP + " TEXT DEFAULT '0'," + DatasetColumns.LAST_MODIFIED_BY + " TEXT," + DatasetColumns.STORAGE_SIZE_BYTES + " INTEGER DEFAULT 0," + DatasetColumns.RECORD_COUNT + " INTEGER DEFAULT 0," + DatasetColumns.LAST_SYNC_COUNT + " INTEGER NOT NULL DEFAULT 0," + DatasetColumns.LAST_SYNC_TIMESTAMP + " INTEGER DEFAULT '0'," + DatasetColumns.LAST_SYNC_RESULT + " TEXT," + "UNIQUE (" + DatasetColumns.IDENTITY_ID + ", " + DatasetColumns.DATASET_NAME + ")" + ")"); } stmt.FinalizeStm(); query = "SELECT count(*) as count FROM sqlite_master WHERE type='table' AND name='" + TABLE_RECORDS + "'"; stmt = db.Prepare(query); if (stmt.Read() && stmt.Fields["count"].INTEGER == 0) { _logger.InfoFormat("{0}", @"Cognito Sync - SQLiteStorage - running create dataset"); db.Exec( "CREATE TABLE " + TABLE_RECORDS + "(" + RecordColumns.IDENTITY_ID + " TEXT NOT NULL," + RecordColumns.DATASET_NAME + " TEXT NOT NULL," + RecordColumns.KEY + " TEXT NOT NULL," + RecordColumns.VALUE + " TEXT," + RecordColumns.SYNC_COUNT + " INTEGER NOT NULL DEFAULT 0," + RecordColumns.LAST_MODIFIED_TIMESTAMP + " TEXT DEFAULT '0'," + RecordColumns.LAST_MODIFIED_BY + " TEXT," + RecordColumns.DEVICE_LAST_MODIFIED_TIMESTAMP + " TEXT DEFAULT '0'," + RecordColumns.MODIFIED + " INTEGER NOT NULL DEFAULT 1," + "UNIQUE (" + RecordColumns.IDENTITY_ID + ", " + RecordColumns.DATASET_NAME + ", " + RecordColumns.KEY + ")" + ")"); } } finally { if (stmt != null) { stmt.FinalizeStm(); } } _logger.InfoFormat("{0}", @"Cognito Sync - SQLiteStorage - completed setupdatabase"); } }
/// <summary> /// Add an event to the store. /// </summary> /// <returns><c>true</c>, if event was put, <c>false</c> otherwise.</returns> public bool PutEvent(string eventString, string appId) { bool success = false; bool proceedToInsert = false; long currentDatabaseSize = GetDatabaseSize(); if (string.IsNullOrEmpty(appId)) { throw new ArgumentNullException("AppId"); } if (currentDatabaseSize >= _maxDbSize) { proceedToInsert = false; InvalidOperationException e = new InvalidOperationException(); _logger.Error(e, "The database size has exceeded the threshold limit. Unable to insert any new events"); } else if (currentDatabaseSize / _maxDbSize >= _dbWarningThreshold) { proceedToInsert = true; _logger.InfoFormat("The database size is almost full"); } else { proceedToInsert = true; } //keep the lock as short as possible if (proceedToInsert) { lock (_lock) { SQLiteStatement stmt = null; try { #if SQL_DEBUG DateTime _dbExecutionStartTime = DateTime.Now; #endif string query = "INSERT INTO " + TABLE_NAME + " (" + EVENT_COLUMN_NAME + "," + EVENT_ID_COLUMN_NAME + "," + MA_APP_ID_COLUMN_NAME + ") values(?,?,?)"; stmt = db.Prepare(query); stmt.BindText(1, eventString); stmt.BindText(2, Guid.NewGuid().ToString()); stmt.BindText(3, appId); stmt.Step(); success = true; #if SQL_DEBUG DateTime _dbExecutionEndTime = DateTime.Now; double totalSeconds = _dbExecutionEndTime.Subtract(_dbExecutionStartTime).TotalSeconds; AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "SQLiteEventStore", "Put Operation completed on local store in " + totalSeconds + " seconds"); #endif } finally { if (stmt != null) { stmt.FinalizeStm(); } } } } return(success); }
private void SynchronizeInternalAsync() { try { if (locked) { _logger.InfoFormat("Already in a Synchronize. Queueing new request.", _datasetName); queuedSync = true; return; } else { locked = true; } waitingForConnectivity = false; bool resume = true; List <string> mergedDatasets = GetLocalMergedDatasets(); if (mergedDatasets.Count > 0) { _logger.InfoFormat("Detected merge datasets - {0}", _datasetName); if (this.OnDatasetMerged != null) { resume = this.OnDatasetMerged(this, mergedDatasets); } } if (!resume) { EndSynchronizeAndCleanup(); FireSyncFailureEvent(new OperationCanceledException(string.Format("Sync canceled on merge for dataset - {0}", this._datasetName))); return; } RunSyncOperationAsync(MAX_RETRY); } catch (Exception e) { FireSyncFailureEvent(e); _logger.Error(e, ""); } }