Package net.tomp2p.tracker

Source Code of net.tomp2p.tracker.TrackerStorage

package net.tomp2p.tracker;

import java.security.PublicKey;
import java.util.Collection;
import java.util.Map;
import java.util.NavigableSet;
import java.util.SortedSet;

import net.tomp2p.connection.PeerConnection;
import net.tomp2p.connection.PeerException;
import net.tomp2p.message.TrackerData;
import net.tomp2p.peers.DefaultMaintenance;
import net.tomp2p.peers.Maintainable;
import net.tomp2p.peers.Number160;
import net.tomp2p.peers.Number320;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.peers.PeerMap;
import net.tomp2p.peers.PeerMapChangeListener;
import net.tomp2p.peers.PeerStatistic;
import net.tomp2p.peers.PeerStatusListener;
import net.tomp2p.rpc.DigestInfo;
import net.tomp2p.storage.Data;
import net.tomp2p.storage.DigestTracker;
import net.tomp2p.utils.ConcurrentCacheMap;

public class TrackerStorage implements Maintainable, PeerMapChangeListener, PeerStatusListener, DigestTracker {
  // Core
  public static final int TRACKER_CACHE_SIZE = 1000;
  final private Map<Number320, TrackerData> dataMapUnverified;
  final private Map<Number320, TrackerData> dataMap;
  final private boolean verifyPeersOnTracker;
  private final int[] intervalSeconds;
  private final ConcurrentCacheMap<Number160, Boolean> peerOffline;
  private final PeerAddress self;
  private final int trackerTimoutSeconds;
  private final PeerMap peerMap;
  private final int replicationFactor;
  //comes later
  private PeerExchange peerExchange;

  public TrackerStorage(int trackerTimoutSeconds, final int[] intervalSeconds,
          int replicationFactor, PeerMap peerMap, PeerAddress self, boolean verifyPeersOnTracker) {
    dataMapUnverified = new ConcurrentCacheMap<Number320, TrackerData>(trackerTimoutSeconds, TRACKER_CACHE_SIZE,
            true);
    dataMap = new ConcurrentCacheMap<Number320, TrackerData>(trackerTimoutSeconds, TRACKER_CACHE_SIZE, true);
    peerOffline = new ConcurrentCacheMap<Number160, Boolean>(trackerTimoutSeconds * 5, TRACKER_CACHE_SIZE, false);
    this.trackerTimoutSeconds = trackerTimoutSeconds;
    this.intervalSeconds = intervalSeconds;
    this.self = self;
    this.peerMap = peerMap;
    this.replicationFactor = replicationFactor;
    this.verifyPeersOnTracker = verifyPeersOnTracker;
  }

  public boolean put(Number320 key, PeerAddress peerAddress, PublicKey publicKey, Data attachement) {
    if (peerOffline.containsKey(peerAddress.peerId())) {
      return false;
    }
    // security check
    Data oldDataUnverified = findOld(key, peerAddress, dataMapUnverified);
    boolean isUnverified = false;
    boolean isVerified = false;
    if(oldDataUnverified != null) {
      //security check
      if (oldDataUnverified.publicKey()!=null && !oldDataUnverified.publicKey().equals(publicKey)) {
        return false;
      }
      isUnverified = true;
    } else {
      Data oldData = findOld(key, peerAddress, dataMap);
      if(oldData != null) {
        //security check
        if (oldData.publicKey()!=null && !oldData.publicKey().equals(publicKey)) {
          return false;
        }
        isVerified = true;
      }
    }
   
    if(attachement == null) {
      attachement = new Data();
    }
    // now store
    attachement.publicKey(publicKey);
    final Map<Number320, TrackerData> dataMapToStore;
    if(isUnverified) {
      dataMapToStore = dataMapUnverified;
    } else if (isVerified) {
      dataMapToStore = dataMap;
    } else if(verifyPeersOnTracker) {
      dataMapToStore = dataMapUnverified;
    } else {
      dataMapToStore = dataMap;
    }
    return add(key, new PeerStatistic(peerAddress), dataMapToStore, attachement);
  }

