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

[PAYARA-3860] - Added synchronization block double check to avoid race condition #4021

Merged
merged 5 commits into from
Jun 11, 2019
Merged
Changes from 4 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
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2016-2018 Payara Foundation and/or its affiliates. All rights reserved.
* Copyright (c) 2016-2019 Payara Foundation and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
Expand Down Expand Up @@ -37,7 +37,6 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/

package fish.payara.appserver.micro.services;

import java.io.Serializable;
Expand Down Expand Up @@ -111,12 +110,12 @@ public class PayaraInstanceImpl implements EventListener, MessageReceiver, Payar
public static final String CDI_EVENTS_NAME = "payara.micro.cdi.event";

public static final String APPLICATIONS_STORE_NAME = "payara.micro.applications.store";

private static final Logger logger = Logger.getLogger(PayaraInstanceImpl.class.getName());

@Inject
private ServiceLocator habitat;

@Inject
private PayaraCluster cluster;

Expand All @@ -139,19 +138,26 @@ public class PayaraInstanceImpl implements EventListener, MessageReceiver, Payar
private String instanceGroup;

private InstanceDescriptorImpl me;

@Inject
private ServerEnvironment environment;

@Inject
private HazelcastCore hazelcast;

@Inject
private ApplicationRegistry appRegistry;

@Inject
private PayaraExecutorService executor;

private synchronized InstanceDescriptorImpl getMyInstanceDescriptor() {
if(me == null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

space after if, please

initialiseInstanceDescriptor();
}
return me;
}

