/*
* Copyright Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ehcache.clustered.server.store;
import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage;
import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse;
import org.ehcache.clustered.server.ClusterTierManagerActiveEntity;
import org.ehcache.clustered.server.EhcacheStateServiceImpl;
import org.terracotta.entity.ActiveServerEntity;
import org.terracotta.entity.ClientDescriptor;
import org.terracotta.entity.ConcurrencyStrategy;
import org.terracotta.entity.ConfigurationException;
import org.terracotta.entity.EntityServerService;
import org.terracotta.entity.ExecutionStrategy;
import org.terracotta.entity.MessageCodec;
import org.terracotta.entity.ServiceRegistry;
import org.terracotta.entity.SyncMessageCodec;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ObservableClusterTierServerEntityService
implements EntityServerService<EhcacheEntityMessage, EhcacheEntityResponse> {
private final ClusterTierServerEntityService delegate = new ClusterTierServerEntityService();
private final List<ClusterTierActiveEntity> servedActiveEntities = new ArrayList<>();
private final List<ClusterTierPassiveEntity> servedPassiveEntities = new ArrayList<>();
public List<ObservableClusterTierActiveEntity> getServedActiveEntities() throws NoSuchFieldException, IllegalAccessException {
List<ObservableClusterTierActiveEntity> observables = new ArrayList<ObservableClusterTierActiveEntity>(servedActiveEntities.size());
for (ClusterTierActiveEntity servedActiveEntity : servedActiveEntities) {
observables.add(new ObservableClusterTierActiveEntity(servedActiveEntity));
}
return Collections.unmodifiableList(observables);
}
public List<ObservableClusterTierPassiveEntity> getServedPassiveEntities() throws Exception {
List<ObservableClusterTierPassiveEntity> observables = new ArrayList<>(servedPassiveEntities.size());
for (ClusterTierPassiveEntity servedPassiveEntity : servedPassiveEntities) {
observables.add(new ObservableClusterTierPassiveEntity(servedPassiveEntity));
}
return Collections.unmodifiableList(observables);
}
@Override
public long getVersion() {
return delegate.getVersion();
}
@Override
public boolean handlesEntityType(String typeName) {
return delegate.handlesEntityType(typeName);
}
@Override
public ClusterTierActiveEntity createActiveEntity(ServiceRegistry registry, byte[] configuration) throws ConfigurationException {
ClusterTierActiveEntity activeEntity = delegate.createActiveEntity(registry, configuration);
servedActiveEntities.add(activeEntity);
return activeEntity;
}
@Override
public ClusterTierPassiveEntity createPassiveEntity(ServiceRegistry registry, byte[] configuration) throws ConfigurationException {
ClusterTierPassiveEntity passiveEntity = delegate.createPassiveEntity(registry, configuration);
servedPassiveEntities.add(passiveEntity);
return passiveEntity;
}
@Override
public ConcurrencyStrategy<EhcacheEntityMessage> getConcurrencyStrategy(byte[] config) {
return delegate.getConcurrencyStrategy(config);
}
@Override
public ExecutionStrategy<EhcacheEntityMessage> getExecutionStrategy(byte[] configuration) {
return delegate.getExecutionStrategy(configuration);
}
@Override
public MessageCodec<EhcacheEntityMessage, EhcacheEntityResponse> getMessageCodec() {
return delegate.getMessageCodec();
}
@Override
public SyncMessageCodec<EhcacheEntityMessage> getSyncMessageCodec() {
return delegate.getSyncMessageCodec();
}
/**
* Provides access to unit test state methods in an {@link ClusterTierManagerActiveEntity} instance.
*/
public static final class ObservableClusterTierActiveEntity {
private final ClusterTierActiveEntity activeEntity;
private ObservableClusterTierActiveEntity(ClusterTierActiveEntity activeEntity) throws NoSuchFieldException, IllegalAccessException {
this.activeEntity = activeEntity;
}
public ActiveServerEntity<EhcacheEntityMessage, EhcacheEntityResponse> getActiveEntity() {
return this.activeEntity;
}
public Set<ClientDescriptor> getConnectedClients() {
return activeEntity.getConnectedClients();
}
public Set<ClientDescriptor> getAttachedClients() {
return activeEntity.getAttachedClients();
}
public Map getClientsWaitingForInvalidation() throws Exception {
Field field = activeEntity.getClass().getDeclaredField("clientsWaitingForInvalidation");
field.setAccessible(true);
return (Map)field.get(activeEntity);
}
}
public static final class ObservableClusterTierPassiveEntity {
private final ClusterTierPassiveEntity passiveEntity;
private final EhcacheStateServiceImpl ehcacheStateService;
private ObservableClusterTierPassiveEntity(ClusterTierPassiveEntity passiveEntity) throws Exception {
this.passiveEntity = passiveEntity;
Field field = passiveEntity.getClass().getDeclaredField("stateService");
field.setAccessible(true);
this.ehcacheStateService = (EhcacheStateServiceImpl)field.get(passiveEntity);
}
public Map getMessageTrackerMap(String storeAlias) throws Exception {
Field field = this.ehcacheStateService.getClientMessageTracker(storeAlias).getClass().getDeclaredField("clientUUIDMessageTrackerMap");
field.setAccessible(true);
return (Map)field.get(this.ehcacheStateService.getClientMessageTracker(storeAlias));
}
}
}