  private Data findOld(Number320 key, PeerAddress peerAddress, Map<Number320, TrackerData> dataMap) {
    for (Map.Entry<Number320, TrackerData> entry : dataMap.entrySet()) {
      for (Map.Entry<PeerStatistic, Data> entry2 : entry.getValue().peerAddresses().entrySet()) {
        if (entry2.getKey().peerAddress().equals(peerAddress)) {
          return entry2.getValue();
        }
      }
    }
    return null;
  }
 
  public PeerExchange peerExchange() {
    return peerExchange;
  }
 
  public TrackerStorage peerExchange(PeerExchange peerExchange) {
    this.peerExchange = peerExchange;
    return this;
  }

  @Override
  public PeerStatistic nextForMaintenance(Collection<PeerAddress> notInterestedAddresses) {
    for (Map.Entry<Number320, TrackerData> entry : dataMapUnverified.entrySet()) {
      for (Map.Entry<PeerStatistic, Data> entry2 : entry.getValue().peerAddresses().entrySet()) {
        if (DefaultMaintenance.needMaintenance(entry2.getKey(), intervalSeconds)) {
          return entry2.getKey();
        }
      }
    }
    return null;
  }

  @Override
  public void peerInserted(PeerAddress remotePeer, boolean verified) {
    if (verified) {
      for (Map.Entry<Number320, TrackerData> entry : dataMap.entrySet()) {
        //if I have conetnt and I see a peer as a new responsible, push it.
        if(isInReplicationRange(entry.getKey().locationKey(), remotePeer, replicationFactor)) {
          //limit the pushing peer to those that are responsible
          if(isInReplicationRange(entry.getKey().locationKey(), self, replicationFactor)) {
            peerExchange.peerExchange(remotePeer, entry.getKey(), entry.getValue());
          }
        }
      }
    }
  }

  @Override
  public void peerRemoved(PeerAddress remotePeer, PeerStatistic storedPeerAddress) {
    // if a responsible peer is removed, and I see myself as a responsible,
    // I should push my content to a random responsible
    for (Map.Entry<Number320, TrackerData> entry : dataMap.entrySet()) {
      //if I have conetnt and I see the removed peer as a responsible, push it.
      if(isInReplicationRange(entry.getKey().locationKey(), remotePeer, replicationFactor)) {
        //limit the pushing peer to those that are responsible
        if(isInReplicationRange(entry.getKey().locationKey(), self, replicationFactor)) {
          NavigableSet<PeerAddress> closePeers = peerMap.closePeers(entry.getKey().locationKey(), replicationFactor);
          PeerAddress newResponsible = closePeers.headSet(remotePeer).last();
          peerExchange.peerExchange(newResponsible, entry.getKey(), entry.getValue());
        }
      }
    }
  }

  @Override
  public void peerUpdated(PeerAddress peerAddress, PeerStatistic storedPeerAddress) {
    // nothing to do
  }

  private boolean isInReplicationRange(final Number160 locationKey, final PeerAddress peerAddress,
          final int replicationFactor) {
    SortedSet<PeerAddress> tmp = peerMap.closePeers(locationKey, replicationFactor);
    tmp.add(self);
    return tmp.headSet(peerAddress).size() < replicationFactor;
  }

  private boolean add(Number320 key, PeerStatistic stat, Map<Number320, TrackerData> map, Data attachement) {
    TrackerData trackerData = map.get(key);
    if (trackerData == null) {
      trackerData = new TrackerData(new ConcurrentCacheMap<PeerStatistic, Data>(trackerTimoutSeconds,
              TRACKER_CACHE_SIZE, true));
      map.put(key, trackerData);
    }
    if (trackerData.size() < TRACKER_CACHE_SIZE) {
      trackerData.put(stat, attachement);
      return true;
    } else {
      return false;
    }
  }

  private boolean remove(Number320 key, PeerStatistic stat, Map<Number320, TrackerData> map) {
    TrackerData trackerData = map.get(key);
    if (trackerData != null) {
      boolean retVal = trackerData.remove(stat.peerAddress().peerId()) != null;
      if(trackerData.peerAddresses().size() == 0) {
        map.remove(key);
      }
      return retVal;
    }
    return false;
  }

  public TrackerData peers(Number320 key) {
    return dataMap.get(key);
  }

  public Collection<Number320> keys() {
    return dataMap.keySet();
  }

  @Override
  public boolean peerFailed(PeerAddress remotePeer, PeerException reason) {
    peerOffline.put(remotePeer.peerId(), Boolean.TRUE);
    Number320 keyToRemove = null;
    PeerStatistic statToRemove = null;
    for (Map.Entry<Number320, TrackerData> entry : dataMapUnverified.entrySet()) {
      for (Map.Entry<PeerStatistic, Data> entry2 : entry.getValue().peerAddresses().entrySet()) {
        if (entry2.getKey().peerAddress().equals(remotePeer)) {
          keyToRemove = entry.getKey();
          statToRemove = entry2.getKey();
        }
      }
    }
    if(keyToRemove !=null) {
      remove(keyToRemove, statToRemove, dataMapUnverified);
    }
    //
    for (Map.Entry<Number320, TrackerData> entry : dataMap.entrySet()) {
      for (Map.Entry<PeerStatistic, Data> entry2 : entry.getValue().peerAddresses().entrySet()) {
        if (entry2.getKey().peerAddress().equals(remotePeer)) {
          keyToRemove = entry.getKey();
          statToRemove = entry2.getKey();
        }
      }
    }
    if(keyToRemove !=null) {
      remove(keyToRemove, statToRemove, dataMap);
    }
    return true;
  }

  @Override
  public boolean peerFound(PeerAddress remotePeer, PeerAddress referrer, PeerConnection peerConnection) {
    boolean firsthand = referrer == null;
    if (firsthand) {
      peerOffline.remove(remotePeer.peerId());
      Number320 keyToRemove = null;
      PeerStatistic statToRemove = null;
      for (Map.Entry<Number320, TrackerData> entry : dataMapUnverified.entrySet()) {
        for (Map.Entry<PeerStatistic, Data> entry2 : entry.getValue().peerAddresses().entrySet()) {
          PeerAddress tmp = entry2.getKey().peerAddress();
          if (tmp.equals(remotePeer)) {
            if (add(entry.getKey(), entry2.getKey(), dataMap, entry2.getValue())) {
              // only remove from unverified if we could store to
              // verified
              keyToRemove = entry.getKey();
              statToRemove = entry2.getKey();
              statToRemove.successfullyChecked();
              // TODO: here we can break to the if statement below
            }
          }
        }
      }
      if (keyToRemove != null && statToRemove != null) {
        remove(keyToRemove, statToRemove, dataMapUnverified);
      }
    }
    return true;
  }

  public int size() {
      return dataMap.size();
    }

  public int sizeUnverified() {
    return dataMapUnverified.size();
    }

  @Override
    public DigestInfo digest(Number160 locationKey, Number160 domainKey, Number160 contentKey) {
    Number160 contentDigest = Number160.ZERO;
    int counter = 0;
    TrackerData trackerData = dataMap.get(new Number320(locationKey, domainKey));
    if(trackerData!=null) {
      if(contentKey!=null) {
        Map.Entry<PeerStatistic, Data> entry = trackerData.get(contentKey);
        if(entry!=null) {
          return new DigestInfo(Number160.ZERO, contentKey, 1);
        }
      } else {
        for(PeerStatistic peerStatatistic: trackerData.peerAddresses().keySet()) {
          contentDigest = contentDigest.xor(peerStatatistic.peerAddress().peerId());
          counter++;
        }
      }
    }
    return new DigestInfo(Number160.ZERO, contentKey, counter);
    }
}
TOP

Related Classes of net.tomp2p.tracker.TrackerStorage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.