protected int ReadInSurrogates(int currentModelVersion)
{
for (; ; ) // Loop is used to retry if we get a corrupt file and restore backup.
{
var fileSize = new FileInfo(ProjectId.Path).Length;
// This arbitrary length is based on two large databases, one 360M with 474 bytes/object, and one 180M with 541.
// It's probably not perfect, but we're mainly trying to prevent fragmenting the large object heap
// by growing it MANY times.
var estimatedObjectCount = (int)(fileSize/400);
m_identityMap.ExpectAdditionalObjects(estimatedObjectCount);
if (!FileUtils.SimilarFileExists(ProjectId.Path))
throw new InvalidOperationException("System does not exist.");
try
{
// We need to reorder the entire file to be nice to Mercurial,
// but only if the current version is less than "7000048".
// Step 0: Get the version number.
m_startupVersionNumber = GetActualModelVersionNumber(ProjectId.Path);
var useLocalTempFile = !IsLocalDrive(ProjectId.Path);
// Step 1:
if (m_startupVersionNumber < 7000048)
{
#if DEBUG
var reorderWatch = new Stopwatch();
reorderWatch.Start();
#endif
var tempPathname = useLocalTempFile ? Path.GetTempFileName() : Path.ChangeExtension(ProjectId.Path, "tmp");
// Rewrite the file in the prescribed order.
using (var writer = FdoXmlServices.CreateWriter(tempPathname))
{
FdoXmlServices.WriteStartElement(writer, m_startupVersionNumber); // Use version from old file, so DM can be done, if needed.
DataSortingService.SortEntireFile(m_mdcInternal.GetSortableProperties(), writer, ProjectId.Path);
writer.WriteEndElement(); // 'languageproject'
writer.Close();
}
#if DEBUG
reorderWatch.Stop();
Debug.WriteLine("Reordering entire file took " + reorderWatch.ElapsedMilliseconds + " ms.");
//Debug.Assert(false, "Force a stop.");
#endif
// Copy reordered file to ProjectId.Path.
CopyTempFileToOriginal(useLocalTempFile, ProjectId.Path, tempPathname);
}
// Step 2: Go on one's merry way....
using (var reader = FdoXmlServices.CreateReader(ProjectId.Path))
{
reader.MoveToContent();
m_needConversion = (m_startupVersionNumber != currentModelVersion);
// Optional AdditionalFields element.
if (reader.Read() && reader.LocalName == "AdditionalFields")
{
var cfiList = new List<CustomFieldInfo>();
while (reader.Read() && reader.LocalName == "CustomField")
{
if (!reader.IsStartElement())
continue;
var cfi = new CustomFieldInfo();
reader.MoveToAttribute("class");
cfi.m_classname = reader.Value;
if (reader.MoveToAttribute("destclass"))
cfi.m_destinationClass = Int32.Parse(reader.Value);
if (reader.MoveToAttribute("helpString"))
cfi.m_fieldHelp = reader.Value;
if (reader.MoveToAttribute("label"))
cfi.Label = reader.Value;
if (reader.MoveToAttribute("listRoot"))
cfi.m_fieldListRoot = new Guid(reader.Value);
reader.MoveToAttribute("name");
cfi.m_fieldname = reader.Value;
reader.MoveToAttribute("type");
cfi.m_fieldType = GetFlidTypeFromString(reader.Value);
if (reader.MoveToAttribute("wsSelector"))
cfi.m_fieldWs = Int32.Parse(reader.Value);
reader.MoveToElement();
cfiList.Add(cfi);
}
RegisterOriginalCustomProperties(cfiList);
}
}
Stopwatch watch = new Stopwatch();
watch.Start();
using (var er = new ElementReader("<rt ", "</languageproject>", ProjectId.Path, MakeSurrogate))
{
er.Run();
}
watch.Stop();
Debug.WriteLine("Making surrogates took " + watch.ElapsedMilliseconds + " ms.");
}
catch (ArgumentException e)
{
Logger.WriteError(e);
// Failed to get a version number from the file!
OfferToRestore(Properties.Resources.kstidInvalidFieldWorksXMLFile);
continue; // backup restored, if previous call returns.
}
catch (XmlException e)
{
Logger.WriteError(e);
// The data is not in the format we expect or not even an XML file
OfferToRestore(Properties.Resources.kstidInvalidFieldWorksXMLFile);
continue; // backup restored, if previous call returns.
}
catch (IOException e)
{
Logger.WriteError(e);
OfferToRestore(e.Message);
continue; // backup restored, if previous call returns.
}
ReportDuplicateGuidsIfTheyExist();
return m_startupVersionNumber;
}
}