Skip to content

Commit

Permalink
Expose ExecuteQuerySafe as part of the IDatabase interface (very curs…
Browse files Browse the repository at this point in the history
…ed). Fix DC when checking profiles of characters on other servers, and possible lurking DB lock in ClanClanPartnerPawnDataGetHandler.
  • Loading branch information
RyanYappert committed Jan 10, 2025
1 parent 4d9eb6d commit 3d1fd45
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 197 deletions.
4 changes: 3 additions & 1 deletion Arrowgene.Ddon.Database/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ void ExecuteReader(
Action<DbCommand> commandAction,
Action<DbDataReader> readAction
);
void ExecuteQuerySafe(DbConnection? connectionIn, Action<DbConnection> work);
T ExecuteQuerySafe<T>(DbConnection? connectionIn, Func<DbConnection, T> work);

// Generic functions for getting/setting
void AddParameter(DbCommand command, string name, object? value, DbType type);
Expand Down Expand Up @@ -120,7 +122,7 @@ CDataPawnSearchParameter searchParams
);
bool DeletePawn(uint pawnId);
bool UpdatePawnBaseInfo(Pawn pawn);
uint GetPawnOwnerCharacterId(uint pawnId);
uint GetPawnOwnerCharacterId(uint pawnId, DbConnection? connectionIn = null);
bool ReplacePawnReaction(uint pawnId, CDataPawnReaction pawnReaction, DbConnection? connectionIn = null);

// Pawn Training Status
Expand Down
13 changes: 13 additions & 0 deletions Arrowgene.Ddon.Database/Sql/Core/DdonSqlDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,19 @@ public void ExecuteQuerySafe(DbConnection? connectionIn, Action<TCon> work)
}
}

// Wrestling with generics; the interface is not happy to expose a generic,
// but a bunch of DB functions break if you don't allow the generic.
// This is the compromise.
public void ExecuteQuerySafe(DbConnection? connectionIn, Action<DbConnection> work)
{
ExecuteQuerySafe(connectionIn, (Action<TCon>)work);
}

public T ExecuteQuerySafe<T>(DbConnection? connectionIn, Func<DbConnection, T> work)
{
return ExecuteQuerySafe(connectionIn, (Func<TCon, T>)work);
}

public bool MigrateDatabase(DatabaseMigrator migrator, uint toVersion)
{
uint currentVersion = GetMeta().DatabaseVersion;
Expand Down
39 changes: 18 additions & 21 deletions Arrowgene.Ddon.Database/Sql/Core/DdonSqlDbPawn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,31 +306,28 @@ CDataPawnSearchParameter searchParams
return registeredPawns;
}

public uint GetPawnOwnerCharacterId(uint pawnId)
{
using TCon connection = OpenNewConnection();
return GetPawnOwnerCharacterId(connection, pawnId);
}

public uint GetPawnOwnerCharacterId(TCon connection, uint pawnId)
public uint GetPawnOwnerCharacterId(uint pawnId, DbConnection? connectionIn = null)
{
uint ownerCharacterId = 0;
ExecuteReader(
connection,
SqlSelectPawnOwnerId,
command =>
{
AddParameter(command, "@pawn_id", pawnId);
},
reader =>
{
if (reader.Read())
ExecuteQuerySafe(connectionIn, connection =>
{
ExecuteReader(
connection,
SqlSelectPawnOwnerId,
command =>
{
AddParameter(command, "@pawn_id", pawnId);
},
reader =>
{
ownerCharacterId = GetUInt32(reader, "character_id");
if (reader.Read())
{
ownerCharacterId = GetUInt32(reader, "character_id");
}
}
}
);

);
});
return ownerCharacterId;
}

Expand Down
54 changes: 30 additions & 24 deletions Arrowgene.Ddon.GameServer/Characters/CharacterManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,45 +33,51 @@ public CharacterManager(DdonGameServer server)

public Character SelectCharacter(GameClient client, uint characterId, DbConnection? connectionIn = null)
{
Character character = SelectCharacter(characterId, connectionIn);
Character character = SelectCharacter(characterId, connectionIn:connectionIn);
client.Character = character;
client.UpdateIdentity();

return character;
}

public Character SelectCharacter(uint characterId, DbConnection? connectionIn = null)
public Character SelectCharacter(uint characterId, bool fetchPawns = true, DbConnection? connectionIn = null)
{
Character character = _Server.Database.SelectCharacter(characterId, connectionIn);
if (character == null)
return _Server.Database.ExecuteQuerySafe(connectionIn, connectionIn =>
{
return null;
}
Character character = _Server.Database.SelectCharacter(characterId, connectionIn);
if (character == null)
{
return null;
}

character.Server = _Server.AssetRepository.ServerList.Where(server => server.Id == _Server.Id).Single().ToCDataGameServerListInfo();
character.Equipment = character.Storage.GetCharacterEquipment();
character.Server = _Server.AssetRepository.ServerList.Where(server => server.Id == _Server.Id).Single().ToCDataGameServerListInfo();
character.Equipment = character.Storage.GetCharacterEquipment();

character.ExtendedParams = _Server.Database.SelectOrbGainExtendParam(character.CommonId, connectionIn);
if (character.ExtendedParams == null)
{
// Old DB is in use and new table not populated with required data for character
Logger.Error($"Character: AccountId={character.AccountId}, CharacterId={character.CharacterId}, CommonId={character.CommonId} is missing table entry in 'ddon_orb_gain_extend_param'.");
return null;
}
character.ExtendedParams = _Server.Database.SelectOrbGainExtendParam(character.CommonId, connectionIn);
if (character.ExtendedParams == null)
{
// Old DB is in use and new table not populated with required data for character
Logger.Error($"Character: AccountId={character.AccountId}, CharacterId={character.CharacterId}, CommonId={character.CommonId} is missing table entry in 'ddon_orb_gain_extend_param'.");
return null;
}

character.EpitaphRoadState.UnlockedContent = _Server.Database.GetEpitaphRoadUnlocks(character.CharacterId, connectionIn);
character.EpitaphRoadState.UnlockedContent = _Server.Database.GetEpitaphRoadUnlocks(character.CharacterId, connectionIn);

if (_Server.GameLogicSettings.EnableEpitaphWeeklyRewards)
{
character.EpitaphRoadState.WeeklyRewardsClaimed = _Server.Database.GetEpitaphClaimedWeeklyRewards(character.CharacterId, connectionIn);
}

if (_Server.GameLogicSettings.EnableEpitaphWeeklyRewards)
{
character.EpitaphRoadState.WeeklyRewardsClaimed = _Server.Database.GetEpitaphClaimedWeeklyRewards(character.CharacterId, connectionIn);
}

UpdateCharacterExtendedParams(character);

SelectPawns(character, connectionIn);
UpdateCharacterExtendedParams(character);

return character;
if (fetchPawns)
{
SelectPawns(character, connectionIn);
}

return character;
});
}

private void SelectPawns(Character character, DbConnection? connectionIn = null)
Expand Down
Loading

0 comments on commit 3d1fd45

Please sign in to comment.