Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

CSHARP-5349: Fix discriminator convention inheritance. #1512

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

Merged
rstam merged 1 commit into mongodb:main from rstam:csharp5349
Nov 22, 2024

Conversation

@rstam
Copy link
Contributor

@rstam rstam commented Oct 23, 2024

No description provided.

jizc reacted with hooray emoji jizc reacted with heart emoji
@rstam rstam requested a review from a team as a code owner October 23, 2024 23:44

if (classMap._isRootClass)
{
return StandardDiscriminatorConvention.Hierarchical;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is still wrong... there just isn't a test to show that it is.

Consider this scenario: there might be a registered discriminator convention at this level and we're not looking it up.

if (classMap._isRootClass)
{
// in this case auto-register a hierarchical convention for the root class and look it up as usual below
BsonSerializer.GetOrRegisterDiscriminatorConvention(classMap._classType, StandardDiscriminatorConvention.Hierarchical);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling GetOrRegisterDiscriminatorConvention instead of RegsiterDiscriminatorConvention is in order to avoid collisions between threads.

Copy link
Contributor

@adelinowona adelinowona Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does it avoid collisions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new GetOrRegisterDiscriminatorConvention method uses the same lock as RegsiterDiscriminatorConvention to handle thread safety.

}
}

internal static IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, IDiscriminatorConvention discriminatorConvention)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These don't need to be public.

Comment on lines 274 to 285
__configLock.EnterReadLock();
try
{
if (__discriminatorConventions.TryGetValue(type, out var registeredConvention))
{
return registeredConvention;
}
}
finally
{
__configLock.ExitReadLock();
}
Copy link
Contributor

@adelinowona adelinowona Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this whole block really needed? Seems a bit redundant to check for a registered convention here and then check again later on below when trying to register.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may seem redundant but it's not. All the other methods use the same pattern.

The idea is that after the initial configuration phase is over everything can be done with read lock only, eliminating lock contention between threads.

The second check below is because of multithreading. Between releasing the read lock and acquiring the write lock some other thread might have snuck in and registered the convention.

Copy link
Contributor

@adelinowona adelinowona left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rstam rstam requested review from damieng and papafe October 28, 2024 16:03
@rstam rstam requested a review from sanych-sun November 1, 2024 02:57
if (classMap._isRootClass)
{
// in this case auto-register a hierarchical convention for the root class and look it up as usual below
BsonSerializer.GetOrRegisterDiscriminatorConvention(classMap._classType, StandardDiscriminatorConvention.Hierarchical);
Copy link
Member

@sanych-sun sanych-sun Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does GetOrRegisterDiscriminatorConvention returns the value we are looking for? Can we return it straight away without additional lookup below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling LookupDiscriminatorConvention below has some side effects that we don't want to skip.

The main side effect is that it registers the convention at all levels between the _classType and where the discriminator convention is found.

{
return registeredConvention;
}
else
Copy link
Member

@sanych-sun sanych-sun Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: this else block if unnecessary as there is return in true path of the check. Can simplify it to reduce the nesting level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True... but at the same time the two conditions are mutually exclusive and the else makes that clearer in some ways.

Nevertheless changed it as requested.

}
}

internal static IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, IDiscriminatorConvention discriminatorConvention)
Copy link
Member

@sanych-sun sanych-sun Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest to have slightly different method signature to mimic ConcurrentDictionary.GetOrAdd method signature:

internal static IDiscriminatorConvention GetOrAddDiscriminatorConvention(Type type, Func<Type, IDiscriminatorConvention> discriminatorConventionFactory)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@sanych-sun sanych-sun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@sanych-sun sanych-sun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rstam rstam merged commit b802157 into mongodb:main Nov 22, 2024
1 check was pending
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@papafe papafe papafe approved these changes

@sanych-sun sanych-sun sanych-sun approved these changes

@adelinowona adelinowona adelinowona approved these changes

@damieng damieng Awaiting requested review from damieng

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /