package socialkademlia.dht; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import kademlia.dht.GetParameter; import kademlia.dht.KadContent; import kademlia.exceptions.ContentExistException; import kademlia.exceptions.ContentNotFoundException; import kademlia.node.KademliaId; /** * It would be infeasible to keep all content in memory to be send when requested * Instead we store content into files * We use this Class to keep track of all content stored * * @author Joshua Kissoon * @since 20140226 */ class StoredContentManager { private final Map<KademliaId, List<SocialKademliaStorageEntryMetadata>> entries; { entries = new HashMap<>(); } /** * Add a new entry to our storage * * @param content The content to store a reference to */ public SocialKademliaStorageEntryMetadata put(KadContent content) throws ContentExistException { return this.put(new JSocialKademliaStorageEntryMetadata(content)); } /** * Add a new entry to our storage * * @param entry The StorageEntry to store */ public SocialKademliaStorageEntryMetadata put(SocialKademliaStorageEntryMetadata entry) throws ContentExistException { if (!this.entries.containsKey(entry.getKey())) { this.entries.put(entry.getKey(), new ArrayList<>()); } /* If this entry doesn't already exist, then we add it */ if (!this.contains(entry)) { this.entries.get(entry.getKey()).add(entry); return entry; } else { throw new ContentExistException("Content already exists on this DHT"); } } /** * Checks if our DHT has a Content for the given criteria * * @param param The parameters used to search for a content * * @return boolean */ public synchronized boolean contains(GetParameter param) { if (this.entries.containsKey(param.getKey())) { /* Content with this key exist, check if any match the rest of the search criteria */ for (SocialKademliaStorageEntryMetadata e : this.entries.get(param.getKey())) { /* If any entry satisfies the given parameters, return true */ if (e.satisfiesParameters(param)) { return true; } } } else { } return false; } /** * Check if a content exist in the DHT */ public synchronized boolean contains(KadContent content) { return this.contains(new GetParameter(content)); } /** * Check if a StorageEntry exist on this DHT */ public synchronized boolean contains(SocialKademliaStorageEntryMetadata entry) { return this.contains(new GetParameter(entry)); } /** * Checks if our DHT has a Content for the given criteria * * @param param The parameters used to search for a content * * @return List of content for the specific search parameters */ public SocialKademliaStorageEntryMetadata get(GetParameter param) throws NoSuchElementException { if (this.entries.containsKey(param.getKey())) { /* Content with this key exist, check if any match the rest of the search criteria */ for (SocialKademliaStorageEntryMetadata e : this.entries.get(param.getKey())) { /* If any entry satisfies the given parameters, return true */ if (e.satisfiesParameters(param)) { return e; } } /* If we got here, means we didn't find any entry */ throw new NoSuchElementException(); } else { throw new NoSuchElementException("No content exist for the given parameters"); } } public SocialKademliaStorageEntryMetadata get(SocialKademliaStorageEntryMetadata md) { return this.get(new GetParameter(md)); } /** * @return A list of all storage entries */ public synchronized List<SocialKademliaStorageEntryMetadata> getAllEntries() { List<SocialKademliaStorageEntryMetadata> entriesRet = new ArrayList<>(); for (List<SocialKademliaStorageEntryMetadata> entrySet : this.entries.values()) { if (entrySet.size() > 0) { entriesRet.addAll(entrySet); } } return entriesRet; } /** * @return A list of all storage entries for cached content */ public List<SocialKademliaStorageEntryMetadata> getAllCachedEntries() { List<SocialKademliaStorageEntryMetadata> entriesRet = new ArrayList<>(); for (List<SocialKademliaStorageEntryMetadata> entrySet : this.entries.values()) { if (entrySet.size() > 0) { for (SocialKademliaStorageEntryMetadata md : entriesRet) { if (md.isCached()) { entriesRet.add(md); } } } } return entriesRet; } public void remove(KadContent content) throws ContentNotFoundException { this.remove(new JSocialKademliaStorageEntryMetadata(content)); } public void remove(SocialKademliaStorageEntryMetadata entry) throws ContentNotFoundException { if (contains(entry)) { this.entries.get(entry.getKey()).remove(entry); } else { throw new ContentNotFoundException("This content does not exist in the Storage Entries"); } } @Override public synchronized String toString() { StringBuilder sb = new StringBuilder("Stored Content: \n"); int count = 0; for (List<SocialKademliaStorageEntryMetadata> es : this.entries.values()) { if (entries.size() < 1) { continue; } for (SocialKademliaStorageEntryMetadata e : es) { sb.append(++count); sb.append(". "); sb.append(e); sb.append("\n"); } } sb.append("\n"); return sb.toString(); } }