Advertisement
Guest User

Untitled

a guest
Aug 20th, 2019
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.98 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using TACT.Net.Common;
  6. using TACT.Net.Cryptography;
  7.  
  8. namespace TACT.Net.Indices
  9. {
  10. internal class IndexRebuilder
  11. {
  12. private readonly IndexContainer _indexContainer;
  13. private readonly TACTRepo _repo;
  14. private readonly List<FileStream> _handles;
  15.  
  16. public IndexRebuilder(IndexContainer indexContainer, TACTRepo repo)
  17. {
  18. _indexContainer = indexContainer;
  19. _repo = repo;
  20. _handles = new List<FileStream>();
  21. }
  22.  
  23. public void Rebuild(string sourcedirectory, string directory)
  24. {
  25. Directory.CreateDirectory(directory);
  26. string tempBlobFilePath = Path.Combine(directory, "temp.blob");
  27.  
  28. // clear the old archive references from the config
  29. _repo.ConfigContainer.CDNConfig.GetValues("archives").Clear();
  30. _repo.ConfigContainer.CDNConfig.GetValues("archives-index-size").Clear();
  31.  
  32. var comparer = new MD5HashComparer();
  33. var entries = BuildEntries(sourcedirectory).OrderBy(x => comparer);
  34.  
  35. var partitions = EnumerablePartitioner.ConcreteBatch(entries, IndexContainer.ArchiveDataSize, (x) => (uint)x.CompressedSize);
  36. foreach (var partition in partitions)
  37. {
  38. // create the blob
  39. WriteTempBlob(partition, tempBlobFilePath);
  40.  
  41. IndexFile index = new IndexFile(IndexType.Data);
  42. index.Add(partition);
  43. index.Write(directory, _repo.ConfigContainer);
  44.  
  45. // move the blob to it's real location
  46. string newpath = Helpers.GetCDNPath(index.Checksum.ToString(), "data", directory);
  47. File.Move(tempBlobFilePath, newpath);
  48. }
  49.  
  50. ClearHandles();
  51. }
  52.  
  53. /// <summary>
  54. /// Generates a new set of IndexEntries for the new archives
  55. /// </summary>
  56. /// <param name="sourcedirectory"></param>
  57. /// <returns></returns>
  58. private IEnumerable<IndexEntry> BuildEntries(string sourcedirectory)
  59. {
  60. ushort i = 0;
  61. foreach (var index in _indexContainer.DataIndices)
  62. {
  63. if (index.IsLooseIndex || index.IsGroupIndex)
  64. continue;
  65.  
  66. // open a handle to the existing blob
  67. string blob = Helpers.GetCDNPath(index.Checksum.ToString(), "data", sourcedirectory);
  68. _handles.Add(new FileStream(blob, FileMode.Open, FileAccess.Read, FileShare.Read));
  69.  
  70. foreach (var entry in index.Entries)
  71. {
  72. // skip unused entries
  73. if (!_repo.EncodingFile.ContainsEKey(entry.Key))
  74. continue;
  75.  
  76. // create a new entry and set it's handle ref
  77. var tmp = entry.Clone();
  78. tmp.IndexOrdinal = i;
  79. yield return tmp;
  80. }
  81.  
  82. i++;
  83. }
  84.  
  85. yield break;
  86. }
  87.  
  88. /// <summary>
  89. /// Creates the blob in a temporary location
  90. /// </summary>
  91. /// <param name="entries"></param>
  92. /// <param name="filename"></param>
  93. private void WriteTempBlob(IList<IndexEntry> entries, string filename)
  94. {
  95. using (var fs = File.Create(filename))
  96. {
  97. foreach (var entry in entries)
  98. {
  99. // copy the data from the original archive
  100. _handles[entry.IndexOrdinal].Position = entry.Offset;
  101. _handles[entry.IndexOrdinal].PartialCopyTo(fs, (long)entry.CompressedSize);
  102.  
  103. // reset the handle ref
  104. entry.IndexOrdinal = 0;
  105. }
  106. }
  107. }
  108.  
  109. /// <summary>
  110. /// Closes all open handles to the blobs
  111. /// </summary>
  112. private void ClearHandles()
  113. {
  114. _handles.ForEach(x => x?.Dispose());
  115. }
  116. }
  117. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement