/*
* Copyright 2014-2016 CyberVision, 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.kaaproject.kaa.server.operations.service.thrift;
import org.apache.thrift.TException;
import org.kaaproject.kaa.common.dto.ApplicationDto;
import org.kaaproject.kaa.common.dto.ProfileFilterDto;
import org.kaaproject.kaa.common.dto.ServerProfileSchemaDto;
import org.kaaproject.kaa.common.dto.VersionDto;
import org.kaaproject.kaa.common.hash.EndpointObjectHash;
import org.kaaproject.kaa.server.common.dao.ApplicationService;
import org.kaaproject.kaa.server.common.dao.ProfileService;
import org.kaaproject.kaa.server.common.dao.ServerProfileService;
import org.kaaproject.kaa.server.common.thrift.gen.operations.Message;
import org.kaaproject.kaa.server.common.thrift.gen.operations.Notification;
import org.kaaproject.kaa.server.common.thrift.gen.operations.Operation;
import org.kaaproject.kaa.server.common.thrift.gen.operations.OperationsThriftService;
import org.kaaproject.kaa.server.common.thrift.gen.operations.RedirectionRule;
import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftEndpointConfigurationRefreshMessage;
import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftEndpointDeregistrationMessage;
import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftEntityRouteMessage;
import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftServerProfileUpdateMessage;
import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftUnicastNotificationMessage;
import org.kaaproject.kaa.server.common.thrift.gen.operations.UserConfigurationUpdate;
import org.kaaproject.kaa.server.operations.service.akka.AkkaService;
import org.kaaproject.kaa.server.operations.service.cache.AppProfileVersionsKey;
import org.kaaproject.kaa.server.operations.service.cache.AppSeqNumber;
import org.kaaproject.kaa.server.operations.service.cache.CacheService;
import org.kaaproject.kaa.server.operations.service.cluster.ClusterService;
import org.kaaproject.kaa.server.operations.service.event.EventService;
import org.kaaproject.kaa.server.operations.service.initialization.OperationsInitializationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.security.PublicKey;
import java.util.List;
/**
* The implementation of {#link
* org.kaaproject.kaa.server.common.thrift.gen.operations
* .OperationsThriftService.Iface OperationsThriftService}. The only one
* specific method to Operations Service is {#link #onNotification(Notification
* notification) onNotification}
*
* @author Andrew Shvayka
*/
@Service
public class OperationsThriftServiceImpl implements OperationsThriftService.Iface {
/**
* The Constant LOG.
*/
private static final Logger LOG = LoggerFactory.getLogger(OperationsThriftServiceImpl.class);
/**
* The operations bootstrap service.
*/
@Autowired
OperationsInitializationService operationsBootstrapService;
/**
* The cache service.
*/
@Autowired
CacheService cacheService;
/**
* The akka service.
*/
@Autowired
AkkaService akkaService;
/**
* The application service.
*/
@Autowired
ApplicationService applicationService;
/**
* The event service.
*/
@Autowired
EventService eventService;
@Autowired
ClusterService clusterService;
@Autowired
ProfileService profileService;
@Autowired
ServerProfileService serverProfileService;
@Override
public void onNotification(Notification notification) throws TException {
LOG.debug("Received Notification from control service {}", notification);
LOG.debug("Going to notify cache service..");
processCacheNotification(notification);
if (notification.getOp() != Operation.APP_UPDATE) {
LOG.debug("Going to notify akka service..");
akkaService.onNotification(notification);
}
}
/*
* (non-Javadoc)
*
* @see org.kaaproject.kaa.server.common.thrift.gen.operations.
* OperationsThriftService
* .Iface#setRedirectionRule(org.kaaproject.kaa.server
* .common.thrift.gen.operations.RedirectionRule)
*/
@Override
public void setRedirectionRule(RedirectionRule redirectionRule) throws TException {
LOG.debug("Received setRedirectionRule from control Dynamic Load Mgmt service {}",
redirectionRule);
LOG.debug("Notify akka service..");
akkaService.onRedirectionRule(redirectionRule);
}
/*
* (non-Javadoc)
*
* @see org.kaaproject.kaa.server.common.thrift.gen.operations.
* OperationsThriftService.Iface#sendEventMessage(java.util.List)
*/
@Override
public void sendMessages(List<Message> messages) throws TException {
eventService.sendEventMessage(messages);
}
@Override
public void sendUserConfigurationUpdates(List<UserConfigurationUpdate> updates)
throws TException {
for (UserConfigurationUpdate update : updates) {
akkaService.onUserConfigurationUpdate(org.kaaproject.kaa.server.operations.service
.akka.messages.core.user.UserConfigurationUpdate.fromThrift(update));
}
}
/**
* Process cache notification.
*
* @param notification the notification
*/
private void processCacheNotification(Notification notification) {
ApplicationDto appDto = applicationService.findAppById(notification.getAppId());
LOG.debug("Processing cache notification {} for app {}", notification, appDto);
if (appDto != null) {
if (notification.getOp() == Operation.APP_UPDATE) {
LOG.debug("Reseting application info {}", appDto.getId());
cacheService.resetAppById(appDto.getId());
return;
}
if (notification.getProfileFilterId() != null) {
ProfileFilterDto filterDto = cacheService.getFilter(notification.getProfileFilterId());
LOG.debug("Processing filter {}", filterDto);
if (filterDto.getEndpointProfileSchemaId() != null
&& filterDto.getServerProfileSchemaId() != null) {
cacheService.resetFilters(new AppProfileVersionsKey(
appDto.getApplicationToken(), filterDto
.getEndpointProfileSchemaVersion(), filterDto.getServerProfileSchemaVersion()));
} else if (filterDto.getServerProfileSchemaVersion() == null) {
for (VersionDto version
: profileService.findProfileSchemaVersionsByAppId(appDto.getId())) {
LOG.debug("Processing version {}", version);
cacheService.resetFilters(new AppProfileVersionsKey(
appDto.getApplicationToken(), version.getVersion(), null));
}
} else {
for (ServerProfileSchemaDto version
: serverProfileService.findServerProfileSchemasByAppId(appDto.getId())) {
LOG.debug("Processing version {}", version);
cacheService.resetFilters(new AppProfileVersionsKey(
appDto.getApplicationToken(), null, version.getVersion()));
}
}
}
if (notification.getGroupId() != null) {
cacheService.resetGroup(notification.getGroupId());
}
if (notification.getAppSeqNumber() != 0) {
LOG.debug("Going to update application {} with seqNumber {} in thread {}",
appDto.getApplicationToken(),
notification.getAppSeqNumber(), Thread.currentThread().getId());
synchronized (cacheService) {
int currentSeqNumber = cacheService.getAppSeqNumber(
appDto.getApplicationToken()).getSeqNumber();
if (currentSeqNumber < notification.getAppSeqNumber()) {
cacheService.putAppSeqNumber(
appDto.getApplicationToken(),
new AppSeqNumber(appDto.getTenantId(), appDto.getId(),
appDto.getApplicationToken(), notification.getAppSeqNumber()));
LOG.debug("Update application {} with seqNumber {} in thread {}",
appDto.getApplicationToken(),
notification.getAppSeqNumber(), Thread.currentThread().getId());
} else {
LOG.debug("Update ignored. application {} already has seqNumber {}",
appDto.getApplicationToken(),
notification.getAppSeqNumber());
}
}
}
} else {
LOG.warn("Application with following id is not found ", notification.getAppId());
}
}
@Override
public void onEntityRouteMessages(List<ThriftEntityRouteMessage> msgs) throws TException {
clusterService.onEntityRouteMessages(msgs);
}
@Override
public void onUnicastNotification(ThriftUnicastNotificationMessage message) throws TException {
clusterService.onUnicastNotificationMessage(message);
}
@Override
public void onServerProfileUpdate(ThriftServerProfileUpdateMessage message) throws TException {
clusterService.onServerProfileUpdateMessage(message);
}
@Override
public void onEndpointDeregistration(ThriftEndpointDeregistrationMessage message)
throws TException {
LOG.debug("Received Event about endpoint deregistration {}", message);
byte[] address = message.getAddress().getEntityId();
EndpointObjectHash hash = EndpointObjectHash.fromBytes(address);
clusterService.onEndpointDeregistrationMessage(message);
PublicKey endpointPublickKey = cacheService.getEndpointKey(hash);
if (endpointPublickKey != null) {
cacheService.resetEndpointKey(hash, endpointPublickKey);
}
}
@Override
public void sendEndpointConfigurationRefreshMessage(ThriftEndpointConfigurationRefreshMessage message) throws TException {
clusterService.sendEndpointConfigurationRefreshMessage(message);
}
}