@ -81,13 +81,18 @@ import de.anomic.server.serverObjects;
import de.anomic.server.serverSwitch ;
import de.anomic.server.servletProperties ;
public class yacysearch {
public class yacysearch
{
public static serverObjects respond ( final RequestHeader header , final serverObjects post , final serverSwitch env ) {
public static serverObjects respond (
final RequestHeader header ,
final serverObjects post ,
final serverSwitch env ) {
final Switchboard sb = ( Switchboard ) env ;
sb . localSearchLastAccess = System . currentTimeMillis ( ) ;
final boolean searchAllowed = sb . getConfigBool ( "publicSearchpage" , true ) | | sb . verifyAuthentication ( header ) ;
final boolean searchAllowed =
sb . getConfigBool ( "publicSearchpage" , true ) | | sb . verifyAuthentication ( header ) ;
boolean authenticated = sb . adminAuthenticated ( header ) > = 2 ;
if ( ! authenticated ) {
@ -96,15 +101,17 @@ public class yacysearch {
}
final boolean localhostAccess = sb . accessFromLocalhost ( header ) ;
final String promoteSearchPageGreeting =
( env . getConfigBool ( SwitchboardConstants . GREETING_NETWORK_NAME , false ) ) ?
env . getConfig ( "network.unit.description" , "" ) :
env . getConfig ( SwitchboardConstants . GREETING , "" ) ;
( env . getConfigBool ( SwitchboardConstants . GREETING_NETWORK_NAME , false ) ) ? env . getConfig (
"network.unit.description" ,
"" ) : env . getConfig ( SwitchboardConstants . GREETING , "" ) ;
final String client = header . get ( HeaderFramework . CONNECTION_PROP_CLIENTIP ) ; // the search client who initiated the search
// get query
final String originalquerystring = ( post = = null ) ? "" : post . get ( "query" , post . get ( "search" , "" ) ) . trim ( ) ;
final String originalquerystring =
( post = = null ) ? "" : post . get ( "query" , post . get ( "search" , "" ) ) . trim ( ) ;
String querystring = originalquerystring . replace ( '+' , ' ' ) . replace ( '*' , ' ' ) . trim ( ) ;
CacheStrategy snippetFetchStrategy = ( post = = null ) ? null : CacheStrategy . parse ( post . get ( "verify" , "cacheonly" ) ) ;
CacheStrategy snippetFetchStrategy =
( post = = null ) ? null : CacheStrategy . parse ( post . get ( "verify" , "cacheonly" ) ) ;
final servletProperties prop = new servletProperties ( ) ;
prop . put ( "topmenu" , sb . getConfigBool ( "publicTopmenu" , true ) ? 1 : 0 ) ;
@ -124,8 +131,12 @@ public class yacysearch {
final boolean rss = EXT . equals ( "rss" ) ;
final boolean json = EXT . equals ( "json" ) ;
prop . put ( "promoteSearchPageGreeting" , promoteSearchPageGreeting ) ;
prop . put ( "promoteSearchPageGreeting.homepage" , sb . getConfig ( SwitchboardConstants . GREETING_HOMEPAGE , "" ) ) ;
prop . put ( "promoteSearchPageGreeting.smallImage" , sb . getConfig ( SwitchboardConstants . GREETING_SMALL_IMAGE , "" ) ) ;
prop . put (
"promoteSearchPageGreeting.homepage" ,
sb . getConfig ( SwitchboardConstants . GREETING_HOMEPAGE , "" ) ) ;
prop . put (
"promoteSearchPageGreeting.smallImage" ,
sb . getConfig ( SwitchboardConstants . GREETING_SMALL_IMAGE , "" ) ) ;
if ( post = = null | | indexSegment = = null | | env = = null | | ! searchAllowed ) {
// we create empty entries for template strings
prop . put ( "searchagain" , "0" ) ;
@ -140,8 +151,12 @@ public class yacysearch {
prop . put ( "constraint" , "" ) ;
prop . put ( "cat" , "href" ) ;
prop . put ( "depth" , "0" ) ;
prop . put ( "search.verify" , ( post = = null ) ? sb . getConfig ( "search.verify" , "iffresh" ) : post . get ( "verify" , "iffresh" ) ) ;
prop . put ( "search.navigation" , ( post = = null ) ? sb . getConfig ( "search.navigation" , "all" ) : post . get ( "nav" , "all" ) ) ;
prop . put (
"search.verify" ,
( post = = null ) ? sb . getConfig ( "search.verify" , "iffresh" ) : post . get ( "verify" , "iffresh" ) ) ;
prop . put (
"search.navigation" ,
( post = = null ) ? sb . getConfig ( "search.navigation" , "all" ) : post . get ( "nav" , "all" ) ) ;
prop . put ( "contentdom" , "text" ) ;
prop . put ( "contentdomCheckText" , "1" ) ;
prop . put ( "contentdomCheckAudio" , "0" ) ;
@ -180,7 +195,14 @@ public class yacysearch {
// collect search attributes
int maximumRecords = Math . min ( ( authenticated ) ? ( snippetFetchStrategy ! = null & & snippetFetchStrategy . isAllowedToFetchOnline ( ) ? 100 : 5000 ) : ( snippetFetchStrategy ! = null & & snippetFetchStrategy . isAllowedToFetchOnline ( ) ? 20 : 1000 ) , post . getInt ( "maximumRecords" , post . getInt ( "count" , 10 ) ) ) ; // SRU syntax with old property as alternative
int maximumRecords =
Math . min (
( authenticated )
? ( snippetFetchStrategy ! = null & & snippetFetchStrategy . isAllowedToFetchOnline ( )
? 100
: 5000 ) : ( snippetFetchStrategy ! = null
& & snippetFetchStrategy . isAllowedToFetchOnline ( ) ? 20 : 1000 ) ,
post . getInt ( "maximumRecords" , post . getInt ( "count" , 10 ) ) ) ; // SRU syntax with old property as alternative
int startRecord = post . getInt ( "startRecord" , post . getInt ( "offset" , 0 ) ) ;
boolean global = post . get ( "resource" , "local" ) . equals ( "global" ) & & sb . peers . sizeConnected ( ) > 0 ;
@ -198,15 +220,21 @@ public class yacysearch {
prefermask = ".*" + prefermask + ".*" ;
}
Bitfield constraint = ( post ! = null & & post . containsKey ( "constraint" ) & & ! post . get ( "constraint" , "" ) . isEmpty ( ) ) ? new Bitfield ( 4 , post . get ( "constraint" , "______" ) ) : null ;
Bitfield constraint =
( post ! = null & & post . containsKey ( "constraint" ) & & ! post . get ( "constraint" , "" ) . isEmpty ( ) )
? new Bitfield ( 4 , post . get ( "constraint" , "______" ) )
: null ;
if ( indexof ) {
constraint = new Bitfield ( 4 ) ;
constraint . set ( Condenser . flag_cat_indexof , true ) ;
}
// SEARCH
final boolean clustersearch = sb . isRobinsonMode ( ) & & ( sb . getConfig ( "cluster.mode" , "" ) . equals ( "privatecluster" ) | | sb . getConfig ( "cluster.mode" , "" ) . equals ( "publiccluster" ) ) ;
final boolean indexReceiveGranted = sb . getConfigBool ( SwitchboardConstants . INDEX_RECEIVE_ALLOW , true ) | | sb . getConfigBool ( SwitchboardConstants . INDEX_RECEIVE_AUTODISABLED , true ) | | clustersearch ;
final boolean clustersearch = sb . isRobinsonMode ( ) & & sb . getConfig ( SwitchboardConstants . CLUSTER_MODE , "" ) . equals ( SwitchboardConstants . CLUSTER_MODE_PUBLIC_CLUSTER ) ;
final boolean indexReceiveGranted =
sb . getConfigBool ( SwitchboardConstants . INDEX_RECEIVE_ALLOW , true )
| | sb . getConfigBool ( SwitchboardConstants . INDEX_RECEIVE_AUTODISABLED , true )
| | clustersearch ;
global = global & & indexReceiveGranted ; // if the user does not want indexes from remote peers, it cannot be a global searchnn
// increase search statistic counter
@ -225,13 +253,18 @@ public class yacysearch {
}
// find search domain
final ContentDomain contentdom = ContentDomain . contentdomParser ( post = = null ? "text" : post . get ( "contentdom" , "text" ) ) ;
final ContentDomain contentdom =
ContentDomain . contentdomParser ( post = = null ? "text" : post . get ( "contentdom" , "text" ) ) ;
// patch until better search profiles are available
if ( contentdom = = ContentDomain . TEXT ) {
if ( maximumRecords > 50 & & maximumRecords < 100 ) maximumRecords = 10 ;
if ( maximumRecords > 50 & & maximumRecords < 100 ) {
maximumRecords = 10 ;
}
} else {
if ( maximumRecords < = 32 ) maximumRecords = 64 ;
if ( maximumRecords < = 32 ) {
maximumRecords = 64 ;
}
}
// check the search tracker
@ -246,33 +279,67 @@ public class yacysearch {
snippetFetchStrategy = null ;
}
block = true ;
Log . logWarning ( "LOCAL_SEARCH" , "ACCESS CONTROL: BLACKLISTED CLIENT FROM " + client + " gets no permission to search" ) ;
Log . logWarning ( "LOCAL_SEARCH" , "ACCESS CONTROL: BLACKLISTED CLIENT FROM "
+ client
+ " gets no permission to search" ) ;
} else if ( Domains . matchesList ( client , sb . networkWhitelist ) ) {
Log . logInfo ( "LOCAL_SEARCH" , "ACCESS CONTROL: WHITELISTED CLIENT FROM " + client + " gets no search restrictions" ) ;
Log . logInfo ( "LOCAL_SEARCH" , "ACCESS CONTROL: WHITELISTED CLIENT FROM "
+ client
+ " gets no search restrictions" ) ;
} else if ( ! authenticated & & ! localhostAccess ) {
// in case that we do a global search or we want to fetch snippets, we check for DoS cases
synchronized ( trackerHandles ) {
final int accInThreeSeconds = trackerHandles . tailSet ( Long . valueOf ( System . currentTimeMillis ( ) - 3000 ) ) . size ( ) ;
final int accInOneMinute = trackerHandles . tailSet ( Long . valueOf ( System . currentTimeMillis ( ) - 60000 ) ) . size ( ) ;
final int accInTenMinutes = trackerHandles . tailSet ( Long . valueOf ( System . currentTimeMillis ( ) - 600000 ) ) . size ( ) ;
final int accInThreeSeconds =
trackerHandles . tailSet ( Long . valueOf ( System . currentTimeMillis ( ) - 3000 ) ) . size ( ) ;
final int accInOneMinute =
trackerHandles . tailSet ( Long . valueOf ( System . currentTimeMillis ( ) - 60000 ) ) . size ( ) ;
final int accInTenMinutes =
trackerHandles . tailSet ( Long . valueOf ( System . currentTimeMillis ( ) - 600000 ) ) . size ( ) ;
// protections against too strong YaCy network load, reduces remote search
if ( global ) {
if ( accInTenMinutes > = 60 | | accInOneMinute > = 6 | | accInThreeSeconds > = 1 ) {
global = false ;
Log . logWarning ( "LOCAL_SEARCH" , "ACCESS CONTROL: CLIENT FROM " + client + ": " + accInThreeSeconds + "/3s, " + accInOneMinute + "/60s, " + accInTenMinutes + "/600s, " + " requests, disallowed global search" ) ;
Log . logWarning ( "LOCAL_SEARCH" , "ACCESS CONTROL: CLIENT FROM "
+ client
+ ": "
+ accInThreeSeconds
+ "/3s, "
+ accInOneMinute
+ "/60s, "
+ accInTenMinutes
+ "/600s, "
+ " requests, disallowed global search" ) ;
}
}
// protection against too many remote server snippet loads (protects traffic on server)
if ( snippetFetchStrategy ! = null & & snippetFetchStrategy . isAllowedToFetchOnline ( ) ) {
if ( accInTenMinutes > = 20 | | accInOneMinute > = 4 | | accInThreeSeconds > = 1 ) {
snippetFetchStrategy = CacheStrategy . CACHEONLY ;
Log . logWarning ( "LOCAL_SEARCH" , "ACCESS CONTROL: CLIENT FROM " + client + ": " + accInThreeSeconds + "/3s, " + accInOneMinute + "/60s, " + accInTenMinutes + "/600s, " + " requests, disallowed remote snippet loading" ) ;
Log . logWarning ( "LOCAL_SEARCH" , "ACCESS CONTROL: CLIENT FROM "
+ client
+ ": "
+ accInThreeSeconds
+ "/3s, "
+ accInOneMinute
+ "/60s, "
+ accInTenMinutes
+ "/600s, "
+ " requests, disallowed remote snippet loading" ) ;
}
}
// general load protection
if ( accInTenMinutes > = 3000 | | accInOneMinute > = 600 | | accInThreeSeconds > = 60 ) {
block = true ;
Log . logWarning ( "LOCAL_SEARCH" , "ACCESS CONTROL: CLIENT FROM " + client + ": " + accInThreeSeconds + "/3s, " + accInOneMinute + "/60s, " + accInTenMinutes + "/600s, " + " requests, disallowed search" ) ;
Log . logWarning ( "LOCAL_SEARCH" , "ACCESS CONTROL: CLIENT FROM "
+ client
+ ": "
+ accInThreeSeconds
+ "/3s, "
+ accInOneMinute
+ "/60s, "
+ accInTenMinutes
+ "/600s, "
+ " requests, disallowed search" ) ;
}
}
}
@ -363,7 +430,9 @@ public class yacysearch {
}
String ft = querystring . substring ( filetype + 9 , ftb ) ;
querystring = querystring . replace ( "filetype:" + ft , "" ) ;
while ( ! ft . isEmpty ( ) & & ft . charAt ( 0 ) = = '.' ) ft = ft . substring ( 1 ) ;
while ( ! ft . isEmpty ( ) & & ft . charAt ( 0 ) = = '.' ) {
ft = ft . substring ( 1 ) ;
}
if ( ! ft . isEmpty ( ) ) {
if ( urlmask = = null ) {
urlmask = ".*\\." + ft ;
@ -382,7 +451,9 @@ public class yacysearch {
if ( tenant ! = null ) {
if ( urlmask = = null ) {
urlmask = ".*" + tenant + ".*" ;
} else urlmask = ".*" + tenant + urlmask ;
} else {
urlmask = ".*" + tenant + urlmask ;
}
}
}
final int site = querystring . indexOf ( "site:" , 0 ) ;
@ -484,7 +555,8 @@ public class yacysearch {
}
// navigation
final String navigation = ( post = = null ) ? sb . getConfig ( "search.navigation" , "all" ) : post . get ( "nav" , "" ) ;
final String navigation =
( post = = null ) ? sb . getConfig ( "search.navigation" , "all" ) : post . get ( "nav" , "" ) ;
// the query
final TreeSet < String > [ ] query = QueryParams . cleanQuery ( querystring . trim ( ) ) ; // converts also umlaute
@ -515,7 +587,10 @@ public class yacysearch {
map . put ( "urlhash" , delHash ) ;
map . put ( "vote" , "negative" ) ;
map . put ( "refid" , "" ) ;
sb . peers . newsPool . publishMyNews ( sb . peers . mySeed ( ) , NewsPool . CATEGORY_SURFTIPP_VOTE_ADD , map ) ;
sb . peers . newsPool . publishMyNews (
sb . peers . mySeed ( ) ,
NewsPool . CATEGORY_SURFTIPP_VOTE_ADD ,
map ) ;
}
// delete the search history since this still shows the entry
@ -536,7 +611,12 @@ public class yacysearch {
if ( urlentry ! = null ) {
Document [ ] documents = null ;
try {
documents = sb . loader . loadDocuments ( sb . loader . request ( urlentry . url ( ) , true , false ) , CacheStrategy . IFEXIST , 5000 , Integer . MAX_VALUE ) ;
documents =
sb . loader . loadDocuments (
sb . loader . request ( urlentry . url ( ) , true , false ) ,
CacheStrategy . IFEXIST ,
5000 ,
Integer . MAX_VALUE ) ;
} catch ( final IOException e ) {
} catch ( final Parser . Failure e ) {
}
@ -548,7 +628,10 @@ public class yacysearch {
map . put ( "description" , documents [ 0 ] . dc_title ( ) . replace ( ',' , ' ' ) ) ;
map . put ( "author" , documents [ 0 ] . dc_creator ( ) ) ;
map . put ( "tags" , documents [ 0 ] . dc_subject ( ' ' ) ) ;
sb . peers . newsPool . publishMyNews ( sb . peers . mySeed ( ) , NewsPool . CATEGORY_SURFTIPP_ADD , map ) ;
sb . peers . newsPool . publishMyNews (
sb . peers . mySeed ( ) ,
NewsPool . CATEGORY_SURFTIPP_ADD ,
map ) ;
documents [ 0 ] . close ( ) ;
}
}
@ -564,7 +647,13 @@ public class yacysearch {
final URIMetadataRow urlentry = indexSegment . urlMetadata ( ) . load ( UTF8 . getBytes ( bookmarkHash ) ) ;
if ( urlentry ! = null ) {
try {
sb . tables . bookmarks . createBookmark ( sb . loader , urlentry . url ( ) , YMarkTables . USER_ADMIN , true , "searchresult" , "/search" ) ;
sb . tables . bookmarks . createBookmark (
sb . loader ,
urlentry . url ( ) ,
YMarkTables . USER_ADMIN ,
true ,
"searchresult" ,
"/search" ) ;
} catch ( final Throwable e ) {
}
}
@ -593,7 +682,8 @@ public class yacysearch {
prefermask = "" ;
}
final QueryParams theQuery = new QueryParams (
final QueryParams theQuery =
new QueryParams (
originalquerystring ,
queryHashes ,
Word . words2hashesHandles ( query [ 1 ] ) ,
@ -610,8 +700,9 @@ public class yacysearch {
maximumRecords ,
startRecord ,
urlmask ,
clustersearch & & global ? QueryParams . Searchdom . CLUSTER :
( global & & indexReceiveGranted ? QueryParams . Searchdom . GLOBAL : QueryParams . Searchdom . LOCAL ) ,
clustersearch & & global ? QueryParams . Searchdom . CLUSTER : ( global & & indexReceiveGranted
? QueryParams . Searchdom . GLOBAL
: QueryParams . Searchdom . LOCAL ) ,
20 ,
constraint ,
true ,
@ -624,9 +715,16 @@ public class yacysearch {
indexSegment ,
ranking ,
header . get ( RequestHeader . USER_AGENT , "" ) ,
sb . getConfigBool ( SwitchboardConstants . SEARCH_VERIFY_DELETE , false ) & & sb . getConfigBool ( SwitchboardConstants . NETWORK_SEARCHVERIFY , false ) & & sb . peers . mySeed ( ) . getFlagAcceptRemoteIndex ( ) ) ;
sb . getConfigBool ( SwitchboardConstants . SEARCH_VERIFY_DELETE , false )
& & sb . getConfigBool ( SwitchboardConstants . NETWORK_SEARCHVERIFY , false )
& & sb . peers . mySeed ( ) . getFlagAcceptRemoteIndex ( ) ) ;
EventTracker . delete ( EventTracker . EClass . SEARCH ) ;
EventTracker . update ( EventTracker . EClass . SEARCH , new ProfilingGraph . EventSearch ( theQuery . id ( true ) , SearchEvent . Type . INITIALIZATION , "" , 0 , 0 ) , false ) ;
EventTracker . update ( EventTracker . EClass . SEARCH , new ProfilingGraph . EventSearch (
theQuery . id ( true ) ,
SearchEvent . Type . INITIALIZATION ,
"" ,
0 ,
0 ) , false ) ;
// tell all threads to do nothing for a specific time
sb . intermissionAllThreads ( 3000 ) ;
@ -635,8 +733,19 @@ public class yacysearch {
theQuery . filterOut ( Switchboard . blueList ) ;
// log
Log . logInfo ( "LOCAL_SEARCH" , "INIT WORD SEARCH: " + theQuery . queryString + ":" + QueryParams . hashSet2hashString ( theQuery . queryHashes ) + " - " + theQuery . neededResults ( ) + " links to be computed, " + theQuery . displayResults ( ) + " lines to be displayed" ) ;
EventChannel . channels ( EventChannel . LOCALSEARCH ) . addMessage ( new RSSMessage ( "Local Search Request" , theQuery . queryString , "" ) ) ;
Log . logInfo (
"LOCAL_SEARCH" ,
"INIT WORD SEARCH: "
+ theQuery . queryString
+ ":"
+ QueryParams . hashSet2hashString ( theQuery . queryHashes )
+ " - "
+ theQuery . neededResults ( )
+ " links to be computed, "
+ theQuery . displayResults ( )
+ " lines to be displayed" ) ;
EventChannel . channels ( EventChannel . LOCALSEARCH ) . addMessage (
new RSSMessage ( "Local Search Request" , theQuery . queryString , "" ) ) ;
final long timestamp = System . currentTimeMillis ( ) ;
// create a new search event
@ -644,10 +753,20 @@ public class yacysearch {
theQuery . setOffset ( 0 ) ; // in case that this is a new search, always start without a offset
startRecord = 0 ;
}
final SearchEvent theSearch = SearchEventCache . getEvent (
theQuery , sb . peers , sb . tables , ( sb . isRobinsonMode ( ) ) ? sb . clusterhashes : null , false , sb . loader ,
( int ) sb . getConfigLong ( SwitchboardConstants . REMOTESEARCH_MAXCOUNT_USER , sb . getConfigLong ( SwitchboardConstants . REMOTESEARCH_MAXCOUNT_DEFAULT , 10 ) ) ,
sb . getConfigLong ( SwitchboardConstants . REMOTESEARCH_MAXTIME_USER , sb . getConfigLong ( SwitchboardConstants . REMOTESEARCH_MAXTIME_DEFAULT , 3000 ) ) ,
final SearchEvent theSearch =
SearchEventCache . getEvent (
theQuery ,
sb . peers ,
sb . tables ,
( sb . isRobinsonMode ( ) ) ? sb . clusterhashes : null ,
false ,
sb . loader ,
( int ) sb . getConfigLong (
SwitchboardConstants . REMOTESEARCH_MAXCOUNT_USER ,
sb . getConfigLong ( SwitchboardConstants . REMOTESEARCH_MAXCOUNT_DEFAULT , 10 ) ) ,
sb . getConfigLong (
SwitchboardConstants . REMOTESEARCH_MAXTIME_USER ,
sb . getConfigLong ( SwitchboardConstants . REMOTESEARCH_MAXTIME_DEFAULT , 3000 ) ) ,
( int ) sb . getConfigLong ( SwitchboardConstants . DHT_BURST_ROBINSON , 0 ) ,
( int ) sb . getConfigLong ( SwitchboardConstants . DHT_BURST_MULTIWORD , 0 ) ) ;
@ -655,7 +774,8 @@ public class yacysearch {
if ( sitehost ! = null & & sb . getConfigBool ( "heuristic.site" , false ) & & authenticated ) {
sb . heuristicSite ( theSearch , sitehost ) ;
}
if ( ( heuristicScroogle > = 0 | | sb . getConfigBool ( "heuristic.scroogle" , false ) ) & & authenticated ) {
if ( ( heuristicScroogle > = 0 | | sb . getConfigBool ( "heuristic.scroogle" , false ) )
& & authenticated ) {
sb . heuristicScroogle ( theSearch ) ;
}
if ( ( heuristicBlekko > = 0 | | sb . getConfigBool ( "heuristic.blekko" , false ) ) & & authenticated ) {
@ -664,15 +784,30 @@ public class yacysearch {
}
// log
Log . logInfo ( "LOCAL_SEARCH" , "EXIT WORD SEARCH: " + theQuery . queryString + " - " +
"local-unfiltered(" + theSearch . getRankingResult ( ) . getLocalIndexCount ( ) + "), " +
"local_miss(" + theSearch . getRankingResult ( ) . getMissCount ( ) + "), " +
"local_sortout(" + theSearch . getRankingResult ( ) . getSortOutCount ( ) + "), " +
"remote(" + theSearch . getRankingResult ( ) . getRemoteResourceSize ( ) + ") links found, " +
( System . currentTimeMillis ( ) - timestamp ) + " ms" ) ;
Log . logInfo ( "LOCAL_SEARCH" , "EXIT WORD SEARCH: "
+ theQuery . queryString
+ " - "
+ "local-unfiltered("
+ theSearch . getRankingResult ( ) . getLocalIndexCount ( )
+ "), "
+ "local_miss("
+ theSearch . getRankingResult ( ) . getMissCount ( )
+ "), "
+ "local_sortout("
+ theSearch . getRankingResult ( ) . getSortOutCount ( )
+ "), "
+ "remote("
+ theSearch . getRankingResult ( ) . getRemoteResourceSize ( )
+ ") links found, "
+ ( System . currentTimeMillis ( ) - timestamp )
+ " ms" ) ;
// prepare search statistics
theQuery . resultcount = theSearch . getRankingResult ( ) . getLocalIndexCount ( ) - theSearch . getRankingResult ( ) . getMissCount ( ) - theSearch . getRankingResult ( ) . getSortOutCount ( ) + theSearch . getRankingResult ( ) . getRemoteIndexCount ( ) ;
theQuery . resultcount =
theSearch . getRankingResult ( ) . getLocalIndexCount ( )
- theSearch . getRankingResult ( ) . getMissCount ( )
- theSearch . getRankingResult ( ) . getSortOutCount ( )
+ theSearch . getRankingResult ( ) . getRemoteIndexCount ( ) ;
theQuery . searchtime = System . currentTimeMillis ( ) - timestamp ;
theQuery . urlretrievaltime = theSearch . result ( ) . getURLRetrievalTime ( ) ;
theQuery . snippetcomputationtime = theSearch . result ( ) . getSnippetComputationTime ( ) ;
@ -683,16 +818,23 @@ public class yacysearch {
prop . put ( "meanCount" , meanMax ) ;
if ( meanMax > 0 & & ! json & & ! rss ) {
final DidYouMean didYouMean = new DidYouMean ( indexSegment . termIndex ( ) , new StringBuilder ( querystring ) ) ;
final DidYouMean didYouMean =
new DidYouMean ( indexSegment . termIndex ( ) , new StringBuilder ( querystring ) ) ;
final Iterator < StringBuilder > meanIt = didYouMean . getSuggestions ( 100 , 5 ) . iterator ( ) ;
int meanCount = 0 ;
String suggestion ;
while ( meanCount < meanMax & & meanIt . hasNext ( ) ) {
suggestion = meanIt . next ( ) . toString ( ) ;
prop . put ( "didYouMean_suggestions_" + meanCount + "_word" , suggestion ) ;
prop . put ( "didYouMean_suggestions_" + meanCount + "_url" ,
QueryParams . navurl ( "html" , 0 , theQuery , suggestion , originalUrlMask . toString ( ) , theQuery . navigators ) . toString ( )
) ;
prop . put (
"didYouMean_suggestions_" + meanCount + "_url" ,
QueryParams . navurl (
"html" ,
0 ,
theQuery ,
suggestion ,
originalUrlMask . toString ( ) ,
theQuery . navigators ) . toString ( ) ) ;
prop . put ( "didYouMean_suggestions_" + meanCount + "_sep" , "|" ) ;
meanCount + + ;
}
@ -714,7 +856,9 @@ public class yacysearch {
prop . put ( "geoinfo_loc_" + i + "_lat" , Math . round ( c . lat ( ) * 10000.0f ) / 10000.0f ) ;
prop . put ( "geoinfo_loc_" + i + "_name" , c . getName ( ) ) ;
i + + ;
if ( i > = 10 ) break ;
if ( i > = 10 ) {
break ;
}
}
prop . put ( "geoinfo_loc" , i ) ;
prop . put ( "geoinfo" , "1" ) ;
@ -725,39 +869,71 @@ public class yacysearch {
synchronized ( trackerHandles ) {
trackerHandles . add ( theQuery . time ) ;
while ( trackerHandles . size ( ) > 600 ) {
if ( ! trackerHandles . remove ( trackerHandles . first ( ) ) ) break ;
if ( ! trackerHandles . remove ( trackerHandles . first ( ) ) ) {
break ;
}
}
}
sb . localSearchTracker . put ( client , trackerHandles ) ;
if ( sb . localSearchTracker . size ( ) > 100 ) {
sb . localSearchTracker . remove ( sb . localSearchTracker . keys ( ) . nextElement ( ) ) ;
}
if ( MemoryControl . shortStatus ( ) ) sb . localSearchTracker . clear ( ) ;
if ( MemoryControl . shortStatus ( ) ) {
sb . localSearchTracker . clear ( ) ;
}
} catch ( final Exception e ) {
Log . logException ( e ) ;
}
final int indexcount = theSearch . getRankingResult ( ) . getLocalIndexCount ( ) - theSearch . getRankingResult ( ) . getMissCount ( ) - theSearch . getRankingResult ( ) . getSortOutCount ( ) + theSearch . getRankingResult ( ) . getRemoteIndexCount ( ) ;
final int indexcount =
theSearch . getRankingResult ( ) . getLocalIndexCount ( )
- theSearch . getRankingResult ( ) . getMissCount ( )
- theSearch . getRankingResult ( ) . getSortOutCount ( )
+ theSearch . getRankingResult ( ) . getRemoteIndexCount ( ) ;
prop . put ( "num-results_offset" , startRecord = = 0 ? 0 : startRecord + 1 ) ;
prop . put ( "num-results_itemscount" , Formatter . number ( startRecord + theSearch . getQuery ( ) . itemsPerPage > indexcount ? startRecord + indexcount % theSearch . getQuery ( ) . itemsPerPage : startRecord + theSearch . getQuery ( ) . itemsPerPage , true ) ) ;
prop . put ( "num-results_itemscount" , Formatter . number (
startRecord + theSearch . getQuery ( ) . itemsPerPage > indexcount ? startRecord
+ indexcount
% theSearch . getQuery ( ) . itemsPerPage : startRecord + theSearch . getQuery ( ) . itemsPerPage ,
true ) ) ;
prop . put ( "num-results_itemsPerPage" , maximumRecords ) ;
prop . put ( "num-results_totalcount" , Formatter . number ( indexcount , true ) ) ;
prop . put ( "num-results_globalresults" , global & & ( indexReceiveGranted | | clustersearch ) ? "1" : "0" ) ;
prop . put ( "num-results_globalresults_localResourceSize" , Formatter . number ( theSearch . getRankingResult ( ) . getLocalIndexCount ( ) , true ) ) ;
prop . put ( "num-results_globalresults_localMissCount" , Formatter . number ( theSearch . getRankingResult ( ) . getMissCount ( ) , true ) ) ;
prop . put ( "num-results_globalresults_remoteResourceSize" , Formatter . number ( theSearch . getRankingResult ( ) . getRemoteResourceSize ( ) , true ) ) ;
prop . put ( "num-results_globalresults_remoteIndexCount" , Formatter . number ( theSearch . getRankingResult ( ) . getRemoteIndexCount ( ) , true ) ) ;
prop . put ( "num-results_globalresults_remotePeerCount" , Formatter . number ( theSearch . getRankingResult ( ) . getRemotePeerCount ( ) , true ) ) ;
prop . put ( "num-results_globalresults" , global & & ( indexReceiveGranted | | clustersearch )
? "1"
: "0" ) ;
prop . put (
"num-results_globalresults_localResourceSize" ,
Formatter . number ( theSearch . getRankingResult ( ) . getLocalIndexCount ( ) , true ) ) ;
prop . put (
"num-results_globalresults_localMissCount" ,
Formatter . number ( theSearch . getRankingResult ( ) . getMissCount ( ) , true ) ) ;
prop . put (
"num-results_globalresults_remoteResourceSize" ,
Formatter . number ( theSearch . getRankingResult ( ) . getRemoteResourceSize ( ) , true ) ) ;
prop . put (
"num-results_globalresults_remoteIndexCount" ,
Formatter . number ( theSearch . getRankingResult ( ) . getRemoteIndexCount ( ) , true ) ) ;
prop . put (
"num-results_globalresults_remotePeerCount" ,
Formatter . number ( theSearch . getRankingResult ( ) . getRemotePeerCount ( ) , true ) ) ;
// compose page navigation
final StringBuilder resnav = new StringBuilder ( 200 ) ;
final int thispage = startRecord / theQuery . displayResults ( ) ;
if ( thispage = = 0 ) {
resnav . append ( "<img src=\"env/grafics/navdl.gif\" alt=\"arrowleft\" width=\"16\" height=\"16\" /> " ) ;
resnav
. append ( "<img src=\"env/grafics/navdl.gif\" alt=\"arrowleft\" width=\"16\" height=\"16\" /> " ) ;
} else {
resnav . append ( "<a id=\"prevpage\" href=\"" ) ;
resnav . append ( QueryParams . navurl ( "html" , thispage - 1 , theQuery , null , originalUrlMask , navigation ) . toString ( ) ) ;
resnav . append ( "\"><img src=\"env/grafics/navdl.gif\" alt=\"arrowleft\" width=\"16\" height=\"16\" /></a> " ) ;
resnav . append ( QueryParams . navurl (
"html" ,
thispage - 1 ,
theQuery ,
null ,
originalUrlMask ,
navigation ) . toString ( ) ) ;
resnav
. append ( "\"><img src=\"env/grafics/navdl.gif\" alt=\"arrowleft\" width=\"16\" height=\"16\" /></a> " ) ;
}
final int numberofpages = Math . min ( 10 , 1 + ( ( indexcount - 1 ) / theQuery . displayResults ( ) ) ) ;
@ -770,7 +946,9 @@ public class yacysearch {
resnav . append ( "\" width=\"16\" height=\"16\" /> " ) ;
} else {
resnav . append ( "<a href=\"" ) ;
resnav . append ( QueryParams . navurl ( "html" , i , theQuery , null , originalUrlMask , navigation ) . toString ( ) ) ;
resnav . append ( QueryParams
. navurl ( "html" , i , theQuery , null , originalUrlMask , navigation )
. toString ( ) ) ;
resnav . append ( "\"><img src=\"env/grafics/navd" ) ;
resnav . append ( i + 1 ) ;
resnav . append ( ".gif\" alt=\"page" ) ;
@ -779,11 +957,19 @@ public class yacysearch {
}
}
if ( thispage > = numberofpages ) {
resnav . append ( "<img src=\"env/grafics/navdr.gif\" alt=\"arrowright\" width=\"16\" height=\"16\" />" ) ;
resnav
. append ( "<img src=\"env/grafics/navdr.gif\" alt=\"arrowright\" width=\"16\" height=\"16\" />" ) ;
} else {
resnav . append ( "<a id=\"nextpage\" href=\"" ) ;
resnav . append ( QueryParams . navurl ( "html" , thispage + 1 , theQuery , null , originalUrlMask , navigation ) . toString ( ) ) ;
resnav . append ( "\"><img src=\"env/grafics/navdr.gif\" alt=\"arrowright\" width=\"16\" height=\"16\" /></a>" ) ;
resnav . append ( QueryParams . navurl (
"html" ,
thispage + 1 ,
theQuery ,
null ,
originalUrlMask ,
navigation ) . toString ( ) ) ;
resnav
. append ( "\"><img src=\"env/grafics/navdr.gif\" alt=\"arrowright\" width=\"16\" height=\"16\" /></a>" ) ;
}
final String resnavs = resnav . toString ( ) ;
prop . put ( "num-results_resnav" , resnavs ) ;
@ -796,7 +982,12 @@ public class yacysearch {
prop . put ( "results_" + i + "_eventID" , theQuery . id ( false ) ) ;
}
prop . put ( "results" , theQuery . displayResults ( ) ) ;
prop . put ( "resultTable" , ( contentdom = = ContentDomain . APP | | contentdom = = ContentDomain . AUDIO | | contentdom = = ContentDomain . VIDEO ) ? 1 : 0 ) ;
prop
. put (
"resultTable" ,
( contentdom = = ContentDomain . APP | | contentdom = = ContentDomain . AUDIO | | contentdom = = ContentDomain . VIDEO )
? 1
: 0 ) ;
prop . put ( "eventID" , theQuery . id ( false ) ) ; // for bottomline
// process result of search
@ -838,10 +1029,20 @@ public class yacysearch {
prop . putHTML ( "prefermaskfilter" , prefermask ) ;
prop . put ( "indexof" , ( indexof ) ? "on" : "off" ) ;
prop . put ( "constraint" , ( constraint = = null ) ? "" : constraint . exportB64 ( ) ) ;
prop . put ( "search.verify" , snippetFetchStrategy = = null ? sb . getConfig ( "search.verify" , "iffresh" ) : snippetFetchStrategy . toName ( ) ) ;
prop . put ( "search.navigation" , ( post = = null ) ? sb . getConfig ( "search.navigation" , "all" ) : post . get ( "nav" , "all" ) ) ;
prop . put ( "search.verify" , snippetFetchStrategy = = null
? sb . getConfig ( "search.verify" , "iffresh" )
: snippetFetchStrategy . toName ( ) ) ;
prop . put (
"search.navigation" ,
( post = = null ) ? sb . getConfig ( "search.navigation" , "all" ) : post . get ( "nav" , "all" ) ) ;
prop . put ( "contentdom" , ( post = = null ? "text" : post . get ( "contentdom" , "text" ) ) ) ;
prop . put ( "searchdomswitches" , sb . getConfigBool ( "search.text" , true ) | | sb . getConfigBool ( "search.audio" , true ) | | sb . getConfigBool ( "search.video" , true ) | | sb . getConfigBool ( "search.image" , true ) | | sb . getConfigBool ( "search.app" , true ) ? 1 : 0 ) ;
prop . put (
"searchdomswitches" ,
sb . getConfigBool ( "search.text" , true )
| | sb . getConfigBool ( "search.audio" , true )
| | sb . getConfigBool ( "search.video" , true )
| | sb . getConfigBool ( "search.image" , true )
| | sb . getConfigBool ( "search.app" , true ) ? 1 : 0 ) ;
prop . put ( "searchdomswitches_searchtext" , sb . getConfigBool ( "search.text" , true ) ? 1 : 0 ) ;
prop . put ( "searchdomswitches_searchaudio" , sb . getConfigBool ( "search.audio" , true ) ? 1 : 0 ) ;
prop . put ( "searchdomswitches_searchvideo" , sb . getConfigBool ( "search.video" , true ) ? 1 : 0 ) ;