public void TestNestedKill() { var lines = new SyncCollection(); var pipeline = TestShell.Run(SampleCommand, "pipe") | TestShell.Run(SampleCommand, "pipe") | TestShell.Run(SampleCommand, "pipe") > lines; // demonstrate that a single line can make it all the way through the pipeline // without getting caught in a buffer along the way pipeline.StandardInput.AutoFlush.ShouldEqual(true); pipeline.StandardInput.WriteLine("a line"); var start = DateTime.UtcNow; while ((DateTime.UtcNow - start) < TimeSpan.FromSeconds(10)) { if (lines.Count > 0) { break; } Thread.Sleep(10); } pipeline.Task.IsCompleted.ShouldEqual(false); lines.FirstOrDefault().ShouldEqual("a line"); pipeline.Task.IsCompleted.ShouldEqual(false); pipeline.Kill(); pipeline.Result.Success.ShouldEqual(false); }
/// <summary> /// handels the sync button click event /// </summary> /// <param name="sender"> /// The sender of this event. /// </param> /// <param name="e"> /// The empty event args for event handling system. /// </param> private void ButtonSyncWithXing_Click(object sender, EventArgs e) { // using a lambda here is much less code EventHandler <ProgressEventArgs> progress = (s, evnt) => this.progressBar.Value = evnt.PercentageDone; // first attach to the events to update the progress bar and the // log list for the user. this.engine.ProcessingEvent += this.LogThis; this.engine.ProgressEvent += progress; // load a SyncCollection from the xml file (this can be // modified in order to change behavior) var list = SyncCollection.LoadSyncList("commands.xml"); // now execute the list of commands this.engine.Execute(list); // detach from the events - there's nothing we should get from there // any more. this.engine.ProcessingEvent -= this.LogThis; this.engine.ProgressEvent -= progress; // tell the user we have finished MessageBox.Show(Resources.messageFinished, this.Text); }
/// <summary> /// execute the commands stored inside the list /// </summary> /// <param name="syncList"> the list to execute </param> /// <returns> a value specifying if the execution should continue </returns> public bool Execute(SyncCollection syncList) { var itemsDone = 0; this.numberOfCommandsInSequence = syncList.Count; LogProcessingEvent(string.Format(CultureInfo.CurrentCulture, Resources.uiStartingProcessing, this.percentageOfSequenceDone)); foreach (var item in syncList) { this.percentageOfSequenceDone = itemsDone * 100 / this.numberOfCommandsInSequence; UpdateProgress(this.percentageOfSequenceDone); if (!this.Execute(item)) { LogProcessingEvent(Resources.uiProcessingCanceled); UpdateProgress(0); return(false); } itemsDone++; } UpdateProgress(100); return(true); }
/// <summary> /// Runs the currently selected template with the currently loaded data. /// </summary> /// <param name="templateScriptPath"> /// The path to the template script. /// </param> public void Run(string templateScriptPath) { if (!File.Exists(templateScriptPath)) { this.ProcessingEvent(this, new ProcessingEventArgs(string.Format(CultureInfo.CurrentCulture, Resources.InstalledFileNotFound, templateScriptPath))); return; } var commands = SyncCollection.LoadSyncList(templateScriptPath); if (commands == null) { return; } foreach (var command in commands) { command.SourceCredentials = (command.SourceConnector != null && command.SourceConnector == "{source}") ? this.Source.LogonCredentials : command.SourceCredentials; command.SourceCredentials = (command.SourceConnector != null && command.SourceConnector == "{target}") ? this.Target.LogonCredentials : command.SourceCredentials; command.TargetCredentials = (command.TargetConnector != null && command.TargetConnector == "{source}") ? this.Source.LogonCredentials : command.TargetCredentials; command.TargetCredentials = (command.TargetConnector != null && command.TargetConnector == "{target}") ? this.Target.LogonCredentials : command.TargetCredentials; command.SourceConnector = this.ReplaceToken(command.SourceConnector); command.TargetConnector = this.ReplaceToken(command.TargetConnector); command.SourceStorePath = this.ReplaceToken(command.SourceStorePath); command.TargetStorePath = this.ReplaceToken(command.TargetStorePath); command.CommandParameter = this.ReplaceToken(command.CommandParameter); } var engine = new SyncEngine { WorkingFolder = Config.WorkingFolder, UiProvider = new UiDispatcher(), }; engine.ProcessingEvent += this.HandleProcessingEvent; engine.ProgressEvent += this.ProgressEvent; try { engine.Execute(commands); } catch (ProcessAbortException) { } engine.ProcessingEvent -= this.HandleProcessingEvent; engine.ProgressEvent -= this.ProgressEvent; if (this.FinishedEvent != null) { this.FinishedEvent(new ProgressEventArgs { PercentageDone = 100 }); } }
/// <summary> /// performs the setup of the form after loading the controls /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The empty event arguments. /// </param> private void LocalSync_Load(object sender, EventArgs e) { // todo: this should be handled by the viewmodel instead of the code behind // route the events this.DataContext.ProcessingEvent += this.LogMessage; this.DataContext.ProgressEvent += this.OnProgressEvent; // we can use a lambda, because we will never need to detach this.DataContext.QueryForLogOnCredentials += (s, eargs) => new LogOn().SetLogonCredentials((IClientBase)s, eargs); // get the data for the combo box from the file system paths this.SyncListSelection.DataSource = (from x in Directory.GetFiles(SyncWizardContext.WorkingFolderTemplates, "*.SyncList") select new { Name = Path.GetFileName(x), Path = x }).ToList(); // display file name only, but store full path this.SyncListSelection.ValueMember = "Path"; this.SyncListSelection.DisplayMember = "Name"; // add event handler that will use the >>value<< instead of the text // to load the grid this.SyncListSelection.SelectedValueChanged += (cbs, cbe) => { var item = ((ComboBox)cbs).SelectedValue; if (item != null) { this.DataContext.SyncCommands = SyncCollection.LoadSyncList(item.ToString()); } this.syncListBindingSource.DataSource = this.DataContext.SyncCommands; }; // unselect first entry, then select one, if there is one ;-) - this will fire the SelectedValueChanged this.SyncListSelection.SelectedIndex = -1; if (this.SyncListSelection.Items.Count > 0) { this.SyncListSelection.SelectedIndex = 0; } this.dataGridView1.KeyDown += (kps, kpe) => { if (kpe.KeyCode == Keys.Enter) { this.RunSelectedRow(); } }; this.dataGridView1.CellDoubleClick += (gvs, gve) => this.RunRowCommand(gve.RowIndex); // setup the commands this.openWorkingFolderToolStripMenuItem.Click += (s, ev) => this.DataContext.OpenWorkingFolder(); this.exitToolStripMenuItem.Click += (s, ev) => this.Close(); this.runSelected.Click += (s, ev) => this.RunSelectedRow(); }
private static void ParseSyncKey(SyncCollection collection) { collection.AllowRecovery = collection.ParseSynckeyAndDetermineRecovery(); if (collection.SyncKey == 0U) { collection.Status = SyncBase.ErrorCodeStatus.UnprimedSyncState; throw new AirSyncPermanentException(false) { ErrorStringForProtocolLogger = "SyncNotPrimed" }; } }
public void TestCancellationCanceledPartway() { using (var cancellationTokenSource = new CancellationTokenSource()) { var results = new SyncCollection(); var command = TestShell.Run(SampleCommand, new object[] { "echo", "--per-char" }, o => o.CancellationToken(cancellationTokenSource.Token)) > results; command.StandardInput.WriteLine("hello"); var timeout = Task.Delay(TimeSpan.FromSeconds(10)); while (results.Count == 0 && !timeout.IsCompleted) { } results.Count.ShouldEqual(1); cancellationTokenSource.Cancel(); var aggregateException = Assert.Throws <AggregateException>(() => command.Task.Wait(1000)); Assert.IsInstanceOf <TaskCanceledException>(aggregateException.GetBaseException()); CollectionAssert.AreEqual(results, new[] { "hello" }); } }
private void FinalizeResponseNode(SyncCollection collection) { AirSyncDiagnostics.TraceInfo(ExTraceGlobals.RequestsTracer, this, "GIE.FinalizeResponseNode"); XmlElement xmlElement = base.XmlResponse.CreateElement("Response", "GetItemEstimate:"); this.getItemEstimateXmlNode.AppendChild(xmlElement); XmlElement xmlElement2 = base.XmlResponse.CreateElement("Status", "GetItemEstimate:"); xmlElement2.InnerText = this.GetStatusString(collection.Status); base.ProtocolLogger.SetValue(collection.InternalName, PerFolderProtocolLoggerData.PerFolderStatus, (int)collection.Status); XmlElement xmlElement3 = base.XmlResponse.CreateElement("Collection", "GetItemEstimate:"); XmlElement xmlElement4 = base.XmlResponse.CreateElement("Class", "GetItemEstimate:"); xmlElement4.InnerText = collection.ClassType; XmlElement xmlElement5 = base.XmlResponse.CreateElement("CollectionId", "GetItemEstimate:"); xmlElement5.InnerText = collection.CollectionId; if (base.Version < 121) { xmlElement3.AppendChild(xmlElement4); } if (collection.ReturnCollectionId) { xmlElement3.AppendChild(xmlElement5); } if (collection.Status == SyncBase.ErrorCodeStatus.Success) { XmlElement xmlElement6 = base.XmlResponse.CreateElement("Estimate", "GetItemEstimate:"); xmlElement6.InnerText = collection.ServerChanges.Count.ToString(CultureInfo.InvariantCulture); xmlElement3.AppendChild(xmlElement6); } base.ProtocolLogger.IncrementValue(ProtocolLoggerData.TotalFolders); xmlElement.AppendChild(xmlElement2); xmlElement.AppendChild(xmlElement3); this.getItemEstimateXmlNode.AppendChild(xmlElement); }
public void GetChanges(SyncCollection collection, bool autoLoadFilterAndSyncKey, bool tryNullSync, bool commitSyncState, bool enumerateAllchanges) { AirSyncDiagnostics.TraceInfo <bool, bool, bool>(ExTraceGlobals.RequestsTracer, this, "GIE:GetChanges autoLoadFilterAndSyncKey:{0} tryNullSync:{1} commitSyncState:{2}", autoLoadFilterAndSyncKey, tryNullSync, commitSyncState); base.InitializeVersionFactory(base.Version); collection.SetDeviceSettings(this); long utcTicks = ExDateTime.Now.Date.UtcTicks; bool nullSyncAllowed = !base.IsInQuarantinedState || base.IsQuarantineMailAvailable; if (tryNullSync && !collection.CollectionRequiresSync(autoLoadFilterAndSyncKey, nullSyncAllowed)) { base.ProtocolLogger.SetProviderSyncType(collection.CollectionId, ProviderSyncType.N); collection.SetEmptyServerChanges(); return; } collection.OpenSyncState(autoLoadFilterAndSyncKey, base.SyncStateStorage); if (base.Context.Request.Version < 160 && collection.FolderType == DefaultFolderType.Drafts) { AirSyncDiagnostics.TraceInfo(ExTraceGlobals.RequestsTracer, this, "[GIE.GetChanges] Ignoring request to sync drafts."); collection.SetEmptyServerChanges(); return; } try { if (collection.HasOptionsNodes) { collection.ParseSyncOptions(); } else if (collection.HasFilterNode) { collection.ParseFilterType(null); } else { collection.ParseStickyOptions(); } } catch (AirSyncPermanentException ex) { base.ProtocolLogger.AppendValue(ProtocolLoggerData.Error, string.Format("ParsingError:{0}", ex.ErrorStringForProtocolLogger)); base.GlobalStatus = SyncBase.ErrorCodeStatus.ProtocolError; throw; } collection.AddDefaultOptions(); collection.InitializeSchemaConverter(base.VersionFactory, base.GlobalInfo); bool syncProviderOptions = base.IsQuarantineMailAvailable && (base.GlobalInfo.DeviceAccessStateReason == DeviceAccessStateReason.ExternalCompliance || base.GlobalInfo.DeviceAccessStateReason == DeviceAccessStateReason.ExternalEnrollment); collection.SetSyncProviderOptions(syncProviderOptions); collection.OpenFolderSync(); collection.VerifySyncKey(false, base.GlobalInfo); if (collection.CollectionId != null) { base.ProtocolLogger.SetValue(collection.InternalName, PerFolderProtocolLoggerData.FolderId, collection.CollectionId); } base.ProtocolLogger.SetValue(collection.InternalName, PerFolderProtocolLoggerData.ClientSyncKey, collection.SyncKey.ToString(CultureInfo.InvariantCulture)); if (!base.IsInQuarantinedState || base.IsQuarantineMailAvailable) { collection.SetFolderSyncOptions(base.VersionFactory, base.IsQuarantineMailAvailable, base.GlobalInfo); base.GlobalWindowSize -= collection.GetServerChanges(base.GlobalWindowSize, enumerateAllchanges); } else { collection.SetEmptyServerChanges(); AirSyncDiagnostics.TraceInfo <DeviceAccessState>(ExTraceGlobals.RequestsTracer, this, "Setting empty server changes for quarantined state. Current AccessState = {0}", base.CurrentAccessState); } if (!base.IsInQuarantinedState && tryNullSync && collection.ServerChanges.Count == 0 && commitSyncState) { collection.SyncState.CustomVersion = new int?(9); object[] nullSyncPropertiesToSave = collection.GetNullSyncPropertiesToSave(); try { if (nullSyncPropertiesToSave != null) { collection.SyncState.CommitState(collection.PropertiesToSaveForNullSync, nullSyncPropertiesToSave); } else { collection.SyncState.CommitState(null, null); } collection.UpdateSavedNullSyncPropertiesInCache(nullSyncPropertiesToSave); base.ProtocolLogger.IncrementValueBy(collection.InternalName, PerFolderProtocolLoggerData.SyncStateKbCommitted, (int)collection.SyncState.GetLastCommittedSize() >> 10); } catch (StorageTransientException) { AirSyncDiagnostics.TraceError(ExTraceGlobals.RequestsTracer, this, "Transient exception thrown while saving syncstate in GIE\r\nSkipping exception due to only being for the null sync optimization."); } } }
private void ReadXmlRequest() { AirSyncDiagnostics.TraceInfo(ExTraceGlobals.RequestsTracer, this, "GIE.ReadXmlRequest"); XmlNode xmlRequest = base.XmlRequest; XmlNode xmlNode = xmlRequest["Collections", "GetItemEstimate:"]; if (xmlNode.ChildNodes.Count >= GlobalSettings.MaxNumOfFolders) { AirSyncDiagnostics.TraceDebug <int>(ExTraceGlobals.RequestsTracer, this, "GIE: client specified too many folders: {0}", GlobalSettings.MaxNumOfFolders); throw new AirSyncPermanentException(HttpStatusCode.BadRequest, StatusCode.InvalidXML, null, false) { ErrorStringForProtocolLogger = "GIE.TooManyFolders" }; } foreach (object obj in xmlNode.ChildNodes) { XmlNode xmlNode2 = (XmlNode)obj; SyncCollection syncCollection = null; bool flag = false; try { if (base.Version >= 140) { syncCollection = SyncCollection.ParseCollection(null, xmlNode2, base.Version, base.MailboxSession); } else { XmlNode xmlNode3 = xmlNode2["CollectionId"]; string collectionId = (xmlNode3 == null) ? null : xmlNode3.InnerText; syncCollection = SyncCollection.CreateSyncCollection(base.MailboxSession, base.Version, collectionId); foreach (object obj2 in xmlNode2.ChildNodes) { XmlNode xmlNode4 = (XmlNode)obj2; string localName; if ((localName = xmlNode4.LocalName) != null) { if (!(localName == "Class")) { if (localName == "SyncKey") { syncCollection.SyncKeyString = xmlNode4.InnerText; continue; } if (localName == "CollectionId") { syncCollection.CollectionId = xmlNode4.InnerText; continue; } if (localName == "FilterType") { int num; if (!int.TryParse(xmlNode4.InnerText, out num) || num > 8 || num < 0) { base.GlobalStatus = SyncBase.ErrorCodeStatus.ProtocolError; base.ProtocolLogger.SetValue(ProtocolLoggerData.Error, "InvalidFilterValue"); throw new AirSyncPermanentException(false); } syncCollection.FilterType = (AirSyncV25FilterTypes)num; syncCollection.HasFilterNode = true; continue; } } else { string innerText = xmlNode4.InnerText; string a; if ((a = innerText) != null && (a == "Email" || a == "Calendar" || a == "Contacts" || a == "Tasks" || a == "Notes")) { syncCollection.ClassType = innerText; continue; } base.ProtocolLogger.SetValue(ProtocolLoggerData.Error, "InvalidClassType"); throw new AirSyncPermanentException(HttpStatusCode.InternalServerError, StatusCode.UnexpectedItemClass, null, false); } } base.ProtocolLogger.SetValue(ProtocolLoggerData.Error, "BadNodeInRequest"); throw new AirSyncPermanentException(HttpStatusCode.BadRequest, StatusCode.InvalidXML, null, false); } } base.Collections[syncCollection.InternalName] = syncCollection; flag = true; } finally { if (syncCollection != null && !flag) { syncCollection.Dispose(); syncCollection = null; } } } }
public void GetChanges(SyncCollection collection, bool autoLoadFilterAndSyncKey, bool tryNullSync, bool commitSyncState) { this.GetChanges(collection, autoLoadFilterAndSyncKey, tryNullSync, commitSyncState, true); }
/// <summary> /// Executes the list of commands specified as a path to the file containing the serialized list in the first parameter. /// </summary> /// <param name="args"> /// The parameter that contains the path to the list of serialized commands. /// </param> public static void Main(string[] args) { #if (DEBUG) if (args.Length < 1) { args = new[] { @"{FS:ApplicationFolder}\A Copy OutlookCal to Xml.SyncList" }; } #endif if (args.Length >= 1) { var success = false; try { var defaultBaseFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SemSyncCmd"); Console.WriteLine(Resources.MessageInfoWorkingFolder, defaultBaseFolder); // setup the sync engine var engine = new SyncEngine { WorkingFolder = defaultBaseFolder, UiProvider = new UiDispatcher() }; var filename = engine.ReplacePathToken(args[0]); if (!File.Exists(filename)) { Console.WriteLine(Resources.ErrorMessageFileNotFound + filename); } else { // load the list of commands Console.WriteLine(Resources.MessageInfoLoadingList, filename); var syncCommands = SyncCollection.LoadSyncList(filename); // feed dispatcher with credentials if specified by the command line ((UiDispatcher)engine.UiProvider).UserDomain = args.Length > 1 ? args[1] : string.Empty; ((UiDispatcher)engine.UiProvider).UserName = args.Length > 2 ? args[2] : string.Empty; ((UiDispatcher)engine.UiProvider).UserPassword = args.Length > 3 ? args[3] : string.Empty; // connect to events engine.ProcessingEvent += ProcessingEvent; engine.ProgressEvent += ProgressEvent; // execute commands success = engine.Execute(syncCommands); // disconnect from events engine.ProcessingEvent -= ProcessingEvent; engine.ProgressEvent -= ProgressEvent; } } catch (Exception ex) { Console.WriteLine(Resources.MessageErrorException, ex); } Console.WriteLine(Resources.MessageInfoStatus, success ? "success" : "failed"); } else { Console.WriteLine( Resources.MessageInfoUsage, Path.GetFileNameWithoutExtension(Assembly.GetAssembly(typeof(Program)).CodeBase)); } #if (DEBUG) // wait for user input if in debug build Console.WriteLine(Resources.MessageInfoCloseWithEnter); Console.ReadLine(); #endif }
public override void Execute() { try { Dictionary <string, SyncEntity> completedImports = ReadCompletedImports(); var allFiles = ReadFiles(FilesFilter); Program.Console($"Found {allFiles.Length} files to import"); foreach (var f in allFiles.OrderBy(f => f.Name)) { if (completedImports.ContainsKey(f.Name)) { Program.Console($"Skipping {f.Name}, already imported on {completedImports[f.Name].Imported.ToString("u")}"); continue; } var fileNameSplit = f.Name.Split('.'); if (fileNameSplit.Length != 4) { throw new InvalidOperationException($"File {f.Name} do not have 4 components: [Order].[Collection].[Operation].json"); } string collectionName = fileNameSplit[1]; ImportMode importMode = Enum.Parse <ImportMode>(fileNameSplit[2], true); Program.Console($"Importing {f.Name} to collection {collectionName}, mode {importMode}"); SyncEntity importResult = new SyncEntity(); importResult.FileName = f.Name; try { switch (importMode) { case ImportMode.Drop: dropCollection(collectionName); break; case ImportMode.Delete: deleteFromCollection(collectionName, f); break; case ImportMode.Insert: case ImportMode.Upsert: case ImportMode.Merge: var resultCode = Program.Exec(IMPORT_COMMAND, $"{ConnectionString.ToCommandLine()}{AuthenticationDatabaseToCommandLine()} --collection {collectionName} --type json --mode {importMode.ToString().ToLower()} --stopOnError --file {f.Name}"); if (resultCode != 0) { throw new InvalidOperationException($"mongoimport result code {resultCode}, interrupting"); } break; case ImportMode.Eval: var evalResultCode = Program.Exec(MONGO_COMMAND, $"{Connection} {f.Name}"); if (evalResultCode != 0) { throw new InvalidOperationException($"mongo result code {evalResultCode}, interrupting"); } break; case ImportMode.CreateIndex: var text = File.ReadAllText(f.FullName); Program.Console("Index params:"); Program.Console(text); var command = string.Format(CREATE_INDEX, collectionName, text); var fileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".js"); File.WriteAllText(fileName, command); try { var createIndexResultCode = Program.Exec(MONGO_COMMAND, $"{Connection} {fileName}"); switch (createIndexResultCode) { // no error case 0: break; case 11000: throw new InvalidOperationException($"CreateIndex failed with error 'duplicate key error', interrupting"); default: // all error codes with explanation // https://github.com/mongodb/mongo/blob/master/src/mongo/base/error_codes.err throw new InvalidOperationException($"CreateIndex result code {createIndexResultCode}, interrupting"); } } finally { File.Delete(fileName); } break; default: throw new InvalidOperationException($"Import mode {importMode} not implemented yet"); } importResult.Success = true; } finally { SyncCollection.InsertOne(importResult); } } Program.Console($"Import completed successfully"); } catch (Exception ex) { Program.Console($"Error during import: {ex.Message}"); Environment.Exit(1); } }