Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Semaphore to address #23 #29

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
name: .NET Build & Test

on:
- push
- pull_request
- workflow_call
push:
pull_request:
workflow_call:
workflow_dispatch:

jobs:
build:
Expand All @@ -20,7 +21,7 @@ jobs:
with:
dotnet-version: 6.0.x

- uses: dotnet/nbgv@main
- uses: dotnet/nbgv@v0.4.1
id: nbgv

- name: Restore dependencies
Expand Down
25 changes: 25 additions & 0 deletions Nodsoft.WowsReplaysUnpack.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;

string samplePath = Path.Join(Directory.GetCurrentDirectory(), "../../../..", "Replay-Samples");
FileStream _GetReplayFile(string name) => File.OpenRead(Path.Join(samplePath, name));
Expand Down Expand Up @@ -49,6 +50,30 @@
// Console.WriteLine($"[{GetGroupString(msg)}] {msg.EntityId} : {msg.MessageContent}");
//}

const int CYCLE = 20;
async Task<UnpackedReplay[]> syncTasks(bool sync)
{
List<UnpackedReplay> unpackedReplays = new List<UnpackedReplay>();
if (sync)
{
for (int i = 0; i < CYCLE; i++)
{
replayUnpacker.GetUnpacker().Unpack(_GetReplayFile("good.wowsreplay"));
}
}
else
{
Parallel.ForEach(Enumerable.Range(0, CYCLE), (i) =>
{
unpackedReplays.Add(replayUnpacker.GetUnpacker().Unpack(_GetReplayFile("good.wowsreplay")));
});
}
return unpackedReplays.ToArray();
}

DateTime start = DateTime.Now;
await syncTasks(false);
Console.WriteLine(DateTime.Now - start);

var goodReplay = replayUnpacker.GetUnpacker().Unpack(_GetReplayFile("good.wowsreplay"));
var alphaReplay = replayUnpacker.GetUnpacker().Unpack(_GetReplayFile("press_account_alpha.wowsreplay"));
Expand Down Expand Up @@ -79,14 +104,14 @@

public class BattleLogic
{
public Statee State { get; set; }

Check warning on line 107 in Nodsoft.WowsReplaysUnpack.Console/Program.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'State' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public class Statee
{
[DataMember(Name = "missions")]
public Missions _missions { get; set; }

Check warning on line 111 in Nodsoft.WowsReplaysUnpack.Console/Program.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property '_missions' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public class Missions
{
public List<TeamsScore> teamsScore { get; set; }

Check warning on line 114 in Nodsoft.WowsReplaysUnpack.Console/Program.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'teamsScore' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public class TeamsScore
{
public ushort score { get; set; }
Expand All @@ -96,10 +121,10 @@
}
public static class ext
{
public static FixedDictionary GetAsDict(this Dictionary<string, object?> dict, string key) => dict[key] as FixedDictionary;

Check warning on line 124 in Nodsoft.WowsReplaysUnpack.Console/Program.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.
public static FixedList GetAsArr(this Dictionary<string, object?> dict, string key) => dict[key] as FixedList;

Check warning on line 125 in Nodsoft.WowsReplaysUnpack.Console/Program.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.
public static FixedDictionary GetAsDict(this FixedList list, int index) => list[index] as FixedDictionary;

Check warning on line 126 in Nodsoft.WowsReplaysUnpack.Console/Program.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.
public static T GetAsValue<T>(this FixedDictionary dict, string key) => (T)dict[key];

Check warning on line 127 in Nodsoft.WowsReplaysUnpack.Console/Program.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.
}

//static string GetGroupString(ReplayMessage msg) => msg.MessageGroup switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
using Xunit;


/*
* FIXME: Test parallelization is disabled due to a file loading issue.
*/
[assembly: CollectionBehavior(DisableTestParallelization = true)]
namespace Nodsoft.WowsReplaysUnpack.Tests;

/// <summary>
Expand Down
10 changes: 8 additions & 2 deletions Nodsoft.WowsReplaysUnpack/Services/ReplayUnpackerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.IO.Compression;
using System.Text;
using System.Text.Json;
using System.Threading;

namespace Nodsoft.WowsReplaysUnpack.Services;

Expand All @@ -21,6 +22,7 @@ public sealed class ReplayUnpackerService<TController> : ReplayUnpackerService,
private readonly JsonSerializerOptions _jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true };
private readonly IReplayDataParser _replayDataParser;
private readonly IReplayController _replayController;
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);

public ReplayUnpackerService(IReplayDataParser replayDataParser, TController replayController)
{
Expand Down Expand Up @@ -69,12 +71,13 @@ Seek to offset 4 in the replay file (skipping the magic number)
See http://wiki.vbaddict.net/pages/File_Replays for more details.
*/
options ??= new();

_semaphore.Wait();
BinaryReader binaryReader = new(stream);

byte[] signature = binaryReader.ReadBytes(4);
int jsonBlockCount = binaryReader.ReadInt32();

_semaphore.Release();
// Verify replay signature
if (!signature.SequenceEqual(ReplaySignature))
{
Expand All @@ -84,11 +87,13 @@ Seek to offset 4 in the replay file (skipping the magic number)
// The first block is the arena info
// Read it and create the unpacked replay model
UnpackedReplay replay = _replayController.CreateUnpackedReplay(ReadJsonBlock<ArenaInfo>(binaryReader));
_semaphore.Wait();
ReadExtraJsonBlocks(replay, binaryReader, jsonBlockCount);

MemoryStream decryptedStream = new();
Decrypt(binaryReader, decryptedStream);

_semaphore.Release();
// Initial stream and reader not used anymore
binaryReader.Dispose();

Expand All @@ -99,11 +104,12 @@ Seek to offset 4 in the replay file (skipping the magic number)
decryptedStream.Dispose();


_semaphore.Wait();
foreach (NetworkPacketBase networkPacket in _replayDataParser.ParseNetworkPackets(replayDataStream, options))
{
_replayController.HandleNetworkPacket(networkPacket, options);
}

_semaphore.Release();
return replay;
}

Expand Down
Loading