/** * Copyright (c) 2011-2014, OpenIoT * * This file is part of OpenIoT. * * OpenIoT is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, version 3 of the License. * * OpenIoT is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with OpenIoT. If not, see <http://www.gnu.org/licenses/>. * * Contact: OpenIoT mailto: info@openiot.eu */ package org.openiot.cupus.topkw; import java.io.Serializable; import java.util.HashSet; import java.util.LinkedList; import java.util.ListIterator; import java.util.Set; import java.util.UUID; import org.openiot.cupus.artefact.MemorizedPublication; import org.openiot.cupus.artefact.MemorySubscription; import org.openiot.cupus.artefact.Publication; import org.openiot.cupus.artefact.TopKWSubscription; import org.openiot.cupus.entity.broker.TopKWMatcher; import org.openiot.cupus.message.external.PublishMessage; /** * * @author Krešimir Pripužić <kpripuzic at gmail.com>, Eugen */ public class SASubscription extends MemorySubscription implements Serializable { private static final long serialVersionUID = 1L; private ExcellentSet excellent; private InfiniteGoodSet good; private FastSkyline[] collection; public SASubscription(UUID subscriber, TopKWSubscription subscription) { super(subscriber, subscription); this.excellent = new ExcellentSet(subscription.getK(), Float.NEGATIVE_INFINITY); this.good = new InfiniteGoodSet(); this.collection = new FastSkyline[subscription.getK()]; for (int i = 0; i < subscription.getK(); i++) { this.collection[i] = new FastSkyline(); } } @Override public synchronized boolean process(Publication publication, UUID publisher, ExpiringMemorizedPublications epubs, long time) { long pubValidity = time; if (time > (System.currentTimeMillis() + this.getW()) || time == -1) { pubValidity = System.currentTimeMillis() + this.getW(); } MemorizedPublication mp = new MemorizedPublication(publisher, publication, this, this.calculateRelevance(publication), pubValidity); LinkedList<MemorizedPublication> uDom = this.addToSkyband(mp, epubs); if (uDom == null) { //bad candidate return false; } if (mp.getRelevance() >= this.excellent.getThreshold()) { //excellent candidate //push to excellent and get overflow MemorizedPublication overflow = this.excellent.pushAndUpdate(mp); if (overflow != null) { //add overflow (worst from excellent) to good this.good.add(overflow); } //it is top-k //TODO: DELIVER this.getNotifier().send(mp.getPublication(), this.getSubscriber()); mp.setDelivered(true); //add excellent to expiring epubs.add(mp); this.removeDominated(uDom, epubs); return false; } else { //good candidate //add to good this.good.add(mp); //add good to expiring epubs.add(mp); this.removeDominated(uDom, epubs); return false; } } @Override public synchronized void remove(MemorizedPublication p) { this.removeFromSkyband(p); if (p.getRelevance() >= this.excellent.getThreshold()) { //excellent candidate this.excellent.remove(p); //get the best from good MemorizedPublication best = this.good.pollFirst(); if (best != null) { //add the best from good to excellent, updates threshold this.excellent.addLastAndUpdate(best); //deliver if it is top-k if (!best.isDelivered()) { this.getNotifier().send(best.getPublication(), this.getSubscriber()); best.setDelivered(true); } } else { //reset threshold, good is empty this.excellent.setThreshold(0); } } else { //if it is not excellent than it is good this.good.remove(p); } } @Override public double currentThreshold() { return this.excellent.getThreshold(); } public boolean contains(MemorizedPublication mp) { if (mp.getRelevance() > this.excellent.getThreshold()) { //excellent candidate return this.excellent.contains(mp); } else { //if it is not excellent than it is good return this.good.contains(mp); } } public int getExcellentSize() { return this.excellent.getSize(); } public int getGoodSize() { return this.good.getSize(); } private void removeFromSkyband(MemorizedPublication p) { int numAllDominators = 0; for (int i = 0; i < super.getK(); i++) { int numDominators = collection[i].getNumDominators(p); numAllDominators += numDominators; if (numAllDominators == i) { //remove it from its skyband collection[i].remove(p); //repair dominated for (int l = i + 1; l < super.getK(); l++) { LinkedList<MemorizedPublication> lDom = collection[l].pollDominated(p); if (!lDom.isEmpty()) { for (ListIterator<MemorizedPublication> j = lDom.listIterator(); j.hasNext();) { collection[l - 1].add(j.next()); } } } return; } } } private LinkedList<MemorizedPublication> addToSkyband(MemorizedPublication p, ExpiringMemorizedPublications epubs) { int numAllDominators = 0; for (int i = 0; i < super.getK(); i++) { int numDominators = collection[i].getNumDominators(p); numAllDominators += numDominators; if (numAllDominators == i) { //get and remove dominated LinkedList<MemorizedPublication> uDom = collection[i].pollDominated(p); //add it to its skyband collection[i].add(p); //remove all dominated for (int l = i + 1; l < super.getK(); l++) { LinkedList<MemorizedPublication> lDom = collection[l].pollDominated(p); if (!uDom.isEmpty()) { for (ListIterator<MemorizedPublication> j = uDom.listIterator(); j.hasNext();) { collection[l].add(j.next()); } } uDom = lDom; } return uDom; } else if (numAllDominators >= super.getK()) { //bad candidate return null; } } return null; } private void removeDominated(LinkedList<MemorizedPublication> uDom, ExpiringMemorizedPublications epubs) { for (ListIterator<MemorizedPublication> j = uDom.listIterator(); j.hasNext();) { MemorizedPublication d = j.next(); //remove d from other structures this.good.remove(d); epubs.remove(d); } } public boolean equals(Object sub) { if (this == sub) { return true; } if (sub instanceof SASubscription) { SASubscription saSub = (SASubscription) sub; return this.subscriber.equals(saSub.subscriber) && this.subscription.equals(saSub.subscription); } else { return false; } } @Override public boolean coversPublication(Publication pub) { System.err.println("coversPublication method of TopKWSubscription subscriptions" + " should not be used!"); return false; } @Override public String toString() { return subscription.toString(); } }