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

Save setting the same state in the Vertx local data duplicated context #34132

Merged
merged 1 commit into from
Jun 30, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ public void set(T state) {
Context context = Vertx.currentContext();
if (context != null && VertxContext.isDuplicatedContext(context)) {
VertxContextSafetyToggle.setContextSafe(context, true);
franz1981 marked this conversation as resolved.
Show resolved Hide resolved
context.putLocal(LOCAL_KEY, state);
// this is racy but should be fine, because DC should not be shared
// and never remove the existing mapping
franz1981 marked this conversation as resolved.
Show resolved Hide resolved
var oldState = context.getLocal(LOCAL_KEY);
if (oldState != state) {
context.putLocal(LOCAL_KEY, state);
mkouba marked this conversation as resolved.
Show resolved Hide resolved
}

} else {
fallback.set(state);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,7 @@ public void destroy(Contextual<?> contextual) {
@Override
public void activate(ContextState initialState) {
if (LOG.isTraceEnabled()) {
String stack = Arrays.stream(Thread.currentThread().getStackTrace())
.skip(2)
.limit(7)
.map(se -> "\n\t" + se.toString())
.collect(Collectors.joining());
LOG.tracef("Activate %s %s\n\t...",
initialState != null ? Integer.toHexString(initialState.hashCode()) : "new", stack);
traceActivate(initialState);
}
if (initialState == null) {
currentContext.set(new RequestContextState(new ConcurrentHashMap<>()));
Expand All @@ -145,6 +139,16 @@ public void activate(ContextState initialState) {
}
}

private void traceActivate(ContextState initialState) {
String stack = Arrays.stream(Thread.currentThread().getStackTrace())
.skip(2)
.limit(7)
.map(se -> "\n\t" + se.toString())
.collect(Collectors.joining());
LOG.tracef("Activate %s %s\n\t...",
initialState != null ? Integer.toHexString(initialState.hashCode()) : "new", stack);
}

@Override
public ContextState getState() {
RequestContextState state = currentContext.get();
Expand All @@ -162,16 +166,20 @@ public ContextState getStateIfActive() {
@Override
public void deactivate() {
if (LOG.isTraceEnabled()) {
String stack = Arrays.stream(Thread.currentThread().getStackTrace())
.skip(2)
.limit(7)
.map(se -> "\n\t" + se.toString())
.collect(Collectors.joining());
LOG.tracef("Deactivate%s\n\t...", stack);
traceDeactivate();
}
currentContext.remove();
}

private static void traceDeactivate() {
String stack = Arrays.stream(Thread.currentThread().getStackTrace())
.skip(2)
.limit(7)
.map(se -> "\n\t" + se.toString())
.collect(Collectors.joining());
LOG.tracef("Deactivate%s\n\t...", stack);
}

@Override
public void destroy() {
destroy(currentContext.get());
Expand All @@ -180,12 +188,7 @@ public void destroy() {
@Override
public void destroy(ContextState state) {
if (LOG.isTraceEnabled()) {
String stack = Arrays.stream(Thread.currentThread().getStackTrace())
.skip(2)
.limit(7)
.map(se -> "\n\t" + se.toString())
.collect(Collectors.joining());
LOG.tracef("Destroy %s%s\n\t...", state != null ? Integer.toHexString(state.hashCode()) : "", stack);
traceDestroy(state);
}
if (state == null) {
// nothing to destroy
Expand All @@ -210,6 +213,15 @@ public void destroy(ContextState state) {
}
}

private static void traceDestroy(ContextState state) {
String stack = Arrays.stream(Thread.currentThread().getStackTrace())
.skip(2)
.limit(7)
.map(se -> "\n\t" + se.toString())
.collect(Collectors.joining());
LOG.tracef("Destroy %s%s\n\t...", state != null ? Integer.toHexString(state.hashCode()) : "", stack);
}

private void destroyContextElement(Contextual<?> contextual, ContextInstanceHandle<?> contextInstanceHandle) {
try {
contextInstanceHandle.destroy();
Expand All @@ -236,6 +248,14 @@ private ContextNotActiveException notActive() {

static class RequestContextState implements ContextState {
franz1981 marked this conversation as resolved.
Show resolved Hide resolved

// Using 0 as default value enable removing an initialization
// in the constructor, piggybacking on the default value.
// As per https://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.5
// the default field values are set before 'this' is accessible, hence
// they should be the very first value observable even in presence of
// unsafe publication of this object.
private static final int VALID = 0;
private static final int INVALID = 1;
private static final VarHandle IS_VALID;

static {
Expand All @@ -251,7 +271,6 @@ static class RequestContextState implements ContextState {

RequestContextState(ConcurrentMap<Contextual<?>, ContextInstanceHandle<?>> value) {
this.map = Objects.requireNonNull(value);
this.isValid = 1;
}

@Override
Expand All @@ -265,12 +284,12 @@ public Map<InjectableBean<?>, Object> getContextualInstances() {
*/
boolean invalidate() {
// Atomically sets the value just like AtomicBoolean.compareAndSet(boolean, boolean)
return IS_VALID.compareAndSet(this, 1, 0);
return IS_VALID.compareAndSet(this, VALID, INVALID);
}

@Override
public boolean isValid() {
return isValid == 1;
return isValid == VALID;
}

}
Expand Down