2006-03-18 22:47:04 +01:00
// yacySeed.java
2005-04-07 21:19:42 +02:00
// -------------------------------------
2008-07-20 19:14:51 +02:00
// (C) by Michael Peter Christen; mc@yacy.net
2005-04-07 21:19:42 +02:00
// first published on http://www.anomic.de
// Frankfurt, Germany, 2004
2005-09-21 23:32:43 +02:00
//
// $LastChangedDate$
// $LastChangedRevision$
// $LastChangedBy$
2005-04-07 21:19:42 +02:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
2006-03-18 22:47:04 +01:00
//
// YACY stands for Yet Another CYberspace
//
// the yacySeed Object is the object that bundles and carries all information about
// a single peer in the yacy space.
// The yacySeed object is carried along peers using a string representation, that can
// be compressed and/or scrambled, depending on the purpose of the process.
//
// the yacy status
// any value that is defined here will be overwritten each time the proxy is started
// to prevent that the system gets confused, it should be set to "" which means
// undefined. Other status' that can be reached at run-time are
// junior - a peer that has no public socket, thus cannot be reached on demand
// senior - a peer that has a public socked and serves search queries
// principal - a peer like a senior socket and serves as gateway for network definition
2005-04-07 21:19:42 +02:00
2011-09-25 18:59:06 +02:00
package net.yacy.peers ;
2005-04-07 21:19:42 +02:00
2005-05-05 07:32:19 +02:00
import java.io.File ;
import java.io.FileReader ;
import java.io.FileWriter ;
import java.io.IOException ;
2006-12-20 02:07:49 +01:00
import java.net.InetAddress ;
2008-05-25 20:35:38 +02:00
import java.net.MalformedURLException ;
import java.net.URL ;
2011-03-12 23:54:41 +01:00
import java.text.ParseException ;
2011-02-13 18:37:28 +01:00
import java.util.Comparator ;
2005-05-05 07:32:19 +02:00
import java.util.Date ;
2007-04-26 11:51:51 +02:00
import java.util.Iterator ;
2007-10-01 14:30:23 +02:00
import java.util.Random ;
2006-10-10 22:09:26 +02:00
import java.util.Set ;
2008-03-11 00:28:05 +01:00
import java.util.TreeMap ;
2010-02-15 16:57:35 +01:00
import java.util.concurrent.ConcurrentHashMap ;
2011-03-15 02:03:35 +01:00
import java.util.concurrent.ConcurrentMap ;
2010-09-07 19:13:47 +02:00
import java.util.regex.Pattern ;
2006-01-04 01:39:00 +01:00
2011-01-03 21:52:54 +01:00
import net.yacy.cora.date.AbstractFormatter ;
import net.yacy.cora.date.GenericFormatter ;
2011-05-27 10:24:54 +02:00
import net.yacy.cora.document.ASCII ;
2011-03-07 21:36:40 +01:00
import net.yacy.cora.document.UTF8 ;
2010-09-14 17:27:27 +02:00
import net.yacy.cora.protocol.Domains ;
2011-12-16 23:59:29 +01:00
import net.yacy.cora.sorting.ClusteredScoreMap ;
import net.yacy.cora.sorting.ScoreMap ;
2009-10-11 02:12:19 +02:00
import net.yacy.kelondro.data.word.Word ;
2010-04-15 15:22:59 +02:00
import net.yacy.kelondro.index.HandleSet ;
2009-10-10 01:22:22 +02:00
import net.yacy.kelondro.order.Base64Order ;
import net.yacy.kelondro.order.Digest ;
2009-10-11 02:24:42 +02:00
import net.yacy.kelondro.util.MapTools ;
2011-01-28 11:12:17 +01:00
import net.yacy.kelondro.util.OS ;
2011-09-25 18:59:06 +02:00
import net.yacy.peers.dht.FlatWordPartitionScheme ;
import net.yacy.peers.operation.yacyVersion ;
import net.yacy.search.Switchboard ;
2005-05-05 07:32:19 +02:00
import de.anomic.tools.bitfield ;
import de.anomic.tools.crypt ;
2005-04-07 21:19:42 +02:00
2012-01-03 17:49:37 +01:00
public class Seed implements Cloneable , Comparable < Seed > , Comparator < Seed >
{
2005-09-21 23:32:43 +02:00
2011-02-12 01:01:40 +01:00
public static String ANON_PREFIX = " _anon " ;
2011-08-03 20:32:11 +02:00
2010-10-26 16:40:19 +02:00
public static final int maxsize = 16000 ;
2006-03-18 22:47:04 +01:00
/ * *
* < b > substance < / b > " sI " ( send index / words )
* /
2005-09-21 23:32:43 +02:00
public static final String INDEX_OUT = " sI " ;
2006-03-18 22:47:04 +01:00
/ * *
* < b > substance < / b > " rI " ( received index / words )
* /
2012-01-03 17:49:37 +01:00
public static final String INDEX_IN = " rI " ;
2006-03-18 22:47:04 +01:00
/ * *
* < b > substance < / b > " sU " ( send URLs )
* /
2005-09-21 23:32:43 +02:00
public static final String URL_OUT = " sU " ;
2006-03-18 22:47:04 +01:00
/ * *
* < b > substance < / b > " rU " ( received URLs )
* /
2012-01-03 17:49:37 +01:00
public static final String URL_IN = " rU " ;
2006-03-18 22:47:04 +01:00
/ * *
* < b > substance < / b > " virgin "
* /
2005-06-28 13:27:31 +02:00
public static final String PEERTYPE_VIRGIN = " virgin " ;
2006-03-18 22:47:04 +01:00
/ * *
* < b > substance < / b > " junior "
* /
2005-06-28 13:27:31 +02:00
public static final String PEERTYPE_JUNIOR = " junior " ;
2006-03-18 22:47:04 +01:00
/ * *
* < b > substance < / b > " senior "
* /
2005-06-28 13:27:31 +02:00
public static final String PEERTYPE_SENIOR = " senior " ;
2006-03-18 22:47:04 +01:00
/ * *
* < b > substance < / b > " principal "
* /
2005-06-28 13:27:31 +02:00
public static final String PEERTYPE_PRINCIPAL = " principal " ;
2006-03-18 22:47:04 +01:00
/ * *
* < b > substance < / b > " PeerType "
* /
2005-06-28 13:27:31 +02:00
public static final String PEERTYPE = " PeerType " ;
2006-03-18 22:47:04 +01:00
2007-04-14 12:11:37 +02:00
/** static/dynamic (if the IP changes often for any reason) */
2012-01-03 17:49:37 +01:00
private static final String IPTYPE = " IPType " ;
private static final String FLAGS = " Flags " ;
2010-04-19 18:42:37 +02:00
private static final String FLAGSZERO = " ____ " ;
2007-04-14 12:11:37 +02:00
/** the applications version */
2012-01-03 17:49:37 +01:00
public static final String VERSION = " Version " ;
2006-03-18 22:47:04 +01:00
2012-01-03 17:49:37 +01:00
public static final String YOURTYPE = " yourtype " ;
public static final String LASTSEEN = " LastSeen " ;
private static final String USPEED = " USpeed " ;
2005-10-17 17:46:12 +02:00
2007-04-14 12:11:37 +02:00
/** the name of the peer (user-set) */
2012-01-03 17:49:37 +01:00
public static final String NAME = " Name " ;
private static final String HASH = " Hash " ;
2007-04-14 12:11:37 +02:00
/** Birthday - first startup */
2012-01-03 17:49:37 +01:00
private static final String BDATE = " BDate " ;
2007-04-14 12:11:37 +02:00
/** UTC-Offset */
2012-01-03 17:49:37 +01:00
public static final String UTC = " UTC " ;
private static final String PEERTAGS = " Tags " ;
2005-10-17 17:46:12 +02:00
2007-04-14 12:11:37 +02:00
/** the speed of indexing (pages/minute) of the peer */
2012-01-03 17:49:37 +01:00
public static final String ISPEED = " ISpeed " ;
2007-04-14 12:11:37 +02:00
/** the speed of retrieval (queries/minute) of the peer */
2012-01-03 17:49:37 +01:00
public static final String RSPEED = " RSpeed " ;
2007-04-14 12:11:37 +02:00
/** the number of minutes that the peer is up in minutes/day (moving average MA30) */
2012-01-03 17:49:37 +01:00
public static final String UPTIME = " Uptime " ;
2007-04-14 12:11:37 +02:00
/** the number of links that the peer has stored (LURL's) */
2012-01-03 17:49:37 +01:00
public static final String LCOUNT = " LCount " ;
2007-04-14 12:11:37 +02:00
/** the number of links that the peer has noticed, but not loaded (NURL's) */
2012-01-03 17:49:37 +01:00
public static final String NCOUNT = " NCount " ;
2007-08-22 02:59:05 +02:00
/** the number of links that the peer provides for remote crawls (ZURL's) */
2012-01-03 17:49:37 +01:00
public static final String RCOUNT = " RCount " ;
2008-04-19 06:24:29 +02:00
/** the number of different words the peer has indexed */
2012-01-03 17:49:37 +01:00
public static final String ICOUNT = " ICount " ;
2007-04-14 12:11:37 +02:00
/** the number of seeds that the peer has stored */
2012-01-03 17:49:37 +01:00
public static final String SCOUNT = " SCount " ;
2007-10-25 01:25:48 +02:00
/** the number of clients that the peer connects (connects/hour as double) */
2012-01-03 17:49:37 +01:00
public static final String CCOUNT = " CCount " ;
public static final String IP = " IP " ;
public static final String PORT = " Port " ;
2010-10-27 15:21:18 +02:00
public static final String SEEDLISTURL = " seedURL " ;
2007-04-14 12:11:37 +02:00
/** zero-value */
2012-01-03 17:49:37 +01:00
private static final String ZERO = " 0 " ;
2011-08-03 20:32:11 +02:00
2012-01-03 17:49:37 +01:00
private static final int FLAG_DIRECT_CONNECT = 0 ;
private static final int FLAG_ACCEPT_REMOTE_CRAWL = 1 ;
private static final int FLAG_ACCEPT_REMOTE_INDEX = 2 ;
2012-05-25 15:33:02 +02:00
private static final int FLAG_ROOT_NODE = 3 ;
2011-08-03 20:32:11 +02:00
2007-06-26 16:37:10 +02:00
public static final String DFLT_NETWORK_UNIT = " freeworld " ;
public static final String DFLT_NETWORK_GROUP = " " ;
2007-10-01 14:30:23 +02:00
private static final Random random = new Random ( System . currentTimeMillis ( ) ) ;
2011-08-03 20:32:11 +02:00
2005-04-07 21:19:42 +02:00
// class variables
2007-04-14 12:11:37 +02:00
/** the peer-hash */
2005-04-07 21:19:42 +02:00
public String hash ;
2012-01-03 17:49:37 +01:00
/** a set of identity founding values, eg. IP, name of the peer, YaCy-version, ... */
2011-03-15 02:03:35 +01:00
private final ConcurrentMap < String , String > dna ;
2010-04-19 18:42:37 +02:00
private String alternativeIP = null ;
2011-09-15 01:34:05 +02:00
private long birthdate ; // keep this value in ram since it is often used and may cause lockings in concurrent situations.
2011-03-12 23:54:41 +01:00
2011-10-04 11:06:24 +02:00
public Seed ( final String theHash , final ConcurrentMap < String , String > theDna ) {
2005-09-21 23:32:43 +02:00
// create a seed with a pre-defined hash map
2008-12-02 00:08:27 +01:00
assert theHash ! = null ;
2005-10-28 09:15:00 +02:00
this . hash = theHash ;
this . dna = theDna ;
2011-10-04 11:06:24 +02:00
final String flags = this . dna . get ( Seed . FLAGS ) ;
2012-01-03 17:49:37 +01:00
if ( ( flags = = null ) | | ( flags . length ( ) ! = 4 ) ) {
this . dna . put ( Seed . FLAGS , Seed . FLAGSZERO ) ;
}
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . NAME , checkPeerName ( get ( Seed . NAME , " ∅ " ) ) ) ;
2011-09-15 01:34:05 +02:00
this . birthdate = - 1 ; // this means 'not yet parsed', parse that later when it is used
2005-04-07 21:19:42 +02:00
}
2011-08-03 20:32:11 +02:00
2011-10-04 11:06:24 +02:00
private Seed ( final String theHash ) {
2010-02-15 16:57:35 +01:00
this . dna = new ConcurrentHashMap < String , String > ( ) ;
2005-09-21 23:32:43 +02:00
// settings that can only be computed by originating peer:
// at first startup -
2006-10-12 00:23:48 +02:00
this . hash = theHash ; // the hash key of the peer - very important. should be static somehow, even after restart
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . NAME , defaultPeerName ( ) ) ;
2011-08-03 20:32:11 +02:00
2005-09-21 23:32:43 +02:00
// later during operation -
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . ISPEED , Seed . ZERO ) ;
this . dna . put ( Seed . RSPEED , Seed . ZERO ) ;
this . dna . put ( Seed . UPTIME , Seed . ZERO ) ;
this . dna . put ( Seed . LCOUNT , Seed . ZERO ) ;
this . dna . put ( Seed . NCOUNT , Seed . ZERO ) ;
this . dna . put ( Seed . RCOUNT , Seed . ZERO ) ;
this . dna . put ( Seed . ICOUNT , Seed . ZERO ) ;
this . dna . put ( Seed . SCOUNT , Seed . ZERO ) ;
this . dna . put ( Seed . CCOUNT , Seed . ZERO ) ;
this . dna . put ( Seed . VERSION , Seed . ZERO ) ;
2005-04-07 21:19:42 +02:00
2005-09-21 23:32:43 +02:00
// settings that is created during the 'hello' phase - in first contact
2012-01-03 17:49:37 +01:00
this . dna . put ( Seed . IP , " " ) ; // 123.234.345.456
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . PORT , " ∅ " ) ;
this . dna . put ( Seed . IPTYPE , " ∅ " ) ;
2005-04-07 21:19:42 +02:00
2005-09-21 23:32:43 +02:00
// settings that can only be computed by visiting peer
2012-01-03 17:49:37 +01:00
this . dna . put ( Seed . USPEED , Seed . ZERO ) ; // the computated uplink speed of the peer
2005-04-07 21:19:42 +02:00
2005-09-21 23:32:43 +02:00
// settings that are needed to organize the seed round-trip
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . FLAGS , Seed . FLAGSZERO ) ;
2005-04-07 21:19:42 +02:00
setFlagDirectConnect ( false ) ;
setFlagAcceptRemoteCrawl ( true ) ;
setFlagAcceptRemoteIndex ( true ) ;
2005-11-11 00:48:20 +01:00
setUnusedFlags ( ) ;
2006-03-18 22:47:04 +01:00
2005-04-07 21:19:42 +02:00
// index transfer
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . INDEX_OUT , Seed . ZERO ) ; // send index
2012-01-03 17:49:37 +01:00
this . dna . put ( Seed . INDEX_IN , Seed . ZERO ) ; // received index
this . dna . put ( Seed . URL_OUT , Seed . ZERO ) ; // send URLs
this . dna . put ( Seed . URL_IN , Seed . ZERO ) ; // received URLs
2011-08-03 20:32:11 +02:00
2011-03-12 23:54:41 +01:00
// default first filling
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . BDATE , GenericFormatter . SHORT_SECOND_FORMATTER . format ( ) ) ;
this . dna . put ( Seed . LASTSEEN , this . dna . get ( Seed . BDATE ) ) ; // just as initial setting
this . dna . put ( Seed . UTC , GenericFormatter . UTCDiffString ( ) ) ;
this . dna . put ( Seed . PEERTYPE , Seed . PEERTYPE_VIRGIN ) ; // virgin/junior/senior/principal
2011-08-03 20:32:11 +02:00
2011-03-12 23:54:41 +01:00
this . birthdate = System . currentTimeMillis ( ) ;
2005-04-07 21:19:42 +02:00
}
2011-08-03 20:32:11 +02:00
2008-04-27 00:53:04 +02:00
/ * *
* check the peer name : protect against usage as XSS hack
2012-01-03 17:49:37 +01:00
*
2011-03-07 16:29:45 +01:00
* @param id
2008-04-27 00:53:04 +02:00
* @return a checked name without " < " and " > "
* /
2011-11-25 12:23:52 +01:00
private final static Pattern tp = Pattern . compile ( " <|> " ) ;
2012-01-03 17:49:37 +01:00
2011-12-25 10:14:15 +01:00
public static String checkPeerName ( String name ) {
2011-11-25 12:23:52 +01:00
name = tp . matcher ( name ) . replaceAll ( " _ " ) ;
2008-04-27 00:53:04 +02:00
return name ;
}
2011-01-28 11:12:17 +01:00
/ * *
* generate a default peer name
2012-01-03 17:49:37 +01:00
*
2011-01-28 11:12:17 +01:00
* @return
* /
private static String defaultPeerName ( ) {
2012-01-03 17:49:37 +01:00
return ANON_PREFIX
+ OS . infoKey ( )
+ " - "
+ ( System . currentTimeMillis ( ) % 77777777L )
+ " - "
+ Network . speedKey ;
2011-01-28 11:12:17 +01:00
}
2011-08-03 20:32:11 +02:00
2007-05-15 17:48:28 +02:00
/ * *
* Checks for the static fragments of a generated default peer name , such as the string ' dpn '
2012-01-03 17:49:37 +01:00
*
2007-05-15 17:48:28 +02:00
* @see # makeDefaultPeerName ( )
* @param name the peer name to check for default peer name compliance
* @return whether the given peer name may be a default generated peer name
* /
2008-08-02 14:12:04 +02:00
public static boolean isDefaultPeerName ( final String name ) {
2011-01-28 11:12:17 +01:00
return name . startsWith ( " _anon " ) ;
2006-03-02 23:25:46 +01:00
}
2011-08-03 20:32:11 +02:00
2007-04-30 00:05:34 +02:00
/ * *
2012-01-03 17:49:37 +01:00
* used when doing routing within a cluster ; this can assign a ip and a port that is used instead the
* address stored in the seed DNA
2007-04-30 00:05:34 +02:00
* /
2008-08-02 14:12:04 +02:00
public void setAlternativeAddress ( final String ipport ) {
2012-01-03 17:49:37 +01:00
if ( ipport = = null ) {
return ;
}
2008-08-02 14:12:04 +02:00
final int p = ipport . indexOf ( ':' ) ;
2012-01-03 17:49:37 +01:00
if ( p < 0 ) {
this . alternativeIP = ipport ;
} else {
this . alternativeIP = ipport . substring ( 0 , p ) ;
}
2007-04-30 00:05:34 +02:00
}
2006-10-12 00:23:48 +02:00
2005-11-03 15:16:16 +01:00
/ * *
* try to get the IP < br >
2012-01-03 17:49:37 +01:00
*
2005-11-03 15:16:16 +01:00
* @return the IP or null
* /
2009-05-29 16:16:03 +02:00
public final String getIP ( ) {
2011-10-04 11:06:24 +02:00
final String ip = get ( Seed . IP , " 127.0.0.1 " ) ;
2011-04-29 12:58:12 +02:00
return ( ip = = null | | ip . length ( ) = = 0 ) ? " 127.0.0.1 " : ip ;
2009-05-29 16:16:03 +02:00
}
2012-01-03 17:49:37 +01:00
2005-11-03 15:16:16 +01:00
/ * *
* try to get the peertype < br >
2012-01-03 17:49:37 +01:00
*
2005-11-03 15:16:16 +01:00
* @return the peertype or null
* /
2012-01-03 17:49:37 +01:00
public final String getPeerType ( ) {
return get ( Seed . PEERTYPE , " " ) ;
}
2006-01-23 00:14:37 +01:00
/ * *
* try to get the peertype < br >
2012-01-03 17:49:37 +01:00
*
2008-02-10 16:57:52 +01:00
* @return the peertype or " virgin "
2006-01-23 00:14:37 +01:00
* /
2012-01-03 17:49:37 +01:00
public final String orVirgin ( ) {
return get ( Seed . PEERTYPE , Seed . PEERTYPE_VIRGIN ) ;
}
2005-11-03 15:16:16 +01:00
/ * *
* try to get the peertype < br >
2012-01-03 17:49:37 +01:00
*
2005-11-03 15:16:16 +01:00
* @return the peertype or " junior "
* /
2012-01-03 17:49:37 +01:00
public final String orJunior ( ) {
return get ( Seed . PEERTYPE , Seed . PEERTYPE_JUNIOR ) ;
}
2005-11-03 15:16:16 +01:00
/ * *
* try to get the peertype < br >
2012-01-03 17:49:37 +01:00
*
2005-11-03 15:16:16 +01:00
* @return the peertype or " senior "
* /
2012-01-03 17:49:37 +01:00
public final String orSenior ( ) {
return get ( Seed . PEERTYPE , Seed . PEERTYPE_SENIOR ) ;
}
2005-11-03 15:16:16 +01:00
/ * *
* try to get the peertype < br >
2012-01-03 17:49:37 +01:00
*
2005-11-03 15:16:16 +01:00
* @return the peertype or " principal "
* /
2012-01-03 17:49:37 +01:00
public final String orPrincipal ( ) {
return get ( Seed . PEERTYPE , Seed . PEERTYPE_PRINCIPAL ) ;
}
2005-10-18 01:12:40 +02:00
2007-04-14 12:11:37 +02:00
/ * *
* Get a value from the peer ' s DNA ( its set of peer defining values , e . g . IP , name , version , . . . )
2012-01-03 17:49:37 +01:00
*
2007-04-14 12:11:37 +02:00
* @param key the key for the value to fetch
* @param dflt the default value
* /
2008-08-02 14:12:04 +02:00
public final String get ( final String key , final String dflt ) {
2005-10-28 09:15:00 +02:00
final Object o = this . dna . get ( key ) ;
2012-01-03 17:49:37 +01:00
if ( o = = null ) {
return dflt ;
}
2005-10-28 09:15:00 +02:00
return ( String ) o ;
2005-04-07 21:19:42 +02:00
}
2011-03-15 02:03:35 +01:00
public final float getFloat ( final String key , final float dflt ) {
final Object o = this . dna . get ( key ) ;
2012-01-03 17:49:37 +01:00
if ( o = = null ) {
return dflt ;
}
if ( o instanceof String ) {
try {
return Float . parseFloat ( ( String ) o ) ;
} catch ( final NumberFormatException e ) {
return dflt ;
}
} else if ( o instanceof Float ) {
2011-03-15 02:03:35 +01:00
return ( ( Float ) o ) . floatValue ( ) ;
2012-01-03 17:49:37 +01:00
} else {
return dflt ;
}
2011-03-15 02:03:35 +01:00
}
2011-08-03 20:32:11 +02:00
2008-08-02 14:12:04 +02:00
public final long getLong ( final String key , final long dflt ) {
2007-11-09 10:40:42 +01:00
final Object o = this . dna . get ( key ) ;
2012-01-03 17:49:37 +01:00
if ( o = = null ) {
return dflt ;
}
if ( o instanceof String ) {
try {
return Long . parseLong ( ( String ) o ) ;
} catch ( final NumberFormatException e ) {
return dflt ;
}
} else if ( o instanceof Long ) {
2007-11-12 15:39:30 +01:00
return ( ( Long ) o ) . longValue ( ) ;
2012-01-03 17:49:37 +01:00
} else if ( o instanceof Integer ) {
2008-06-06 18:01:27 +02:00
return ( ( Integer ) o ) . intValue ( ) ;
2012-01-03 17:49:37 +01:00
} else {
return dflt ;
}
}
public final void setIP ( final String ip ) {
this . dna . put ( Seed . IP , ip ) ;
}
public final void setPort ( final String port ) {
this . dna . put ( Seed . PORT , port ) ;
}
public final void setType ( final String type ) {
this . dna . put ( Seed . PEERTYPE , type ) ;
}
public final void setJunior ( ) {
this . dna . put ( Seed . PEERTYPE , Seed . PEERTYPE_JUNIOR ) ;
2007-11-09 10:40:42 +01:00
}
2005-04-07 21:19:42 +02:00
2012-01-03 17:49:37 +01:00
public final void setSenior ( ) {
this . dna . put ( Seed . PEERTYPE , Seed . PEERTYPE_SENIOR ) ;
}
public final void setPrincipal ( ) {
this . dna . put ( Seed . PEERTYPE , Seed . PEERTYPE_PRINCIPAL ) ;
}
2008-02-10 16:57:52 +01:00
2008-08-02 14:12:04 +02:00
public final void put ( final String key , final String value ) {
2012-01-03 17:49:37 +01:00
synchronized ( this . dna ) {
2005-10-28 09:15:00 +02:00
this . dna . put ( key , value ) ;
}
2005-04-07 21:19:42 +02:00
}
2007-05-15 17:48:28 +02:00
/** @return the DNA-map of this peer */
2011-09-14 23:19:02 +02:00
public final ConcurrentMap < String , String > getMap ( ) {
2005-10-28 09:15:00 +02:00
return this . dna ;
2005-04-07 21:19:42 +02:00
}
2005-09-21 23:32:43 +02:00
2011-08-03 20:32:11 +02:00
public final void setName ( final String name ) {
2012-01-03 17:49:37 +01:00
synchronized ( this . dna ) {
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . NAME , checkPeerName ( name ) ) ;
2011-01-28 11:12:17 +01:00
}
}
2011-08-03 20:32:11 +02:00
2006-10-12 00:23:48 +02:00
public final String getName ( ) {
2011-10-04 11:06:24 +02:00
return checkPeerName ( get ( Seed . NAME , " ∅ " ) ) ;
2005-04-07 21:19:42 +02:00
}
2005-09-21 23:32:43 +02:00
2006-10-12 00:23:48 +02:00
public final String getHexHash ( ) {
2005-10-28 09:15:00 +02:00
return b64Hash2hexHash ( this . hash ) ;
2005-04-07 21:19:42 +02:00
}
2008-08-02 14:12:04 +02:00
public final void incSI ( final int count ) {
2011-10-04 11:06:24 +02:00
String v = this . dna . get ( Seed . INDEX_OUT ) ;
2012-01-03 17:49:37 +01:00
if ( v = = null ) {
v = Seed . ZERO ;
}
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . INDEX_OUT , Long . toString ( Long . parseLong ( v ) + count ) ) ;
2005-04-07 21:19:42 +02:00
}
2005-09-21 23:32:43 +02:00
2008-08-02 14:12:04 +02:00
public final void incRI ( final int count ) {
2011-10-04 11:06:24 +02:00
String v = this . dna . get ( Seed . INDEX_IN ) ;
2012-01-03 17:49:37 +01:00
if ( v = = null ) {
v = Seed . ZERO ;
}
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . INDEX_IN , Long . toString ( Long . parseLong ( v ) + count ) ) ;
2005-04-07 21:19:42 +02:00
}
2005-09-21 23:32:43 +02:00
2008-08-02 14:12:04 +02:00
public final void incSU ( final int count ) {
2011-10-04 11:06:24 +02:00
String v = this . dna . get ( Seed . URL_OUT ) ;
2012-01-03 17:49:37 +01:00
if ( v = = null ) {
v = Seed . ZERO ;
}
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . URL_OUT , Long . toString ( Long . parseLong ( v ) + count ) ) ;
2005-04-07 21:19:42 +02:00
}
2005-09-21 23:32:43 +02:00
2008-08-02 14:12:04 +02:00
public final void incRU ( final int count ) {
2011-10-04 11:06:24 +02:00
String v = this . dna . get ( Seed . URL_IN ) ;
2012-01-03 17:49:37 +01:00
if ( v = = null ) {
v = Seed . ZERO ;
}
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . URL_IN , Long . toString ( Long . parseLong ( v ) + count ) ) ;
2005-04-07 21:19:42 +02:00
}
2011-08-03 20:32:11 +02:00
2012-01-03 17:49:37 +01:00
public final void resetCounters ( ) {
this . dna . put ( Seed . INDEX_OUT , Seed . ZERO ) ;
this . dna . put ( Seed . INDEX_IN , Seed . ZERO ) ;
this . dna . put ( Seed . URL_OUT , Seed . ZERO ) ;
this . dna . put ( Seed . URL_IN , Seed . ZERO ) ;
2009-05-28 17:49:42 +02:00
}
2005-04-07 21:19:42 +02:00
2007-05-15 17:48:28 +02:00
/ * *
* < code > 12 * 6 bit = 72 bit = 24 < / code > characters octal - hash
* < p >
2012-01-03 17:49:37 +01:00
* Octal hashes are used for cache - dumps that are DHT - ready
* < / p >
* < p >
* Cause : the natural order of octal hashes are the same as the b64 - order of b64Hashes . a hexhash cannot
* be used in such cases , and b64Hashes are not appropriate for file names
2007-05-15 17:48:28 +02:00
* < / p >
2012-01-03 17:49:37 +01:00
*
2007-05-15 17:48:28 +02:00
* @param b64Hash a base64 hash
* @return the octal representation of the given base64 hash
* /
2008-08-02 14:12:04 +02:00
public static String b64Hash2octalHash ( final String b64Hash ) {
2009-07-06 17:21:43 +02:00
return Digest . encodeOctal ( Base64Order . enhancedCoder . decode ( b64Hash ) ) ;
2007-02-06 17:01:03 +01:00
}
2007-05-15 17:48:28 +02:00
/ * *
* < code > 12 * 6 bit = 72 bit = 18 < / code > characters hex - hash
2012-01-03 17:49:37 +01:00
*
2007-05-15 17:48:28 +02:00
* @param b64Hash a base64 hash
* @return the hexadecimal representation of the given base64 hash
* /
2008-08-02 14:12:04 +02:00
public static String b64Hash2hexHash ( final String b64Hash ) {
2012-01-03 17:49:37 +01:00
if ( b64Hash . length ( ) > 12 ) {
return " " ;
}
2005-12-22 02:01:46 +01:00
// the hash string represents 12 * 6 bit = 72 bits. This is too much for a long integer.
2009-07-06 17:21:43 +02:00
return Digest . encodeHex ( Base64Order . enhancedCoder . decode ( b64Hash ) ) ;
2005-12-22 02:01:46 +01:00
}
2011-08-03 20:32:11 +02:00
2007-05-15 17:48:28 +02:00
/ * *
* @param hexHash a hexadecimal hash
* @return the base64 representation of the given hex hash
* /
2008-08-02 14:12:04 +02:00
public static String hexHash2b64Hash ( final String hexHash ) {
2009-01-30 16:33:00 +01:00
return Base64Order . enhancedCoder . encode ( Digest . decodeHex ( hexHash ) ) ;
2005-04-07 21:19:42 +02:00
}
2011-08-03 20:32:11 +02:00
2007-05-15 17:48:28 +02:00
/ * *
2011-08-03 20:32:11 +02:00
* The returned version follows this pattern : < code > MAJORVERSION . MINORVERSION 0 SVN REVISION < / code >
2012-01-03 17:49:37 +01:00
*
2007-05-15 17:48:28 +02:00
* @return the YaCy version of this peer as a float or < code > 0 < / code > if no valid value could be retrieved
2012-01-03 17:49:37 +01:00
* from this yacySeed object
2007-05-15 17:48:28 +02:00
* /
2006-10-12 00:23:48 +02:00
public final float getVersion ( ) {
2005-04-07 21:19:42 +02:00
try {
2011-10-04 11:06:24 +02:00
return Float . parseFloat ( get ( Seed . VERSION , Seed . ZERO ) ) ;
2012-01-03 17:49:37 +01:00
} catch ( final NumberFormatException e ) {
2005-04-07 21:19:42 +02:00
return 0 ;
}
}
2011-08-03 20:32:11 +02:00
2011-05-18 16:26:28 +02:00
/ * *
* get the SVN version of the peer
2012-01-03 17:49:37 +01:00
*
2011-05-18 16:26:28 +02:00
* @return
* /
public final int getRevision ( ) {
2011-10-04 11:06:24 +02:00
return yacyVersion . revision ( get ( Seed . VERSION , Seed . ZERO ) ) ;
2011-05-18 16:26:28 +02:00
}
2011-08-03 20:32:11 +02:00
2007-05-15 17:48:28 +02:00
/ * *
* @return the public address of the peer as IP : port string or < code > null < / code > if no valid values for
2012-01-03 17:49:37 +01:00
* either the IP or the port could be retrieved from this yacySeed object
2007-05-15 17:48:28 +02:00
* /
2007-04-30 00:05:34 +02:00
public final String getPublicAddress ( ) {
2011-08-03 20:32:11 +02:00
String ip = getIP ( ) ;
2012-01-03 17:49:37 +01:00
if ( ip = = null | | ip . length ( ) < 8 | | ip . length ( ) > 60 ) {
ip = " 127.0.0.1 " ;
}
2011-08-03 20:32:11 +02:00
2011-10-04 11:06:24 +02:00
final String port = this . dna . get ( Seed . PORT ) ;
2012-01-03 17:49:37 +01:00
if ( port = = null | | port . length ( ) < 2 | | port . length ( ) > 5 ) {
return null ;
}
2006-10-12 00:23:48 +02:00
2011-08-03 20:32:11 +02:00
final StringBuilder sb = new StringBuilder ( ip . length ( ) + port . length ( ) + 1 ) ;
2011-02-25 02:19:39 +01:00
sb . append ( ip ) ;
sb . append ( ':' ) ;
sb . append ( port ) ;
return sb . toString ( ) ;
2005-04-07 21:19:42 +02:00
}
2011-08-03 20:32:11 +02:00
2007-05-15 17:48:28 +02:00
/ * *
* If this seed is part of a cluster , the peer has probably the { @linkplain # alternativeIP } object set to
2012-01-03 17:49:37 +01:00
* a local IP . If this is present and the public IP of this peer is identical to the public IP of the own
* seed , construct an address using this IP ; otherwise return the public address
*
2007-05-15 17:48:28 +02:00
* @see # getPublicAddress ( )
* @return the alternative IP : port if present , else the public address
* /
2007-04-30 00:05:34 +02:00
public final String getClusterAddress ( ) {
2012-01-03 17:49:37 +01:00
if ( this . alternativeIP = = null ) {
return getPublicAddress ( ) ;
}
2011-08-03 20:32:11 +02:00
2011-10-04 11:06:24 +02:00
final String port = this . dna . get ( Seed . PORT ) ;
2012-01-03 17:49:37 +01:00
if ( ( port = = null ) | | ( port . length ( ) < 2 ) ) {
return null ;
}
2007-04-30 00:05:34 +02:00
return this . alternativeIP + " : " + port ;
}
2011-08-03 20:32:11 +02:00
2007-05-15 17:48:28 +02:00
/ * *
* @return the IP address of the peer represented by this yacySeed object as { @link InetAddress }
* /
2006-12-20 02:07:49 +01:00
public final InetAddress getInetAddress ( ) {
2011-08-03 20:32:11 +02:00
return Domains . dnsResolve ( getIP ( ) ) ;
2006-12-20 02:07:49 +01:00
}
2011-08-03 20:32:11 +02:00
2007-05-15 17:48:28 +02:00
/** @return the portnumber of this seed or <code>-1</code> if not present */
2006-12-20 02:07:49 +01:00
public final int getPort ( ) {
2011-10-04 11:06:24 +02:00
final String port = this . dna . get ( Seed . PORT ) ;
2012-01-03 17:49:37 +01:00
if ( port = = null ) {
return - 1 ;
}
2007-04-14 12:11:37 +02:00
/*if (port.length() < 2) return -1; It is possible to use port 0-9*/
2006-12-20 02:07:49 +01:00
return Integer . parseInt ( port ) ;
}
2011-08-03 20:32:11 +02:00
2007-05-15 17:48:28 +02:00
/** puts the current time into the lastseen field and cares about the time differential to UTC */
2007-02-03 00:54:27 +01:00
public final void setLastSeenUTC ( ) {
// because java thinks it must apply the UTC offset to the current time,
// to create a string that looks like our current time, it adds the local UTC offset to the
// time. To create a corrected UTC Date string, we first subtract the local UTC offset.
2012-01-03 17:49:37 +01:00
final GenericFormatter my_SHORT_SECOND_FORMATTER =
new GenericFormatter ( GenericFormatter . FORMAT_SHORT_SECOND , GenericFormatter . time_second ) ; // use our own formatter to prevent concurrency locks with other processes
final String ls =
my_SHORT_SECOND_FORMATTER
. format ( new Date ( System . currentTimeMillis ( ) /*- DateFormatter.UTCDiff()*/ ) ) ;
2010-01-13 21:01:46 +01:00
//System.out.println("SETTING LAST-SEEN of " + this.getName() + " to " + ls);
2012-01-03 17:49:37 +01:00
this . dna . put ( Seed . LASTSEEN , ls ) ;
2007-02-03 00:54:27 +01:00
}
2011-08-03 20:32:11 +02:00
2007-05-15 17:48:28 +02:00
/ * *
* @return the last seen time converted to UTC in milliseconds
* /
2007-02-03 00:54:27 +01:00
public final long getLastSeenUTC ( ) {
2005-09-27 18:28:55 +02:00
try {
2012-01-03 17:49:37 +01:00
final GenericFormatter my_SHORT_SECOND_FORMATTER =
new GenericFormatter ( GenericFormatter . FORMAT_SHORT_SECOND , GenericFormatter . time_second ) ; // use our own formatter to prevent concurrency locks with other processes
2011-10-04 11:06:24 +02:00
final long t = my_SHORT_SECOND_FORMATTER . parse ( get ( Seed . LASTSEEN , " 20040101000000 " ) ) . getTime ( ) ;
2007-02-03 00:54:27 +01:00
// getTime creates a UTC time number. But in this case java thinks, that the given
// time string is a local time, which has a local UTC offset applied.
// Therefore java subtracts the local UTC offset, to get a UTC number.
// But the given time string is already in UTC time, so the subtraction
// of the local UTC offset is wrong. We correct this here by adding the local UTC
// offset again.
2010-01-13 21:01:46 +01:00
return t /*+ DateFormatter.UTCDiff()*/ ;
2012-01-03 17:49:37 +01:00
} catch ( final java . text . ParseException e ) { // in case of an error make seed look old!!!
2011-01-03 21:52:54 +01:00
return System . currentTimeMillis ( ) - AbstractFormatter . dayMillis ;
2012-01-03 17:49:37 +01:00
} catch ( final java . lang . NumberFormatException e ) {
2011-01-03 21:52:54 +01:00
return System . currentTimeMillis ( ) - AbstractFormatter . dayMillis ;
2005-09-27 18:28:55 +02:00
}
}
2011-08-03 20:32:11 +02:00
2011-03-01 10:03:33 +01:00
/ * *
* test if the lastSeen time of the seed has a time - out
2012-01-03 17:49:37 +01:00
*
2011-03-01 10:03:33 +01:00
* @param milliseconds the maximum age of the last - seen value
* @return true , if the time between the last - seen time and now is greater then the given time - out
* /
2011-08-03 20:32:11 +02:00
public final boolean isLastSeenTimeout ( final long milliseconds ) {
final long d = Math . abs ( System . currentTimeMillis ( ) - getLastSeenUTC ( ) ) ;
2011-04-05 10:04:25 +02:00
return d > milliseconds ;
2011-03-01 10:03:33 +01:00
}
2005-10-16 01:37:37 +02:00
2011-09-15 01:34:05 +02:00
public final long getBirthdate ( ) {
2012-01-03 17:49:37 +01:00
if ( this . birthdate > 0 ) {
return this . birthdate ;
}
2011-09-15 01:34:05 +02:00
long b ;
try {
2012-01-03 17:49:37 +01:00
final GenericFormatter my_SHORT_SECOND_FORMATTER =
new GenericFormatter ( GenericFormatter . FORMAT_SHORT_SECOND , GenericFormatter . time_second ) ; // use our own formatter to prevent concurrency locks with other processes
2011-10-04 11:06:24 +02:00
b = my_SHORT_SECOND_FORMATTER . parse ( get ( Seed . BDATE , " 20040101000000 " ) ) . getTime ( ) ;
2012-01-03 17:49:37 +01:00
} catch ( final ParseException e ) {
2011-09-15 01:34:05 +02:00
b = System . currentTimeMillis ( ) ;
}
this . birthdate = b ;
return this . birthdate ;
}
2007-05-15 17:48:28 +02:00
/** @return the age of the seed in number of days */
2006-10-12 00:23:48 +02:00
public final int getAge ( ) {
2011-09-15 01:34:05 +02:00
return ( int ) Math . abs ( ( System . currentTimeMillis ( ) - getBirthdate ( ) ) / 1000 / 60 / 60 / 24 ) ;
2005-09-29 00:54:31 +02:00
}
2005-10-16 01:37:37 +02:00
2008-08-02 14:12:04 +02:00
public void setPeerTags ( final Set < String > keys ) {
2011-08-03 20:32:11 +02:00
this . dna . put ( PEERTAGS , MapTools . set2string ( keys , " | " , false ) ) ;
2006-10-10 22:09:26 +02:00
}
2006-10-12 00:23:48 +02:00
2008-01-11 15:13:08 +01:00
public Set < String > getPeerTags ( ) {
2009-10-11 02:24:42 +02:00
return MapTools . string2set ( get ( PEERTAGS , " * " ) , " | " ) ;
2006-10-10 22:09:26 +02:00
}
2006-10-12 00:23:48 +02:00
2010-04-15 15:22:59 +02:00
public boolean matchPeerTags ( final HandleSet searchHashes ) {
2008-08-02 14:12:04 +02:00
final String peertags = get ( PEERTAGS , " " ) ;
2012-01-03 17:49:37 +01:00
if ( peertags . equals ( " * " ) ) {
return true ;
}
2009-10-11 02:24:42 +02:00
final Set < String > tags = MapTools . string2set ( peertags , " | " ) ;
2008-08-02 14:12:04 +02:00
final Iterator < String > i = tags . iterator ( ) ;
2012-01-03 17:49:37 +01:00
while ( i . hasNext ( ) ) {
if ( searchHashes . has ( Word . word2hash ( i . next ( ) ) ) ) {
return true ;
}
2007-04-26 11:51:51 +02:00
}
return false ;
}
2005-07-19 02:26:31 +02:00
public int getPPM ( ) {
try {
2011-10-04 11:06:24 +02:00
return Integer . parseInt ( get ( Seed . ISPEED , Seed . ZERO ) ) ;
2012-01-03 17:49:37 +01:00
} catch ( final NumberFormatException e ) {
2005-07-19 02:26:31 +02:00
return 0 ;
}
}
2005-09-21 23:32:43 +02:00
2011-02-02 00:49:11 +01:00
public float getQPM ( ) {
2007-01-31 16:39:11 +01:00
try {
2011-10-04 11:06:24 +02:00
return Float . parseFloat ( get ( Seed . RSPEED , Seed . ZERO ) ) ;
2012-01-03 17:49:37 +01:00
} catch ( final NumberFormatException e ) {
2011-02-02 00:49:11 +01:00
return 0f ;
2007-01-31 16:39:11 +01:00
}
}
2006-10-12 00:23:48 +02:00
public final long getLinkCount ( ) {
2005-10-08 02:37:43 +02:00
try {
2011-10-04 11:06:24 +02:00
return getLong ( Seed . LCOUNT , 0 ) ;
2012-01-03 17:49:37 +01:00
} catch ( final NumberFormatException e ) {
2005-10-08 02:37:43 +02:00
return 0 ;
}
}
2005-10-16 01:37:37 +02:00
2009-12-21 12:36:48 +01:00
public final long getWordCount ( ) {
try {
2011-10-04 11:06:24 +02:00
return getLong ( Seed . ICOUNT , 0 ) ;
2012-01-03 17:49:37 +01:00
} catch ( final NumberFormatException e ) {
2009-12-21 12:36:48 +01:00
return 0 ;
}
}
2008-08-02 14:12:04 +02:00
private boolean getFlag ( final int flag ) {
2011-10-04 11:06:24 +02:00
final String flags = get ( Seed . FLAGS , Seed . FLAGSZERO ) ;
2011-04-12 07:02:36 +02:00
return ( new bitfield ( UTF8 . getBytes ( flags ) ) ) . get ( flag ) ;
2005-04-07 21:19:42 +02:00
}
2005-09-21 23:32:43 +02:00
2008-08-02 14:12:04 +02:00
private void setFlag ( final int flag , final boolean value ) {
2011-10-04 11:06:24 +02:00
String flags = get ( Seed . FLAGS , Seed . FLAGSZERO ) ;
2012-01-03 17:49:37 +01:00
if ( flags . length ( ) ! = 4 ) {
flags = Seed . FLAGSZERO ;
}
2011-04-12 07:02:36 +02:00
final bitfield f = new bitfield ( UTF8 . getBytes ( flags ) ) ;
2005-04-07 21:19:42 +02:00
f . set ( flag , value ) ;
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . FLAGS , UTF8 . String ( f . getBytes ( ) ) ) ;
2005-04-07 21:19:42 +02:00
}
2005-09-21 23:32:43 +02:00
2012-01-03 17:49:37 +01:00
public final void setFlagDirectConnect ( final boolean value ) {
setFlag ( FLAG_DIRECT_CONNECT , value ) ;
}
public final void setFlagAcceptRemoteCrawl ( final boolean value ) {
setFlag ( FLAG_ACCEPT_REMOTE_CRAWL , value ) ;
}
public final void setFlagAcceptRemoteIndex ( final boolean value ) {
setFlag ( FLAG_ACCEPT_REMOTE_INDEX , value ) ;
}
2012-05-25 15:33:02 +02:00
public final void setFlagRootNode ( final boolean value ) {
setFlag ( FLAG_ROOT_NODE , value ) ;
}
2012-01-03 17:49:37 +01:00
public final boolean getFlagDirectConnect ( ) {
return getFlag ( 0 ) ;
}
2006-10-12 00:23:48 +02:00
public final boolean getFlagAcceptRemoteCrawl ( ) {
2005-04-07 21:19:42 +02:00
//if (getVersion() < 0.300) return false;
//if (getVersion() < 0.334) return true;
return getFlag ( 1 ) ;
}
2012-01-03 17:49:37 +01:00
2006-10-12 00:23:48 +02:00
public final boolean getFlagAcceptRemoteIndex ( ) {
2005-04-07 21:19:42 +02:00
//if (getVersion() < 0.335) return false;
return getFlag ( 2 ) ;
}
2012-01-03 17:49:37 +01:00
2012-05-25 17:29:54 +02:00
public final boolean getFlagRootNode ( ) {
return getFlag ( FLAG_ROOT_NODE ) ;
}
2006-10-12 00:23:48 +02:00
public final void setUnusedFlags ( ) {
2012-01-03 17:49:37 +01:00
for ( int i = 4 ; i < 24 ; i + + ) {
2012-05-25 17:29:54 +02:00
setFlag ( i , false ) ;
2012-01-03 17:49:37 +01:00
}
2005-11-11 00:48:20 +01:00
}
2012-01-03 17:49:37 +01:00
2008-08-02 14:12:04 +02:00
public final boolean isType ( final String type ) {
2011-10-04 11:06:24 +02:00
return get ( Seed . PEERTYPE , " " ) . equals ( type ) ;
2006-09-14 11:28:17 +02:00
}
2012-01-03 17:49:37 +01:00
2006-10-12 00:23:48 +02:00
public final boolean isVirgin ( ) {
2011-10-04 11:06:24 +02:00
return get ( Seed . PEERTYPE , " " ) . equals ( Seed . PEERTYPE_VIRGIN ) ;
2005-04-07 21:19:42 +02:00
}
2012-01-03 17:49:37 +01:00
2006-10-12 00:23:48 +02:00
public final boolean isJunior ( ) {
2011-10-04 11:06:24 +02:00
return get ( Seed . PEERTYPE , " " ) . equals ( Seed . PEERTYPE_JUNIOR ) ;
2005-04-07 21:19:42 +02:00
}
2012-01-03 17:49:37 +01:00
2006-10-12 00:23:48 +02:00
public final boolean isSenior ( ) {
2011-10-04 11:06:24 +02:00
return get ( Seed . PEERTYPE , " " ) . equals ( Seed . PEERTYPE_SENIOR ) ;
2005-04-07 21:19:42 +02:00
}
2012-01-03 17:49:37 +01:00
2006-10-12 00:23:48 +02:00
public final boolean isPrincipal ( ) {
2011-10-04 11:06:24 +02:00
return get ( Seed . PEERTYPE , " " ) . equals ( Seed . PEERTYPE_PRINCIPAL ) ;
2005-04-07 21:19:42 +02:00
}
2012-01-03 17:49:37 +01:00
2008-02-10 16:57:52 +01:00
public final boolean isPotential ( ) {
return isVirgin ( ) | | isJunior ( ) ;
}
2012-01-03 17:49:37 +01:00
2008-02-10 16:57:52 +01:00
public final boolean isActive ( ) {
return isSenior ( ) | | isPrincipal ( ) ;
}
2012-01-03 17:49:37 +01:00
2006-10-12 00:23:48 +02:00
public final boolean isOnline ( ) {
return isSenior ( ) | | isPrincipal ( ) ;
2005-04-07 21:19:42 +02:00
}
2012-01-03 17:49:37 +01:00
2006-10-12 00:23:48 +02:00
public final boolean isOnline ( final String type ) {
2011-10-04 11:06:24 +02:00
return type . equals ( Seed . PEERTYPE_SENIOR ) | | type . equals ( Seed . PEERTYPE_PRINCIPAL ) ;
2005-10-18 01:12:40 +02:00
}
2011-08-03 20:32:11 +02:00
public long nextLong ( final Random random , final long n ) {
2010-09-26 00:32:26 +02:00
return Math . abs ( random . nextLong ( ) ) % n ;
}
2008-02-10 16:57:52 +01:00
2011-10-04 11:06:24 +02:00
private static byte [ ] bestGap ( final SeedDB seedDB ) {
2011-08-03 20:32:11 +02:00
final byte [ ] randomHash = randomHash ( ) ;
2012-01-03 17:49:37 +01:00
if ( seedDB = = null | | seedDB . sizeConnected ( ) < = 2 ) {
2008-03-11 00:28:05 +01:00
// use random hash
2010-09-16 00:11:52 +02:00
return randomHash ;
2008-03-11 00:28:05 +01:00
}
// find gaps
2008-11-03 01:27:23 +01:00
final TreeMap < Long , String > gaps = hashGaps ( seedDB ) ;
2011-08-03 20:32:11 +02:00
2008-03-11 00:28:05 +01:00
// take one gap; prefer biggest but take also another smaller by chance
String interval = null ;
2012-01-03 17:49:37 +01:00
while ( ! gaps . isEmpty ( ) ) {
2008-03-11 00:28:05 +01:00
interval = gaps . remove ( gaps . lastKey ( ) ) ;
2012-01-03 17:49:37 +01:00
if ( random . nextBoolean ( ) ) {
break ;
}
}
if ( interval = = null ) {
return randomHash ( ) ;
2008-03-11 00:28:05 +01:00
}
2011-08-03 20:32:11 +02:00
2008-03-11 00:28:05 +01:00
// find dht position and size of gap
2012-01-03 17:49:37 +01:00
final long left =
FlatWordPartitionScheme . std . dhtPosition ( ASCII . getBytes ( interval . substring ( 0 , 12 ) ) , null ) ;
final long right =
FlatWordPartitionScheme . std . dhtPosition ( ASCII . getBytes ( interval . substring ( 12 ) ) , null ) ;
2010-09-26 00:32:26 +02:00
final long gap8 = FlatWordPartitionScheme . dhtDistance ( left , right ) > > 3 ; // 1/8 of a gap
2011-08-03 20:32:11 +02:00
final long gapx = gap8 + ( Math . abs ( random . nextLong ( ) ) % ( 6 * gap8 ) ) ;
final long gappos = ( Long . MAX_VALUE - left > = gapx ) ? left + gapx : ( left - Long . MAX_VALUE ) + gapx ;
final byte [ ] computedHash = FlatWordPartitionScheme . positionToHash ( gappos ) ;
2010-09-16 00:11:52 +02:00
// the computed hash is the perfect position (modulo gap4 population and gap alternatives)
// this is too tight. The hash must be more randomized. We take only (!) the first two bytes
// of the computed hash and add random bytes at the remaining positions. The first two bytes
// of the hash may have 64*64 = 2^^10 positions, good for over 1 million peers.
byte [ ] combined = new byte [ 12 ] ;
System . arraycopy ( computedHash , 0 , combined , 0 , 2 ) ;
System . arraycopy ( randomHash , 2 , combined , 2 , 10 ) ;
2011-11-30 23:06:13 +01:00
// patch for the 'first sector' problem
2012-01-03 17:49:37 +01:00
if ( combined [ 0 ] = = 'A' | | combined [ 1 ] = = 'D' ) { // for some strange reason there are too many of them
2011-11-30 23:06:13 +01:00
combined [ 1 ] = randomHash [ 1 ] ;
}
2010-09-16 00:11:52 +02:00
// finally check if the hash is already known
2012-01-03 17:49:37 +01:00
while ( seedDB . hasConnected ( combined )
| | seedDB . hasDisconnected ( combined )
| | seedDB . hasPotential ( combined ) ) {
2010-09-16 00:11:52 +02:00
// if we are lucky then this loop will never run
combined = randomHash ( ) ;
}
return combined ;
2008-03-11 00:28:05 +01:00
}
2011-08-03 20:32:11 +02:00
2011-10-04 11:06:24 +02:00
private static TreeMap < Long , String > hashGaps ( final SeedDB seedDB ) {
2012-01-03 17:49:37 +01:00
final TreeMap < Long , String > gaps = new TreeMap < Long , String > ( ) ;
if ( seedDB = = null ) {
return gaps ;
}
2011-08-03 20:32:11 +02:00
2011-10-04 11:06:24 +02:00
final Iterator < Seed > i = seedDB . seedsConnected ( true , false , null , ( float ) 0 . 0 ) ;
2008-11-03 01:27:23 +01:00
long l ;
2011-10-04 11:06:24 +02:00
Seed s0 = null , s1 , first = null ;
2012-01-03 17:49:37 +01:00
while ( i . hasNext ( ) ) {
2008-03-11 00:28:05 +01:00
s1 = i . next ( ) ;
2012-01-03 17:49:37 +01:00
if ( s0 = = null ) {
2008-03-11 00:28:05 +01:00
s0 = s1 ;
first = s0 ;
continue ;
}
2012-01-03 17:49:37 +01:00
l =
FlatWordPartitionScheme . dhtDistance (
2011-05-27 10:24:54 +02:00
FlatWordPartitionScheme . std . dhtPosition ( ASCII . getBytes ( s0 . hash ) , null ) ,
FlatWordPartitionScheme . std . dhtPosition ( ASCII . getBytes ( s1 . hash ) , null ) ) ;
2008-11-03 01:27:23 +01:00
gaps . put ( l , s0 . hash + s1 . hash ) ;
2008-03-11 00:28:05 +01:00
s0 = s1 ;
}
// compute also the last gap
2012-01-03 17:49:37 +01:00
if ( ( first ! = null ) & & ( s0 ! = null ) ) {
l =
FlatWordPartitionScheme . dhtDistance (
2011-05-27 10:24:54 +02:00
FlatWordPartitionScheme . std . dhtPosition ( ASCII . getBytes ( s0 . hash ) , null ) ,
FlatWordPartitionScheme . std . dhtPosition ( ASCII . getBytes ( first . hash ) , null ) ) ;
2008-11-03 01:27:23 +01:00
gaps . put ( l , s0 . hash + first . hash ) ;
2008-03-11 00:28:05 +01:00
}
return gaps ;
}
2011-08-03 20:32:11 +02:00
2011-10-04 11:06:24 +02:00
public static Seed genLocalSeed ( final SeedDB db ) {
2008-05-06 01:13:47 +02:00
return genLocalSeed ( db , 0 , null ) ; // an anonymous peer
}
2011-08-03 20:32:11 +02:00
2011-10-04 11:06:24 +02:00
public static Seed genLocalSeed ( final SeedDB db , final int port , final String name ) {
2008-05-06 01:13:47 +02:00
// generate a seed for the local peer
2006-10-12 00:23:48 +02:00
// this is the birthplace of a seed, that then will start to travel to other peers
2011-05-27 10:24:54 +02:00
final String hashs = ASCII . String ( bestGap ( db ) ) ;
2011-10-04 11:06:24 +02:00
Network . log . logInfo ( " init: OWN SEED = " + hashs ) ;
2006-10-12 00:23:48 +02:00
2011-10-04 11:06:24 +02:00
final Seed newSeed = new Seed ( hashs ) ;
2006-10-12 00:23:48 +02:00
// now calculate other information about the host
2011-10-04 11:06:24 +02:00
newSeed . dna . put ( Seed . NAME , ( name ) = = null ? defaultPeerName ( ) : name ) ;
newSeed . dna . put ( Seed . PORT , Integer . toString ( ( port < = 0 ) ? 8090 : port ) ) ;
2006-10-12 00:23:48 +02:00
return newSeed ;
2005-04-07 21:19:42 +02:00
}
2005-11-14 01:23:20 +01:00
//public static String randomHash() { return "zLXFf5lTteUv"; } // only for debugging
2006-10-12 00:23:48 +02:00
2009-04-16 17:29:00 +02:00
public static byte [ ] randomHash ( ) {
2006-10-12 00:23:48 +02:00
final String hash =
2012-01-03 17:49:37 +01:00
Base64Order . enhancedCoder
. encode ( Digest . encodeMD5Raw ( Long . toString ( random . nextLong ( ) ) ) )
. substring ( 0 , 6 )
+ Base64Order . enhancedCoder
. encode ( Digest . encodeMD5Raw ( Long . toString ( random . nextLong ( ) ) ) )
. substring ( 0 , 6 ) ;
2011-05-27 10:24:54 +02:00
return ASCII . getBytes ( hash ) ;
2005-11-11 00:48:20 +01:00
}
2006-10-12 00:23:48 +02:00
2012-01-03 17:49:37 +01:00
public static Seed genRemoteSeed (
final String seedStr ,
final String key ,
final boolean ownSeed ,
final String patchIP ) throws IOException {
2005-09-27 18:28:55 +02:00
// this method is used to convert the external representation of a seed into a seed object
2008-05-25 20:35:38 +02:00
// yacyCore.log.logFinest("genRemoteSeed: seedStr=" + seedStr + " key=" + key);
// check protocol and syntax of seed
2012-01-03 17:49:37 +01:00
if ( seedStr = = null ) {
throw new IOException ( " seedStr == null " ) ;
}
if ( seedStr . length ( ) = = 0 ) {
throw new IOException ( " seedStr.length() == 0 " ) ;
}
2005-10-16 01:37:37 +02:00
final String seed = crypt . simpleDecode ( seedStr , key ) ;
2012-01-03 17:49:37 +01:00
if ( seed = = null ) {
throw new IOException ( " seed == null " ) ;
}
if ( seed . length ( ) = = 0 ) {
throw new IOException ( " seed.length() == 0 " ) ;
}
2011-08-03 20:32:11 +02:00
2008-05-25 20:35:38 +02:00
// extract hash
2010-02-15 16:57:35 +01:00
final ConcurrentHashMap < String , String > dna = MapTools . string2map ( seed , " , " ) ;
2011-10-04 11:06:24 +02:00
final String hash = dna . remove ( Seed . HASH ) ;
2012-01-03 17:49:37 +01:00
if ( hash = = null ) {
throw new IOException ( " hash == null " ) ;
}
2011-10-04 11:06:24 +02:00
final Seed resultSeed = new Seed ( hash , dna ) ;
2008-05-25 20:35:38 +02:00
// check semantics of content
2011-04-29 12:58:12 +02:00
String testResult = resultSeed . isProper ( ownSeed ) ;
2012-01-03 17:49:37 +01:00
if ( testResult ! = null & & patchIP ! = null ) {
2011-04-29 12:58:12 +02:00
// in case that this proper-Test fails and a patchIP is given
// then replace the given IP in the resultSeed with given patchIP
// this is done if a remote peer reports its IP in a wrong way (maybe fraud attempt)
resultSeed . setIP ( patchIP ) ;
testResult = resultSeed . isProper ( ownSeed ) ;
}
2012-01-03 17:49:37 +01:00
if ( testResult ! = null ) {
throw new IOException ( " seed is not proper ( " + testResult + " ): " + resultSeed ) ;
}
2011-08-03 20:32:11 +02:00
2008-05-25 20:35:38 +02:00
// seed ok
2006-04-06 18:28:28 +02:00
return resultSeed ;
2005-04-07 21:19:42 +02:00
}
2010-10-27 15:21:18 +02:00
// TODO: add here IP ranges to accept also intranet networks
2008-08-02 14:12:04 +02:00
public final String isProper ( final boolean checkOwnIP ) {
2008-05-25 20:35:38 +02:00
// checks if everything is ok with that seed
2011-08-03 20:32:11 +02:00
2008-05-25 20:35:38 +02:00
// check hash
2012-01-03 17:49:37 +01:00
if ( this . hash = = null ) {
return " hash is null " ;
}
if ( this . hash . length ( ) ! = Word . commonHashLength ) {
return " wrong hash length ( " + this . hash . length ( ) + " ) " ;
}
2008-05-25 20:35:38 +02:00
// name
2011-10-04 11:06:24 +02:00
final String peerName = this . dna . get ( Seed . NAME ) ;
2012-01-03 17:49:37 +01:00
if ( peerName = = null ) {
return " no peer name given " ;
}
2011-10-04 11:06:24 +02:00
this . dna . put ( Seed . NAME , checkPeerName ( peerName ) ) ;
2008-08-08 15:56:29 +02:00
// type
2011-08-03 20:32:11 +02:00
final String peerType = getPeerType ( ) ;
2012-01-03 17:49:37 +01:00
if ( ( peerType = = null )
| | ! ( peerType . equals ( Seed . PEERTYPE_VIRGIN )
| | peerType . equals ( Seed . PEERTYPE_JUNIOR )
| | peerType . equals ( Seed . PEERTYPE_SENIOR ) | | peerType . equals ( Seed . PEERTYPE_PRINCIPAL ) ) ) {
2008-08-08 15:56:29 +02:00
return " invalid peerType ' " + peerType + " ' " ;
2012-01-03 17:49:37 +01:00
}
2008-08-08 15:56:29 +02:00
2008-05-25 20:35:38 +02:00
// check IP
2012-01-03 17:49:37 +01:00
if ( ! checkOwnIP ) {
2011-08-03 20:32:11 +02:00
// checking of IP is omitted if we read the own seed file
final String ipCheck = isProperIP ( getIP ( ) ) ;
2012-01-03 17:49:37 +01:00
if ( ipCheck ! = null ) {
return ipCheck ;
}
2008-06-05 00:24:00 +02:00
}
2011-08-03 20:32:11 +02:00
2008-05-25 20:35:38 +02:00
// seedURL
2010-10-27 15:21:18 +02:00
final String seedURL = this . dna . get ( SEEDLISTURL ) ;
2012-01-03 17:49:37 +01:00
if ( seedURL ! = null & & seedURL . length ( ) > 0 ) {
if ( ! seedURL . startsWith ( " http:// " ) & & ! seedURL . startsWith ( " https:// " ) ) {
return " wrong protocol for seedURL " ;
}
2008-05-25 20:35:38 +02:00
try {
2008-08-02 14:12:04 +02:00
final URL url = new URL ( seedURL ) ;
final String host = url . getHost ( ) ;
2012-01-03 17:49:37 +01:00
if ( host . equals ( " localhost " )
| | host . startsWith ( " 127. " )
| | ( host . startsWith ( " 0:0:0:0:0:0:0:1 " ) ) ) {
return " seedURL in localhost rejected " ;
}
} catch ( final MalformedURLException e ) {
2008-05-25 20:35:38 +02:00
return " seedURL malformed " ;
}
}
return null ;
}
2011-08-03 20:32:11 +02:00
2008-08-02 14:12:04 +02:00
public static final String isProperIP ( final String ipString ) {
2010-04-15 15:22:59 +02:00
// returns null if ipString is proper, a string with the cause otherwise
2012-01-03 17:49:37 +01:00
if ( ipString = = null ) {
return ipString + " -> IP is null " ;
}
if ( ipString . length ( ) > 0 & & ipString . length ( ) < 8 ) {
return ipString + " -> IP is too short: " ;
}
if ( Switchboard . getSwitchboard ( ) . isAllIPMode ( ) ) {
return null ;
}
2011-09-30 10:26:31 +02:00
final boolean islocal = Domains . isLocal ( ipString , null ) ;
2011-09-08 21:13:19 +02:00
//if (islocal && Switchboard.getSwitchboard().isGlobalMode()) return ipString + " - local IP for global mode rejected";
2012-01-03 17:49:37 +01:00
if ( ! islocal & & Switchboard . getSwitchboard ( ) . isIntranetMode ( ) ) {
return ipString + " - global IP for intranet mode rejected " ;
}
2011-04-29 04:19:13 +02:00
return null ;
2008-06-05 13:01:20 +02:00
}
2011-03-15 02:03:35 +01:00
@Override
2006-10-12 00:23:48 +02:00
public final String toString ( ) {
2011-08-03 20:32:11 +02:00
final ConcurrentMap < String , String > copymap = new ConcurrentHashMap < String , String > ( ) ;
2009-09-28 17:23:15 +02:00
copymap . putAll ( this . dna ) ;
2012-01-03 17:49:37 +01:00
copymap . put ( Seed . HASH , this . hash ) ; // set hash into seed code structure
2009-10-11 02:24:42 +02:00
return MapTools . map2string ( copymap , " , " , true ) ; // generate string representation
2005-04-07 21:19:42 +02:00
}
2008-08-02 14:12:04 +02:00
public final String genSeedStr ( final String key ) {
2005-10-16 01:37:37 +02:00
// use a default encoding
2011-08-03 20:32:11 +02:00
final String r = toString ( ) ;
final String z = crypt . simpleEncode ( r , key , 'z' ) ;
final String b = crypt . simpleEncode ( r , key , 'b' ) ;
2008-02-17 13:36:43 +01:00
// the compressed string may be longer that the uncompressed if there is too much overhead for compression meta-info
// take simply that string that is shorter
2012-01-03 17:49:37 +01:00
if ( b . length ( ) < z . length ( ) ) {
return b ;
} else {
return z ;
}
2005-04-07 21:19:42 +02:00
}
2008-08-02 14:12:04 +02:00
public final void save ( final File f ) throws IOException {
2011-08-03 20:32:11 +02:00
final String out = crypt . simpleEncode ( toString ( ) , null , 'p' ) ;
2005-10-16 01:37:37 +02:00
final FileWriter fw = new FileWriter ( f ) ;
fw . write ( out , 0 , out . length ( ) ) ;
fw . close ( ) ;
2005-04-07 21:19:42 +02:00
}
2011-10-04 11:06:24 +02:00
public static Seed load ( final File f ) throws IOException {
2005-10-16 01:37:37 +02:00
final FileReader fr = new FileReader ( f ) ;
final char [ ] b = new char [ ( int ) f . length ( ) ] ;
fr . read ( b , 0 , b . length ) ;
fr . close ( ) ;
2011-10-04 11:06:24 +02:00
final Seed mySeed = genRemoteSeed ( new String ( b ) , null , true , null ) ;
2010-10-26 17:00:22 +02:00
assert mySeed ! = null ; // in case of an error, an IOException is thrown
2011-10-04 11:06:24 +02:00
mySeed . dna . put ( Seed . IP , " " ) ; // set own IP as unknown
2008-06-05 00:24:00 +02:00
return mySeed ;
2005-04-07 21:19:42 +02:00
}
2011-03-15 02:03:35 +01:00
@Override
2011-10-04 11:06:24 +02:00
public final Seed clone ( ) {
2011-08-03 20:32:11 +02:00
final ConcurrentHashMap < String , String > ndna = new ConcurrentHashMap < String , String > ( ) ;
2010-02-15 16:57:35 +01:00
ndna . putAll ( this . dna ) ;
2011-10-04 11:06:24 +02:00
return new Seed ( this . hash , ndna ) ;
2005-04-07 21:19:42 +02:00
}
2011-02-13 18:37:28 +01:00
@Override
2011-10-04 11:06:24 +02:00
public int compareTo ( final Seed arg0 ) {
2011-02-13 18:37:28 +01:00
// TODO Auto-generated method stub
2011-08-03 20:32:11 +02:00
final int o1 = hashCode ( ) ;
final int o2 = arg0 . hashCode ( ) ;
2012-01-03 17:49:37 +01:00
if ( o1 > o2 ) {
return 1 ;
}
if ( o2 > o1 ) {
return - 1 ;
}
2011-02-13 18:37:28 +01:00
return 0 ;
}
2011-08-03 20:32:11 +02:00
2011-03-15 02:03:35 +01:00
@Override
2011-02-13 18:37:28 +01:00
public int hashCode ( ) {
2011-08-03 20:32:11 +02:00
return ( int ) ( Base64Order . enhancedCoder . cardinal ( this . hash ) & ( Integer . MAX_VALUE ) ) ;
2011-02-13 18:37:28 +01:00
}
@Override
2011-10-04 11:06:24 +02:00
public int compare ( final Seed o1 , final Seed o2 ) {
2011-02-13 18:37:28 +01:00
return o1 . compareTo ( o2 ) ;
}
2011-08-03 20:32:11 +02:00
2011-11-30 23:06:13 +01:00
public static void main ( final String [ ] args ) {
final ScoreMap < Integer > s = new ClusteredScoreMap < Integer > ( ) ;
2012-01-03 17:49:37 +01:00
for ( int i = 0 ; i < 10000 ; i + + ) {
2011-11-30 23:06:13 +01:00
final byte [ ] b = randomHash ( ) ;
s . inc ( 0xff & Base64Order . enhancedCoder . decodeByte ( b [ 0 ] ) ) ;
//System.out.println(ASCII.String(b));
}
final Iterator < Integer > i = s . keys ( false ) ;
2012-01-03 17:49:37 +01:00
while ( i . hasNext ( ) ) {
2011-11-30 23:06:13 +01:00
System . out . println ( i . next ( ) ) ;
}
}
2005-10-17 17:46:12 +02:00
}