private static void SaveChanges(FileRecord fileRecord)
        {
            fileRecord.LastModified = DateTime.Now;
            fileRecord.ReadOnlyElementsList = fileRecord.RecordSet.Index.GetValues();
            fileRecord.CachedTable = null;
            fileRecord.Dirty = false;

            XmlDataProviderDocumentWriter.Save(fileRecord);
        }
        private static void DoSave(FileRecord fileRecord)
        {
            XDocument xDocument = new XDocument();

            XElement root = new XElement(GetRootElementName(fileRecord.ElementName));
            xDocument.Add(root);

            var recordSet = fileRecord.RecordSet;
            List<XElement> elements = new List<XElement>(recordSet.Index.GetValues());

            string key = fileRecord.FilePath.ToLowerInvariant();

            Func<IEnumerable<XElement>, IOrderedEnumerable<XElement>> orderer;
            if (TryGetFileOrderer(out orderer, fileRecord.FilePath))
            {
                var orderedElements = orderer(elements);

                orderedElements.ForEach(root.Add);
            }
            else
            {
                elements.ForEach(root.Add);
            }

            Exception thrownException = null;

            // Writing the file in the "catch" block in order to prevent chance of corrupting the file by experiencing ThreadAbortException.
            try
            {
            }
            finally
            {
                try
                {
                    // Saving to temp file and file move to prevent broken saves
                    XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
                    xmlWriterSettings.CheckCharacters = false;
                    xmlWriterSettings.Indent = true;

                    using (XmlWriter xmlWriter = XmlWriter.Create(fileRecord.TempFilePath, xmlWriterSettings))
                    {
                        xDocument.Save(xmlWriter);
                    }
                    Thread.Sleep(_fileIoDelay);

                    bool failed = true;
                    Exception lastException = null;
                    for (int i = 0; i < NumberOfRetries; i++)
                    {
                        DateTime lastSuccessfulFileChange = fileRecord.FileModificationDate;
                        try
                        {

                            fileRecord.FileModificationDate = DateTime.MinValue;
                            File.Copy(fileRecord.TempFilePath, fileRecord.FilePath, true);
                            failed = false;
                            break;
                        }
                        catch (Exception ex)
                        {
                            fileRecord.FileModificationDate = lastSuccessfulFileChange;
                            lastException = ex;
                            Thread.Sleep(10 * (i + 1));
                        }
                    }

                    if (!failed)
                    {
                        Thread.Sleep(_fileIoDelay);
                        File.Delete(fileRecord.TempFilePath);
                    }
                    else
                    {
                        Log.LogCritical(LogTitle, "Failed deleting the file: " + fileRecord.FilePath);
                        if (lastException != null) throw lastException;

                        throw new InvalidOperationException("Failed to delete a file, this code shouldn't be reacheable");
                    }

                    fileRecord.FileModificationDate = C1File.GetLastWriteTime(fileRecord.FilePath);
                }
                catch (Exception exception)
                {
                    Log.LogCritical(LogTitle, "Failed to save data to the file file:" + fileRecord.FilePath);
                    Log.LogCritical(LogTitle, exception);
                    thrownException = exception;
                }
            }
            // ThreadAbortException should have a higher prioriry, and therefore we're doing rethrow in a separate block
            if (thrownException != null) throw thrownException;
        }
Beispiel #3
0
        private static void DoSave(FileRecord fileRecord)
        {
            XDocument xDocument = new XDocument();

            XElement root = new XElement(GetRootElementName(fileRecord.ElementName));

            xDocument.Add(root);

            var             recordSet = fileRecord.RecordSet;
            List <XElement> elements  = new List <XElement>(recordSet.Index.GetValues());

            string key = fileRecord.FilePath.ToLowerInvariant();

            Func <IEnumerable <XElement>, IOrderedEnumerable <XElement> > orderer;

            if (TryGetFileOrderer(out orderer, fileRecord.FilePath))
            {
                var orderedElements = orderer(elements);

                orderedElements.ForEach(root.Add);
            }
            else
            {
                elements.ForEach(root.Add);
            }

            Exception thrownException = null;

            // Writing the file in the "catch" block in order to prevent chance of corrupting the file by experiencing ThreadAbortException.
            try
            {
            }
            finally
            {
                try
                {
                    // Saving to temp file and file move to prevent broken saves
                    XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
                    xmlWriterSettings.CheckCharacters = false;
                    xmlWriterSettings.Indent          = true;

                    using (XmlWriter xmlWriter = XmlWriter.Create(fileRecord.TempFilePath, xmlWriterSettings))
                    {
                        xDocument.Save(xmlWriter);
                    }
                    Thread.Sleep(_fileIoDelay);

                    bool      failed        = true;
                    Exception lastException = null;
                    for (int i = 0; i < NumberOfRetries; i++)
                    {
                        DateTime lastSuccessfulFileChange = fileRecord.FileModificationDate;
                        try
                        {
                            fileRecord.FileModificationDate = DateTime.MinValue;
                            File.Copy(fileRecord.TempFilePath, fileRecord.FilePath, true);
                            failed = false;
                            break;
                        }
                        catch (Exception ex)
                        {
                            fileRecord.FileModificationDate = lastSuccessfulFileChange;
                            lastException = ex;
                            Thread.Sleep(10 * (i + 1));
                        }
                    }

                    if (!failed)
                    {
                        Thread.Sleep(_fileIoDelay);
                        File.Delete(fileRecord.TempFilePath);
                    }
                    else
                    {
                        Log.LogCritical(LogTitle, "Failed deleting the file: " + fileRecord.FilePath);
                        if (lastException != null)
                        {
                            throw lastException;
                        }

                        throw new InvalidOperationException("Failed to delete a file, this code shouldn't be reacheable");
                    }

                    fileRecord.FileModificationDate = C1File.GetLastWriteTime(fileRecord.FilePath);
                }
                catch (Exception exception)
                {
                    Log.LogCritical(LogTitle, "Failed to save data to the file file:" + fileRecord.FilePath);
                    Log.LogCritical(LogTitle, exception);
                    thrownException = exception;
                }
            }
            // ThreadAbortException should have a higher prioriry, and therefore we're doing rethrow in a separate block
            if (thrownException != null)
            {
                throw thrownException;
            }
        }
        internal static void Save(FileRecord fileRecord)
        {
            _dirtyRecords.Enqueue(fileRecord);

            if (forceImmediateWrite)
            {
                Flush();
            }
        }