/**
* Copyright (C) 2015-2017 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
*
* This program 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, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* A copy of the GNU Lesser General Public License is in the file COPYING.
*/
package net.named_data.jndn.impl;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.named_data.jndn.Name;
import net.named_data.jndn.util.Common;
/**
* A RegisteredPrefixTable is an internal class to hold a list of registered
* prefixes with information necessary to remove the registration later.
*/
public class RegisteredPrefixTable {
/**
* Create a new RegisteredPrefixTable with an empty table.
* @param interestFilterTable See removeRegisteredPrefix(), which may call
* interestFilterTable.unsetInterestFilter().
*/
public RegisteredPrefixTable(InterestFilterTable interestFilterTable)
{
interestFilterTable_ = interestFilterTable;
}
/**
* Add a new entry to the table. However, if removeRegisteredPrefix was already
* called with the registeredPrefixId, don't add an entry and return false.
* @param registeredPrefixId The ID from Node.getNextEntryId().
* @param prefix The name prefix.
* @param relatedInterestFilterId (optional) The related interestFilterId
* for the filter set in the same registerPrefix operation. If omitted, set
* to 0.
* @return True if added an entry, false if removeRegisteredPrefix was already
* called with the registeredPrefixId.
*/
public synchronized final boolean
add(long registeredPrefixId, Name prefix, long relatedInterestFilterId)
{
int removeRequestIndex = removeRequests_.indexOf(registeredPrefixId);
if (removeRequestIndex >= 0) {
// removeRegisteredPrefix was called with the registeredPrefixId returned
// by registerPrefix before we got here, so don't add a registered
// prefix table entry.
removeRequests_.remove(removeRequestIndex);
return false;
}
table_.add(new Entry(registeredPrefixId, prefix, relatedInterestFilterId));
return true;
}
/**
* Remove the registered prefix entry with the registeredPrefixId from the
* registered prefix table. This does not affect another registered prefix with
* a different registeredPrefixId, even if it has the same prefix name. If an
* interest filter was automatically created by registerPrefix, also call
* interestFilterTable_.unsetInterestFilter to remove it.
* If there is no entry with the registeredPrefixId, do nothing.
* @param registeredPrefixId The ID returned from registerPrefix.
*/
public synchronized final void
removeRegisteredPrefix(long registeredPrefixId)
{
int count = 0;
// Go backwards through the list so we can remove entries.
// Remove all entries even though registeredPrefixId should be unique.
for (int i = table_.size() - 1; i >= 0; --i) {
Entry entry = table_.get(i);
if (entry.getRegisteredPrefixId() == registeredPrefixId) {
++count;
if (entry.getRelatedInterestFilterId() > 0)
// Remove the related interest filter.
interestFilterTable_.unsetInterestFilter
(entry.getRelatedInterestFilterId());
table_.remove(i);
}
}
if (count == 0)
logger_.log
(Level.WARNING, "removeRegisteredPrefix: Didn't find registeredPrefixId {0}",
registeredPrefixId);
if (count == 0) {
// The registeredPrefixId was not found. Perhaps this has been called before
// the callback in registerPrefix can add to the registered prefix table.
// Add this removal request which will be checked before adding to the
// registered prefix table.
if (removeRequests_.indexOf(registeredPrefixId) < 0)
// Not already requested, so add the request.
removeRequests_.add(registeredPrefixId);
}
}
/**
* A RegisteredPrefixTable.Entry holds a registeredPrefixId and information
* necessary to remove the registration later. It optionally holds a related
* interestFilterId if the InterestFilter was set in the same registerPrefix
* operation.
*/
private static class Entry {
/**
* Create a RegisteredPrefixTable.Entry with the given values.
* @param registeredPrefixId The ID from Node.getNextEntryId().
* @param prefix The name prefix.
* @param relatedInterestFilterId (optional) The related interestFilterId
* for the filter set in the same registerPrefix operation. If omitted, set
* to 0.
*/
public Entry
(long registeredPrefixId, Name prefix, long relatedInterestFilterId)
{
registeredPrefixId_ = registeredPrefixId;
prefix_ = prefix;
relatedInterestFilterId_ = relatedInterestFilterId;
}
/**
* Get the registeredPrefixId given to the constructor.
* @return The registeredPrefixId.
*/
public final long
getRegisteredPrefixId() { return registeredPrefixId_; }
/**
* Get the name prefix given to the constructor.
* @return The name prefix.
*/
public final Name
getPrefix() { return prefix_; }
/**
* Get the related interestFilterId given to the constructor.
* @return The related interestFilterId.
*/
public final long
getRelatedInterestFilterId() { return relatedInterestFilterId_; }
private final long registeredPrefixId_; /**< A unique identifier for this entry so it can be deleted */
private final Name prefix_;
private final long relatedInterestFilterId_;
}
private final ArrayList<Entry> table_ = new ArrayList<Entry>();
private final InterestFilterTable interestFilterTable_;
private final ArrayList<Long> removeRequests_ = new ArrayList<Long>();
private static final Logger logger_ = Logger.getLogger
(RegisteredPrefixTable.class.getName());
// This is to force an import of net.named_data.jndn.util.
private static Common dummyCommon_ = new Common();
}