/* * Copyright 2015-2017 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * 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.hawkular.alerts.engine.impl; import java.util.HashSet; import java.util.Set; /** * Auxiliary cache for AlertsEngine implementation. * * It stores a lightweight cache with active dataIds and pointers to triggerIds and conditionIds for the current node. * This cache allows to filter unnecessary data that is processed by the RulesEngine. * * This scenario works on single or distributed deployments. * In distributed deployments this helps to avoid unnecessary processing. * * @author Jay Shaughnessy * @author Lucas Ponce */ public class AlertsEngineCache { /** * It represents the Triggers -> Conditions relation hold on this node. * A single dataId can be part of several triggers or even several conditions. */ private Set<DataEntry> activeDataEntries; /** * A cache of the dataIds hold. Used to filter if a data has a dataId on this node or not. */ private Set<DataId> activeDataIds; public AlertsEngineCache() { activeDataEntries = new HashSet<>(); activeDataIds = new HashSet<>(); } /** * Check if a specific dataId is active on this node * * @param tenantId to check if has triggers deployed on this node * @param dataId to check if it has triggers deployed on this node * @return true if it is active * false otherwise */ public boolean isDataIdActive(String tenantId, String dataId) { return tenantId != null && dataId != null && activeDataIds.contains(new DataId(tenantId, dataId)); } /** * Register a new DataEntry (triggerId,conditionId,dataId) * * @param dataEntry to register on this node */ public void add(DataEntry dataEntry) { activeDataEntries.add(dataEntry); DataId newDataId = new DataId(dataEntry.getTenantId(), dataEntry.getDataId()); if (!activeDataIds.contains(newDataId)) { activeDataIds.add(newDataId); } } /** * Remove all DataEntry for a specified trigger. * * @param triggerId to remove */ public void remove(String tenantId, String triggerId) { if (tenantId == null) { throw new IllegalArgumentException("tenantId must be not null"); } if (triggerId == null) { throw new IllegalArgumentException("triggerId must be not null"); } Set<DataEntry> dataEntriesToRemove = new HashSet<>(); activeDataEntries.stream().forEach(e -> { if (e.getTenantId().equals(tenantId) && e.getTriggerId().equals(triggerId)) { dataEntriesToRemove.add(e); } }); activeDataEntries.removeAll(dataEntriesToRemove); Set<DataId> dataIdToCheck = new HashSet<>(); dataEntriesToRemove.stream().forEach(e -> { dataIdToCheck.add(new DataId(e.getTenantId(), e.getDataId())); }); Set<DataId> dataIdToRemove = new HashSet<>(); dataIdToCheck.stream().forEach(dataId -> { boolean found = false; for (DataEntry entry : activeDataEntries) { DataId currentDataId = new DataId(entry.getTenantId(), entry.getDataId()); if (currentDataId.equals(dataId)) { found = true; break; } } if (!found) { dataIdToRemove.add(dataId); } }); activeDataIds.removeAll(dataIdToRemove); } /** * Clear all cache entries. */ public void clear() { activeDataEntries.clear(); activeDataIds.clear(); } public static class DataId { String tenantId; String dataId; public DataId(String tenantId, String dataId) { this.tenantId = tenantId; this.dataId = dataId; } public String getTenantId() { return tenantId; } public void setTenantId(String tenantId) { this.tenantId = tenantId; } public String getDataId() { return dataId; } public void setDataId(String dataId) { this.dataId = dataId; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; DataId dataId1 = (DataId) o; if (tenantId != null ? !tenantId.equals(dataId1.tenantId) : dataId1.tenantId != null) return false; return dataId != null ? dataId.equals(dataId1.dataId) : dataId1.dataId == null; } @Override public int hashCode() { int result = tenantId != null ? tenantId.hashCode() : 0; result = 31 * result + (dataId != null ? dataId.hashCode() : 0); return result; } @Override public String toString() { return "DataId{" + "tenantId='" + tenantId + '\'' + ", dataId='" + dataId + '\'' + '}'; } } public static class DataEntry { String tenantId; String triggerId; String dataId; public DataEntry(String tenantId, String triggerId, String dataId) { if (tenantId == null) { throw new NullPointerException("triggerId must be not null"); } if (triggerId == null) { throw new NullPointerException("triggerId must be not null"); } if (dataId == null) { throw new NullPointerException("dataId must be not null"); } this.tenantId = tenantId; this.triggerId = triggerId; this.dataId = dataId; } public String getTenantId() { return tenantId; } public void setTenantId(String tenantId) { this.tenantId = tenantId; } public String getTriggerId() { return triggerId; } public void setTriggerId(String triggerId) { this.triggerId = triggerId; } public String getDataId() { return dataId; } public void setDataId(String dataId) { this.dataId = dataId; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; DataEntry dataEntry = (DataEntry) o; if (tenantId != null ? !tenantId.equals(dataEntry.tenantId) : dataEntry.tenantId != null) return false; if (triggerId != null ? !triggerId.equals(dataEntry.triggerId) : dataEntry.triggerId != null) return false; return !(dataId != null ? !dataId.equals(dataEntry.dataId) : dataEntry.dataId != null); } @Override public int hashCode() { int result = tenantId != null ? tenantId.hashCode() : 0; result = 31 * result + (triggerId != null ? triggerId.hashCode() : 0); result = 31 * result + (dataId != null ? dataId.hashCode() : 0); return result; } @Override public String toString() { return "DataEntry" + '[' + "tenantId='" + tenantId + '\'' + ", triggerId='" + triggerId + '\'' + ", dataId='" + dataId + '\'' + ']'; } } }