@Override
public String getInstanceName() {
return instanceName;
Expand All @@ -162,8 +168,6 @@ public void setInstanceName(String instanceName) {
this.instanceName = instanceName;
me.setInstanceName(instanceName);
}



@Override
public <T extends Serializable> Map<String, Future<T>> runCallable(Collection<String> memberUUIDS, Callable<T> callable) {
Expand Down Expand Up @@ -228,7 +232,7 @@ public void receiveMessage(ClusterMessage msg) {
void postConstruct() {
events.register(this);
myListeners = new HashSet<>(1);
myCDIListeners = new HashSet<>(1);
myCDIListeners = new HashSet<>(1);
}

/**
Expand All @@ -239,50 +243,46 @@ void postConstruct() {
@SuppressWarnings({"unchecked"})
public void event(Event event) {
if (event.is(EventTypes.SERVER_READY)) {
initialiseInstanceDescriptor();
PayaraInternalEvent pie = new PayaraInternalEvent(PayaraInternalEvent.MESSAGE.ADDED, me);
//initialiseInstanceDescriptor();
Copy link
Contributor

Choose a reason for hiding this comment

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

remove this one as well

PayaraInternalEvent pie = new PayaraInternalEvent(PayaraInternalEvent.MESSAGE.ADDED, getMyInstanceDescriptor());
ClusterMessage<PayaraInternalEvent> message = new ClusterMessage<>(pie);
this.cluster.getEventBus().publish(INTERNAL_EVENTS_NAME, message);

for (String appName : appRegistry.getAllApplicationNames()) {
me.addApplication(new ApplicationDescriptorImpl(appRegistry.get(appName)));
getMyInstanceDescriptor().addApplication(new ApplicationDescriptorImpl(appRegistry.get(appName)));
}
cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, me);

cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, getMyInstanceDescriptor());
executor.scheduleAtFixedRate(() -> {
me.setLastHeartBeat(System.currentTimeMillis());
getMyInstanceDescriptor().setLastHeartBeat(System.currentTimeMillis());
if (myCurrentID != null) {
cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, me);
cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, getMyInstanceDescriptor());
}
}, 0, 5, TimeUnit.SECONDS);
}
// Adds the application to the clustered register of deployed applications
} // Adds the application to the clustered register of deployed applications
else if (event.is(Deployment.APPLICATION_STARTED)) {
if (event.hook() != null && event.hook() instanceof ApplicationInfo) {
ApplicationInfo applicationInfo = (ApplicationInfo) event.hook();
if (me == null) {//race check
initialiseInstanceDescriptor();
}
me.addApplication(new ApplicationDescriptorImpl(applicationInfo));
getMyInstanceDescriptor().addApplication(new ApplicationDescriptorImpl(applicationInfo));
logger.log(Level.FINE, "App Loaded: {2}, Enabled: {0}, my ID: {1}", new Object[] { hazelcast.isEnabled(),
myCurrentID, applicationInfo.getName() });
cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, me);
cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, getMyInstanceDescriptor());
}
}
// removes the application from the clustered registry of applications
else if (event.is(Deployment.APPLICATION_UNLOADED)) {
if (event.hook() != null && event.hook() instanceof ApplicationInfo) {
ApplicationInfo applicationInfo = (ApplicationInfo) event.hook();
me.removeApplication(new ApplicationDescriptorImpl(applicationInfo));
cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, me);
getMyInstanceDescriptor().removeApplication(new ApplicationDescriptorImpl(applicationInfo));
cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, getMyInstanceDescriptor());
}
} else if (event.is(HazelcastEvents.HAZELCAST_SHUTDOWN_STARTED)) {
PayaraInternalEvent pie = new PayaraInternalEvent(PayaraInternalEvent.MESSAGE.REMOVED, me);
PayaraInternalEvent pie = new PayaraInternalEvent(PayaraInternalEvent.MESSAGE.REMOVED, getMyInstanceDescriptor());
ClusterMessage<PayaraInternalEvent> message = new ClusterMessage<>(pie);
this.cluster.getClusteredStore().remove(INSTANCE_STORE_NAME, myCurrentID);
this.cluster.getEventBus().publish(INTERNAL_EVENTS_NAME, message);
}

// When Hazelcast is bootstrapped, update the instance descriptor with any new information
if (event.is(HazelcastEvents.HAZELCAST_BOOTSTRAP_COMPLETE)) {
initialiseInstanceDescriptor();
Expand All @@ -293,7 +293,7 @@ else if (event.is(Deployment.APPLICATION_UNLOADED)) {
cluster.getEventBus().addMessageReceiver(INTERNAL_EVENTS_NAME, this);
cluster.getEventBus().addMessageReceiver(CDI_EVENTS_NAME, this);
}

// If the generated name had to be changed, update the instance descriptor with the new information
if (event.is(HazelcastEvents.HAZELCAST_GENERATED_NAME_CHANGE)) {
initialiseInstanceDescriptor();
Expand Down Expand Up @@ -360,7 +360,7 @@ private void initialiseInstanceDescriptor() {
boolean liteMember = false;
int hazelcastPort = 5900;
InetAddress hostname = null;

// Get the Hazelcast specific information
if (hazelcast.isEnabled()) {
instanceName = hazelcast.getMemberName();
Expand All @@ -373,10 +373,10 @@ private void initialiseInstanceDescriptor() {
instanceName = "payara-micro";
instanceGroup = "no-cluster";
}

// Get this instance's runtime type
String instanceType = environment.getRuntimeType().toString();

// Get the ports in use by this instance from its network listener configs
List<Integer> ports = new ArrayList<>();
List<Integer> sslPorts = new ArrayList<>();
Expand Down Expand Up @@ -422,8 +422,8 @@ private void initialiseInstanceDescriptor() {
}
}
}
}
}

// Initialise the instance descriptor and set all of its attributes
try {
// If Hazelcast is being rebooted dynamically, we don't want to lose the already registered applications
Expand All @@ -437,37 +437,37 @@ private void initialiseInstanceDescriptor() {
for (int port : ports) {
me.addHttpPort(port);
}

for (int sslPort : sslPorts) {
me.addHttpsPort(sslPort);
}

me.setAdminPort(adminPort);
me.setHazelcastPort(hazelcastPort);
me.setLiteMember(liteMember);
me.setInstanceType(instanceType);

if (hostname != null) {
me.setHostName(hostname);
}

// If there were some deployed applications from the previous instance descriptor, register them with the new
// one
if (!deployedApplications.isEmpty()) {
for (ApplicationDescriptor application : deployedApplications) {
me.addApplication(application);
}
}

// Register the instance descriptor to the cluster if it's enabled
if (cluster.isEnabled()) {
cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, me);
}
}
} catch (UnknownHostException ex) {
logger.log(Level.SEVERE, "Could not find local hostname", ex);
}
}

/**
* Checks whether or not this instance is in a Hazelcast cluster
* @return true if this instance is in a Hazelcast cluster
Expand Down