/*******************************************************************************
* Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved
*
* 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.cloudifysource.rest.events.cache;
import com.gigaspaces.log.LogEntries;
import com.gigaspaces.log.LogEntry;
import com.gigaspaces.log.LogEntryMatcher;
import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import org.cloudifysource.dsl.rest.response.DeploymentEvent;
import org.cloudifysource.dsl.rest.response.DeploymentEvents;
import org.cloudifysource.rest.events.EventsUtils;
import org.cloudifysource.rest.events.LogEntryMatcherProvider;
import org.cloudifysource.rest.events.LogEntryMatcherProviderKey;
import org.openspaces.admin.gsc.GridServiceContainer;
import org.openspaces.admin.pu.ProcessingUnit;
import org.openspaces.admin.pu.ProcessingUnitInstance;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
/**
* Created with IntelliJ IDEA.
* User: elip
* Date: 5/20/13
* Time: 2:09 PM
* <br/><br/>
* The cache loader used to load events to the events cache.
* implements load, for initial load. and reload, for continues cache population.
*
* Load and reload operation will execute a remote call to fetch container logs.
* These logs are then translated to events and saved inside the cache.
*
* @see org.cloudifysource.dsl.rest.response.DeploymentEvents
*
*/
public class EventsCacheLoader extends CacheLoader<EventsCacheKey, EventsCacheValue> {
private static final Logger logger = Logger.getLogger(EventsCacheLoader.class.getName());
private final LogEntryMatcherProvider matcherProvider;
private final GridServiceContainerProvider containerProvider;
public EventsCacheLoader(final GridServiceContainerProvider containerProvider) {
this.matcherProvider = new LogEntryMatcherProvider();
this.containerProvider = containerProvider;
}
@Override
public EventsCacheValue load(final EventsCacheKey key) throws Exception {
logger.fine(EventsUtils.getThreadId() + "Could not find events for key " + key
+ " in cache. Loading from container logs...");
DeploymentEvents events = new DeploymentEvents();
// initial load. no events are present in the cache for this deployment.
// iterate over all container and retrieve logs from logs cache.
Set<GridServiceContainer> containersForDeployment = containerProvider
.getContainersForDeployment(key.getDeploymentId());
Set<ProcessingUnit> processingUnitsForDeployment = new HashSet<ProcessingUnit>();
int index = 0;
for (GridServiceContainer container : containersForDeployment) {
ProcessingUnitInstance[] processingUnitInstances = container.getProcessingUnitInstances();
if (processingUnitInstances != null && processingUnitInstances.length > 0) {
processingUnitsForDeployment.add(processingUnitInstances[0].getProcessingUnit());
}
LogEntryMatcherProviderKey logEntryMatcherProviderKey = createKey(container, key);
if (container.isDiscovered()) {
LogEntries logEntries = container.logEntries(matcherProvider.get(logEntryMatcherProviderKey));
for (LogEntry logEntry : logEntries) {
if (logEntry.isLog()) {
DeploymentEvent event = EventsUtils.logToEvent(logEntry,
logEntries.getHostName(), logEntries.getHostAddress());
event.setIndex(++index);
events.getEvents().add(event);
}
}
}
}
EventsCacheValue value = new EventsCacheValue();
value.setLastEventIndex(index);
value.setEvents(events);
value.getProcessingUnits().addAll(processingUnitsForDeployment);
value.setContainers(containersForDeployment);
value.setLastRefreshedTimestamp(System.currentTimeMillis());
return value;
}
@Override
public ListenableFuture<EventsCacheValue> reload(final EventsCacheKey key, final EventsCacheValue oldValue)
throws Exception {
logger.fine(EventsUtils.getThreadId() + "Reloading events cache entry for key " + key);
// pickup any new containers along with the old ones
oldValue.getContainers().addAll(containerProvider.getContainersForDeployment(key.getDeploymentId()));
if (!oldValue.getContainers().isEmpty()) {
int index = oldValue.getLastEventIndex();
for (GridServiceContainer container : oldValue.getContainers()) {
// this will give us just the new logs.
LogEntryMatcherProviderKey logEntryMatcherProviderKey = createKey(container, key);
LogEntryMatcher matcher = matcherProvider.get(logEntryMatcherProviderKey);
if (container.isDiscovered()) {
// don't fetch logs from undiscovered containers
logger.fine(EventsUtils.getThreadId() + "Retrieving logs from container " + container.getUid() +
container.getExactZones().getZones());
LogEntries logEntries = container.logEntries(matcher);
for (LogEntry logEntry : logEntries) {
if (logEntry.isLog()) {
logger.finest(EventsUtils.getThreadId() + "Found log " + logEntry.getText() + " for " +
"deployment id " + key.getDeploymentId() + " from container "
+ container.getUid() + container.getExactZones().getZones());
DeploymentEvent event = EventsUtils.logToEvent(
logEntry, logEntries.getHostName(), logEntries.getHostAddress());
event.setIndex(++index);
oldValue.getEvents().getEvents().add(event);
}
}
} else {
logger.fine(EventsUtils.getThreadId() + "Not retrieving logs from container " + container.getUid()
+ container.getExactZones().getZones() + " since it is not discovered by the admin");
}
}
// update refresh time.
oldValue.setLastRefreshedTimestamp(System.currentTimeMillis());
oldValue.setLastEventIndex(index);
}
return Futures.immediateFuture(oldValue);
}
public LogEntryMatcherProvider getMatcherProvider() {
return matcherProvider;
}
private LogEntryMatcherProviderKey createKey(final GridServiceContainer container,
final EventsCacheKey key) {
LogEntryMatcherProviderKey logEntryMatcherProviderKey = new LogEntryMatcherProviderKey();
logEntryMatcherProviderKey.setDeploymentId(key.getDeploymentId());
logEntryMatcherProviderKey.setContainer(container);
return logEntryMatcherProviderKey;
}
}