SourceForge: gazzera/gazzera: changeset 72:d6680cbcf304
use visibility on search panel
authorMsx <msx80@users.sourceforge.net>
Thu Oct 15 19:12:00 2009 +0200 (5 weeks ago)
changeset 72d6680cbcf304
parent 718de2ff19246d
child 7310fe8d9bf6f6
use visibility on search panel
src/gazzera.lpi
src/node/plugins/searchpluginunit.pas
     1.1 --- a/src/gazzera.lpi	Tue Oct 13 15:53:54 2009 +0200
     1.2 +++ b/src/gazzera.lpi	Thu Oct 15 19:12:00 2009 +0200
     1.3 @@ -12,7 +12,7 @@
     1.4        </Flags>
     1.5        <MainUnit Value="0"/>
     1.6        <TargetFileExt Value=""/>
     1.7 -      <ActiveEditorIndexAtStart Value="8"/>
     1.8 +      <ActiveEditorIndexAtStart Value="1"/>
     1.9      </General>
    1.10      <PublishOptions>
    1.11        <Version Value="2"/>
    1.12 @@ -112,14 +112,12 @@
    1.13          <UnitName Value="mainwindowunit"/>
    1.14          <CursorPos X="35" Y="623"/>
    1.15          <TopLine Value="601"/>
    1.16 -        <EditorIndex Value="13"/>
    1.17          <UsageCount Value="62"/>
    1.18          <Bookmarks Count="3">
    1.19            <Item0 X="29" Y="86" ID="1"/>
    1.20            <Item1 X="10" Y="407" ID="2"/>
    1.21            <Item2 X="1" Y="270" ID="6"/>
    1.22          </Bookmarks>
    1.23 -        <Loaded Value="True"/>
    1.24          <SyntaxHighlighter Value="Delphi"/>
    1.25        </Unit10>
    1.26        <Unit11>
    1.27 @@ -185,9 +183,9 @@
    1.28        <Unit19>
    1.29          <Filename Value="node\nodedatabaseunit.pas"/>
    1.30          <UnitName Value="nodedatabaseunit"/>
    1.31 -        <CursorPos X="1" Y="115"/>
    1.32 +        <CursorPos X="31" Y="103"/>
    1.33          <TopLine Value="92"/>
    1.34 -        <EditorIndex Value="15"/>
    1.35 +        <EditorIndex Value="3"/>
    1.36          <UsageCount Value="63"/>
    1.37          <Loaded Value="True"/>
    1.38          <SyntaxHighlighter Value="Delphi"/>
    1.39 @@ -197,9 +195,7 @@
    1.40          <UnitName Value="peerunit"/>
    1.41          <CursorPos X="63" Y="49"/>
    1.42          <TopLine Value="25"/>
    1.43 -        <EditorIndex Value="2"/>
    1.44          <UsageCount Value="29"/>
    1.45 -        <Loaded Value="True"/>
    1.46          <SyntaxHighlighter Value="Delphi"/>
    1.47        </Unit20>
    1.48        <Unit21>
    1.49 @@ -391,9 +387,7 @@
    1.50          <UnitName Value="actionsunit"/>
    1.51          <CursorPos X="67" Y="62"/>
    1.52          <TopLine Value="60"/>
    1.53 -        <EditorIndex Value="14"/>
    1.54          <UsageCount Value="32"/>
    1.55 -        <Loaded Value="True"/>
    1.56          <SyntaxHighlighter Value="Delphi"/>
    1.57        </Unit46>
    1.58        <Unit47>
    1.59 @@ -488,9 +482,9 @@
    1.60        <Unit59>
    1.61          <Filename Value="node\plugins\browsepluginunit.pas"/>
    1.62          <UnitName Value="browsepluginunit"/>
    1.63 -        <CursorPos X="1" Y="138"/>
    1.64 -        <TopLine Value="117"/>
    1.65 -        <EditorIndex Value="12"/>
    1.66 +        <CursorPos X="112" Y="123"/>
    1.67 +        <TopLine Value="111"/>
    1.68 +        <EditorIndex Value="2"/>
    1.69          <UsageCount Value="32"/>
    1.70          <Loaded Value="True"/>
    1.71          <SyntaxHighlighter Value="Delphi"/>
    1.72 @@ -498,11 +492,9 @@
    1.73        <Unit60>
    1.74          <Filename Value="ultimatesockets\normalsocketunit.pas"/>
    1.75          <UnitName Value="normalsocketunit"/>
    1.76 -        <CursorPos X="47" Y="57"/>
    1.77 +        <CursorPos X="29" Y="39"/>
    1.78          <TopLine Value="35"/>
    1.79 -        <EditorIndex Value="8"/>
    1.80          <UsageCount Value="67"/>
    1.81 -        <Loaded Value="True"/>
    1.82          <SyntaxHighlighter Value="Delphi"/>
    1.83        </Unit60>
    1.84        <Unit61>
    1.85 @@ -572,9 +564,7 @@
    1.86          <UnitName Value="mainunit"/>
    1.87          <CursorPos X="22" Y="87"/>
    1.88          <TopLine Value="76"/>
    1.89 -        <EditorIndex Value="1"/>
    1.90          <UsageCount Value="53"/>
    1.91 -        <Loaded Value="True"/>
    1.92          <SyntaxHighlighter Value="Delphi"/>
    1.93        </Unit69>
    1.94        <Unit70>
    1.95 @@ -594,9 +584,7 @@
    1.96          <UnitName Value="messagesunit"/>
    1.97          <CursorPos X="46" Y="937"/>
    1.98          <TopLine Value="911"/>
    1.99 -        <EditorIndex Value="11"/>
   1.100          <UsageCount Value="71"/>
   1.101 -        <Loaded Value="True"/>
   1.102          <SyntaxHighlighter Value="Delphi"/>
   1.103        </Unit72>
   1.104        <Unit73>
   1.105 @@ -630,9 +618,7 @@
   1.106          <UnitName Value="socketunit"/>
   1.107          <CursorPos X="61" Y="373"/>
   1.108          <TopLine Value="349"/>
   1.109 -        <EditorIndex Value="10"/>
   1.110          <UsageCount Value="44"/>
   1.111 -        <Loaded Value="True"/>
   1.112          <SyntaxHighlighter Value="Delphi"/>
   1.113        </Unit77>
   1.114        <Unit78>
   1.115 @@ -671,9 +657,7 @@
   1.116          <UnitName Value="grouppluginunit"/>
   1.117          <CursorPos X="1" Y="80"/>
   1.118          <TopLine Value="59"/>
   1.119 -        <EditorIndex Value="6"/>
   1.120          <UsageCount Value="13"/>
   1.121 -        <Loaded Value="True"/>
   1.122          <SyntaxHighlighter Value="Delphi"/>
   1.123        </Unit82>
   1.124        <Unit83>
   1.125 @@ -689,9 +673,7 @@
   1.126          <UnitName Value="friendpluginunit"/>
   1.127          <CursorPos X="1" Y="232"/>
   1.128          <TopLine Value="217"/>
   1.129 -        <EditorIndex Value="3"/>
   1.130          <UsageCount Value="40"/>
   1.131 -        <Loaded Value="True"/>
   1.132          <SyntaxHighlighter Value="Delphi"/>
   1.133        </Unit84>
   1.134        <Unit85>
   1.135 @@ -739,9 +721,7 @@
   1.136          <UnitName Value="pluginmanagerunit"/>
   1.137          <CursorPos X="90" Y="113"/>
   1.138          <TopLine Value="104"/>
   1.139 -        <EditorIndex Value="9"/>
   1.140          <UsageCount Value="52"/>
   1.141 -        <Loaded Value="True"/>
   1.142          <SyntaxHighlighter Value="Delphi"/>
   1.143        </Unit90>
   1.144        <Unit91>
   1.145 @@ -804,9 +784,7 @@
   1.146          <UnitName Value="sharemanagerunit"/>
   1.147          <CursorPos X="1" Y="194"/>
   1.148          <TopLine Value="173"/>
   1.149 -        <EditorIndex Value="4"/>
   1.150          <UsageCount Value="46"/>
   1.151 -        <Loaded Value="True"/>
   1.152          <SyntaxHighlighter Value="Delphi"/>
   1.153        </Unit98>
   1.154        <Unit99>
   1.155 @@ -932,9 +910,11 @@
   1.156        <Unit117>
   1.157          <Filename Value="node\plugins\searchpluginunit.pas"/>
   1.158          <UnitName Value="searchpluginunit"/>
   1.159 -        <CursorPos X="1" Y="80"/>
   1.160 -        <TopLine Value="66"/>
   1.161 +        <CursorPos X="1" Y="154"/>
   1.162 +        <TopLine Value="132"/>
   1.163 +        <EditorIndex Value="1"/>
   1.164          <UsageCount Value="22"/>
   1.165 +        <Loaded Value="True"/>
   1.166          <SyntaxHighlighter Value="Delphi"/>
   1.167        </Unit117>
   1.168        <Unit118>
   1.169 @@ -983,9 +963,7 @@
   1.170          <UnitName Value="downloadpluginunit"/>
   1.171          <CursorPos X="106" Y="171"/>
   1.172          <TopLine Value="156"/>
   1.173 -        <EditorIndex Value="16"/>
   1.174          <UsageCount Value="38"/>
   1.175 -        <Loaded Value="True"/>
   1.176          <SyntaxHighlighter Value="Delphi"/>
   1.177        </Unit124>
   1.178        <Unit125>
   1.179 @@ -1222,9 +1200,7 @@
   1.180          <UnitName Value="modelunit"/>
   1.181          <CursorPos X="22" Y="30"/>
   1.182          <TopLine Value="1"/>
   1.183 -        <EditorIndex Value="7"/>
   1.184          <UsageCount Value="17"/>
   1.185 -        <Loaded Value="True"/>
   1.186          <SyntaxHighlighter Value="Delphi"/>
   1.187        </Unit158>
   1.188        <Unit159>
   1.189 @@ -1892,133 +1868,15 @@
   1.190          <UnitName Value="sharedpanelunit"/>
   1.191          <CursorPos X="11" Y="9"/>
   1.192          <TopLine Value="1"/>
   1.193 -        <EditorIndex Value="5"/>
   1.194          <UsageCount Value="10"/>
   1.195 -        <Loaded Value="True"/>
   1.196          <SyntaxHighlighter Value="Delphi"/>
   1.197        </Unit250>
   1.198      </Units>
   1.199 -    <JumpHistory Count="30" HistoryIndex="29">
   1.200 +    <JumpHistory Count="1" HistoryIndex="0">
   1.201        <Position1>
   1.202 -        <Filename Value="ultimatesockets\normalsocketunit.pas"/>
   1.203 -        <Caret Line="62" Column="58" TopLine="35"/>
   1.204 -      </Position1>
   1.205 -      <Position2>
   1.206 -        <Filename Value="ultimatesockets\normalsocketunit.pas"/>
   1.207 -        <Caret Line="60" Column="58" TopLine="35"/>
   1.208 -      </Position2>
   1.209 -      <Position3>
   1.210 -        <Filename Value="gui\mainwindowunit.pas"/>
   1.211 -        <Caret Line="416" Column="9" TopLine="409"/>
   1.212 -      </Position3>
   1.213 -      <Position4>
   1.214 -        <Filename Value="gui\mainwindowunit.pas"/>
   1.215 -        <Caret Line="632" Column="16" TopLine="604"/>
   1.216 -      </Position4>
   1.217 -      <Position5>
   1.218 -        <Filename Value="gui\actionsunit.pas"/>
   1.219 -        <Caret Line="20" Column="45" TopLine="16"/>
   1.220 -      </Position5>
   1.221 -      <Position6>
   1.222 -        <Filename Value="gui\mainwindowunit.pas"/>
   1.223 -        <Caret Line="632" Column="16" TopLine="604"/>
   1.224 -      </Position6>
   1.225 -      <Position7>
   1.226 -        <Filename Value="gui\mainwindowunit.pas"/>
   1.227 -        <Caret Line="623" Column="35" TopLine="601"/>
   1.228 -      </Position7>
   1.229 -      <Position8>
   1.230 -        <Filename Value="gui\actionsunit.pas"/>
   1.231 -        <Caret Line="64" Column="1" TopLine="22"/>
   1.232 -      </Position8>
   1.233 -      <Position9>
   1.234 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.235 -        <Caret Line="31" Column="5" TopLine="20"/>
   1.236 -      </Position9>
   1.237 -      <Position10>
   1.238          <Filename Value="gazzera.pas"/>
   1.239          <Caret Line="93" Column="12" TopLine="58"/>
   1.240 -      </Position10>
   1.241 -      <Position11>
   1.242 -        <Filename Value="node\mainunit.pas"/>
   1.243 -        <Caret Line="87" Column="22" TopLine="76"/>
   1.244 -      </Position11>
   1.245 -      <Position12>
   1.246 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.247 -        <Caret Line="8" Column="10" TopLine="1"/>
   1.248 -      </Position12>
   1.249 -      <Position13>
   1.250 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.251 -        <Caret Line="110" Column="14" TopLine="88"/>
   1.252 -      </Position13>
   1.253 -      <Position14>
   1.254 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.255 -        <Caret Line="105" Column="1" TopLine="84"/>
   1.256 -      </Position14>
   1.257 -      <Position15>
   1.258 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.259 -        <Caret Line="108" Column="1" TopLine="87"/>
   1.260 -      </Position15>
   1.261 -      <Position16>
   1.262 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.263 -        <Caret Line="109" Column="1" TopLine="88"/>
   1.264 -      </Position16>
   1.265 -      <Position17>
   1.266 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.267 -        <Caret Line="110" Column="1" TopLine="89"/>
   1.268 -      </Position17>
   1.269 -      <Position18>
   1.270 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.271 -        <Caret Line="108" Column="1" TopLine="87"/>
   1.272 -      </Position18>
   1.273 -      <Position19>
   1.274 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.275 -        <Caret Line="109" Column="1" TopLine="88"/>
   1.276 -      </Position19>
   1.277 -      <Position20>
   1.278 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.279 -        <Caret Line="110" Column="1" TopLine="89"/>
   1.280 -      </Position20>
   1.281 -      <Position21>
   1.282 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.283 -        <Caret Line="108" Column="1" TopLine="87"/>
   1.284 -      </Position21>
   1.285 -      <Position22>
   1.286 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.287 -        <Caret Line="109" Column="1" TopLine="88"/>
   1.288 -      </Position22>
   1.289 -      <Position23>
   1.290 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.291 -        <Caret Line="112" Column="1" TopLine="91"/>
   1.292 -      </Position23>
   1.293 -      <Position24>
   1.294 -        <Filename Value="node\nodedatabaseunit.pas"/>
   1.295 -        <Caret Line="115" Column="1" TopLine="92"/>
   1.296 -      </Position24>
   1.297 -      <Position25>
   1.298 -        <Filename Value="node\plugins\grouppluginunit.pas"/>
   1.299 -        <Caret Line="100" Column="1" TopLine="79"/>
   1.300 -      </Position25>
   1.301 -      <Position26>
   1.302 -        <Filename Value="ultimatesockets\normalsocketunit.pas"/>
   1.303 -        <Caret Line="59" Column="59" TopLine="35"/>
   1.304 -      </Position26>
   1.305 -      <Position27>
   1.306 -        <Filename Value="node\plugins\grouppluginunit.pas"/>
   1.307 -        <Caret Line="64" Column="1" TopLine="43"/>
   1.308 -      </Position27>
   1.309 -      <Position28>
   1.310 -        <Filename Value="ultimatesockets\normalsocketunit.pas"/>
   1.311 -        <Caret Line="56" Column="1" TopLine="35"/>
   1.312 -      </Position28>
   1.313 -      <Position29>
   1.314 -        <Filename Value="node\plugins\grouppluginunit.pas"/>
   1.315 -        <Caret Line="80" Column="1" TopLine="59"/>
   1.316 -      </Position29>
   1.317 -      <Position30>
   1.318 -        <Filename Value="ultimatesockets\normalsocketunit.pas"/>
   1.319 -        <Caret Line="54" Column="13" TopLine="35"/>
   1.320 -      </Position30>
   1.321 +      </Position1>
   1.322      </JumpHistory>
   1.323    </ProjectOptions>
   1.324    <CompilerOptions>
     2.1 --- a/src/node/plugins/searchpluginunit.pas	Tue Oct 13 15:53:54 2009 +0200
     2.2 +++ b/src/node/plugins/searchpluginunit.pas	Thu Oct 15 19:12:00 2009 +0200
     2.3 @@ -1,170 +1,184 @@
     2.4 -unit searchpluginunit;
     2.5 -{$H+}
     2.6 -
     2.7 -interface
     2.8 -uses Classes, SysUtils, pluginunit, peerunit, messagesunit, logunit,
     2.9 -  interfacemessageunit, Types, controllercommandsunit, propertiesunit, dateutils,
    2.10 -  dictionaryunit, databaseunit, nodedatabaseunit, msxstrings;
    2.11 -
    2.12 -type
    2.13 -
    2.14 -TActiveSearch = class
    2.15 -  searchId: integer;
    2.16 -  gid: string;
    2.17 -  started: TDateTime;
    2.18 -end;
    2.19 -
    2.20 -TSearchPlugin = class(TPlugin)
    2.21 -  private
    2.22 -    activeSearches: TDictionary;
    2.23 -    procedure readFileSearch(m:TMsgFileSearch);
    2.24 -    procedure readFileSearchReply(m:TMsgFileSearchReply);
    2.25 -    procedure everyFiveSeconds;
    2.26 -    procedure commandStartFileSearch(m:TMsgCommandStartFileSearch);
    2.27 -  protected
    2.28 -    function getName: string; override;
    2.29 -  public
    2.30 -    procedure Initialize; override;
    2.31 -    procedure Finalize; override;
    2.32 -    procedure OnMessage(m:TMessage); override;
    2.33 -end;
    2.34 -
    2.35 -
    2.36 -implementation
    2.37 -uses objectsunit;
    2.38 -
    2.39 -function TSearchPlugin.getName: string;
    2.40 -begin
    2.41 -  result := 'Search Plugin';
    2.42 -end;
    2.43 -
    2.44 -procedure TSearchPlugin.Initialize;
    2.45 -begin
    2.46 -  log(llInfo, 'Initialize');
    2.47 -  registerMessageType(mtFileSearch);
    2.48 -  registerMessageType(mtFileSearchReply);
    2.49 -  registerMessageType(mtCommandStartFileSearch);
    2.50 -  registerMessageType(mtMetaFiveSeconds);
    2.51 -  activeSearches := TDictionary.create;
    2.52 -end;
    2.53 -
    2.54 -procedure TSearchPlugin.Finalize;
    2.55 -begin
    2.56 -  log(llInfo, 'Finalize');
    2.57 -  activeSearches.free;
    2.58 -end;
    2.59 -
    2.60 -procedure TSearchPlugin.OnMessage(m:TMessage);
    2.61 -begin
    2.62 -  case m.msgType of
    2.63 -    mtFileSearch: readFileSearch(TMsgFileSearch(m));
    2.64 -    mtFileSearchReply: readFileSearchReply(TMsgFileSearchReply(m));
    2.65 -    mtCommandStartFileSearch: commandStartFileSearch(TMsgCommandStartFileSearch(m));
    2.66 -    mtMetaFiveSeconds: everyFiveSeconds;
    2.67 -  end;
    2.68 -end;
    2.69 -
    2.70 -procedure TSearchPlugin.everyFiveSeconds;
    2.71 -var
    2.72 -  i: integer;
    2.73 -  a: TActiveSearch;
    2.74 -begin
    2.75 -  for i := activeSearches.count-1 downto 0 do
    2.76 -  begin
    2.77 -    a := activeSearches[activeSearches.byIndex(i)] as TActiveSearch;
    2.78 -    if (a.started + (OneMinute*2)) < now() then
    2.79 -    begin
    2.80 -      log(llInfo, 'Removing a search that timed out ' + activeSearches.byIndex(i));
    2.81 -      activeSearches.remove(activeSearches.byIndex(i));
    2.82 -    end;
    2.83 -  end;
    2.84 -end;
    2.85 -
    2.86 -procedure TSearchPlugin.commandStartFileSearch(m:TMsgCommandStartFileSearch);
    2.87 -var
    2.88 -  n, i: integer;
    2.89 -  peers: TStringList;
    2.90 -  q: TMsgFileSearch;
    2.91 -  s: TActiveSearch;
    2.92 -begin
    2.93 -  repeat
    2.94 -    n := Random(maxLongint);
    2.95 -  until activeSearches[inttostr(n)] = nil;
    2.96 -  s := TActiveSearch.Create;
    2.97 -  s.searchId := n;
    2.98 -  s.started := now();
    2.99 -  activeSearches[inttostr(n)] := s;  // TODO this is never released!!
   2.100 -  for i:=0 to PluginManager.PeerList.count-1 do
   2.101 -    PluginManager.PeerList.get(i).enqueue(TMsgFileSearch.create(n, m.keywords, m.min, m.max));
   2.102 -  Notifier.postToController(TMsgCommandNewFileSearch.Create(n, m.keywords));
   2.103 -end;
   2.104 -
   2.105 -procedure TSearchPlugin.readFileSearch(m:TMsgFileSearch);
   2.106 -var
   2.107 -  rs: TResultSet;
   2.108 -  i: integer;
   2.109 -  kw: TStringDynArray;
   2.110 -  q: string;
   2.111 -begin
   2.112 -  log(llDebug, 'Received FileSearch');
   2.113 -  q := ' where ok = 1 ';
   2.114 -  kw := SeparateString(m.keywords, ' ');
   2.115 -  for i:=0 to length(kw)-1 do
   2.116 -  begin
   2.117 -    kw[i] := '%'+kw[i]+'%';
   2.118 -    q := q + 'and (filename like ?)';
   2.119 -  end;
   2.120 -
   2.121 -  if m.minSize > 0 then
   2.122 -  begin
   2.123 -    setlength(kw, length(kw) + 1);
   2.124 -    kw[length(kw)-1] := inttostr((int64(m.minsize) * int64(1024*1024)));
   2.125 -    q := q + ' and (size >= ?)';
   2.126 -  end;
   2.127 -  if m.maxSize > 0 then
   2.128 -  begin
   2.129 -    setlength(kw, length(kw)+1);
   2.130 -    kw[length(kw)-1] := inttostr((int64(m.maxsize) * int64(1024*1024)));
   2.131 -    q := q + ' and (size <= ?)';
   2.132 -  end;
   2.133 -
   2.134 -  (* use this one instead:
   2.135 -
   2.136 -  select filename, hash, size from (
   2.137 -  select 1 x,* from files where filename like '%m%'  and size < 1000 and size > 400
   2.138 -  union
   2.139 -  select 2 x,* from files where virtualpath like '%m%'  and size < 1000 and size > 400
   2.140 -  )  order by x asc limit 100
   2.141 -  *)
   2.142 -
   2.143 -  q := 'select filename, hash, size from files ' + q + ' limit 100';
   2.144 -  log(llInfo, 'Search query: ' + q);
   2.145 -  rs := Database.executeQuery(q, kw);
   2.146 -  try
   2.147 -    while rs.next do
   2.148 -    begin
   2.149 -      log(llDebug, 'Sending a result');
   2.150 -      m.peer.enqueue(TMsgFileSearchReply.Create(m.searchid, rs[0], rs[1], strtoint64(rs[2])));
   2.151 -    end;
   2.152 -    log(llDebug, 'finished sending results');
   2.153 -  finally
   2.154 -    log(llDebug, 'closing resultset');
   2.155 -    rs.Free;
   2.156 -  end;
   2.157 -end;
   2.158 -
   2.159 -procedure TSearchPlugin.readFileSearchReply(m:TMsgFileSearchReply);
   2.160 -var s: TActiveSearch;
   2.161 -begin
   2.162 -  log(llDebug, 'Received FileSearchReply');
   2.163 -  log(llDebug, m.name + ' ' + inttostr(m.size) + ' ' +m.hash);
   2.164 -  s := activeSearches[inttostr(m.searchId)] as TActiveSearch;
   2.165 -  if s = nil then
   2.166 -    log(llWarning, 'Received reply summary without search.. timeout?')
   2.167 -  else
   2.168 -    notifier.postToController(TMsgCommandFileSearchReply.Create(m.searchId,
   2.169 -        m.peer.gid, m.name, m.hash, m.size));
   2.170 -end;
   2.171 -
   2.172 -
   2.173 -end.
   2.174 +unit searchpluginunit;
   2.175 +{$H+}
   2.176 +
   2.177 +interface
   2.178 +uses Classes, SysUtils, pluginunit, peerunit, messagesunit, logunit,
   2.179 +  interfacemessageunit, Types, controllercommandsunit, propertiesunit, dateutils,
   2.180 +  dictionaryunit, databaseunit, nodedatabaseunit, msxstrings;
   2.181 +
   2.182 +type
   2.183 +
   2.184 +TActiveSearch = class
   2.185 +  searchId: integer;
   2.186 +  gid: string;
   2.187 +  started: TDateTime;
   2.188 +end;
   2.189 +
   2.190 +TSearchPlugin = class(TPlugin)
   2.191 +  private
   2.192 +    activeSearches: TDictionary;
   2.193 +    procedure readFileSearch(m:TMsgFileSearch);
   2.194 +    procedure readFileSearchReply(m:TMsgFileSearchReply);
   2.195 +    procedure everyFiveSeconds;
   2.196 +    procedure commandStartFileSearch(m:TMsgCommandStartFileSearch);
   2.197 +  protected
   2.198 +    function getName: string; override;
   2.199 +  public
   2.200 +    procedure Initialize; override;
   2.201 +    procedure Finalize; override;
   2.202 +    procedure OnMessage(m:TMessage); override;
   2.203 +end;
   2.204 +
   2.205 +
   2.206 +implementation
   2.207 +uses objectsunit;
   2.208 +
   2.209 +function TSearchPlugin.getName: string;
   2.210 +begin
   2.211 +  result := 'Search Plugin';
   2.212 +end;
   2.213 +
   2.214 +procedure TSearchPlugin.Initialize;
   2.215 +begin
   2.216 +  log(llInfo, 'Initialize');
   2.217 +  registerMessageType(mtFileSearch);
   2.218 +  registerMessageType(mtFileSearchReply);
   2.219 +  registerMessageType(mtCommandStartFileSearch);
   2.220 +  registerMessageType(mtMetaFiveSeconds);
   2.221 +  activeSearches := TDictionary.create;
   2.222 +end;
   2.223 +
   2.224 +procedure TSearchPlugin.Finalize;
   2.225 +begin
   2.226 +  log(llInfo, 'Finalize');
   2.227 +  activeSearches.free;
   2.228 +end;
   2.229 +
   2.230 +procedure TSearchPlugin.OnMessage(m:TMessage);
   2.231 +begin
   2.232 +  case m.msgType of
   2.233 +    mtFileSearch: readFileSearch(TMsgFileSearch(m));
   2.234 +    mtFileSearchReply: readFileSearchReply(TMsgFileSearchReply(m));
   2.235 +    mtCommandStartFileSearch: commandStartFileSearch(TMsgCommandStartFileSearch(m));
   2.236 +    mtMetaFiveSeconds: everyFiveSeconds;
   2.237 +  end;
   2.238 +end;
   2.239 +
   2.240 +procedure TSearchPlugin.everyFiveSeconds;
   2.241 +var
   2.242 +  i: integer;
   2.243 +  a: TActiveSearch;
   2.244 +begin
   2.245 +  for i := activeSearches.count-1 downto 0 do
   2.246 +  begin
   2.247 +    a := activeSearches[activeSearches.byIndex(i)] as TActiveSearch;
   2.248 +    if (a.started + (OneMinute*2)) < now() then
   2.249 +    begin
   2.250 +      log(llInfo, 'Removing a search that timed out ' + activeSearches.byIndex(i));
   2.251 +      activeSearches.remove(activeSearches.byIndex(i));
   2.252 +    end;
   2.253 +  end;
   2.254 +end;
   2.255 +
   2.256 +procedure TSearchPlugin.commandStartFileSearch(m:TMsgCommandStartFileSearch);
   2.257 +var
   2.258 +  n, i: integer;
   2.259 +  peers: TStringList;
   2.260 +  q: TMsgFileSearch;
   2.261 +  s: TActiveSearch;
   2.262 +begin
   2.263 +  repeat
   2.264 +    n := Random(maxLongint);
   2.265 +  until activeSearches[inttostr(n)] = nil;
   2.266 +  s := TActiveSearch.Create;
   2.267 +  s.searchId := n;
   2.268 +  s.started := now();
   2.269 +  activeSearches[inttostr(n)] := s;  // TODO this is never released!!
   2.270 +  for i:=0 to PluginManager.PeerList.count-1 do
   2.271 +    PluginManager.PeerList.get(i).enqueue(TMsgFileSearch.create(n, m.keywords, m.min, m.max));
   2.272 +  Notifier.postToController(TMsgCommandNewFileSearch.Create(n, m.keywords));
   2.273 +end;
   2.274 +
   2.275 +procedure TSearchPlugin.readFileSearch(m:TMsgFileSearch);
   2.276 +var
   2.277 +  rs: TResultSet;
   2.278 +  i: integer;
   2.279 +  kw: TStringDynArray;
   2.280 +  q: string;
   2.281 +begin
   2.282 +  log(llDebug, 'Received FileSearch');
   2.283 +  q := ' where ok = 1 ';
   2.284 +  kw := SeparateString(m.keywords, ' ');
   2.285 +  for i:=0 to length(kw)-1 do
   2.286 +  begin
   2.287 +    kw[i] := '%'+kw[i]+'%';
   2.288 +    q := q + 'and (filename like ?)';
   2.289 +  end;
   2.290 +
   2.291 +  if m.minSize > 0 then
   2.292 +  begin
   2.293 +    setlength(kw, length(kw) + 1);
   2.294 +    kw[length(kw)-1] := inttostr((int64(m.minsize) * int64(1024*1024)));
   2.295 +    q := q + ' and (size >= ?)';
   2.296 +  end;
   2.297 +  if m.maxSize > 0 then
   2.298 +  begin
   2.299 +    setlength(kw, length(kw)+1);
   2.300 +    kw[length(kw)-1] := inttostr((int64(m.maxsize) * int64(1024*1024)));
   2.301 +    q := q + ' and (size <= ?)';
   2.302 +  end;
   2.303 +
   2.304 +  (* use this one instead:
   2.305 +
   2.306 +  select filename, hash, size from (
   2.307 +  select 1 x,* from files where filename like '%m%'  and size < 1000 and size > 400
   2.308 +  union
   2.309 +  select 2 x,* from files where virtualpath like '%m%'  and size < 1000 and size > 400
   2.310 +  )  order by x asc limit 100
   2.311 +  *)
   2.312 +
   2.313 +  (*
   2.314 +    with groups:
   2.315 +
   2.316 +select f.filename, f.hash, f.size from shares_visible_per_user s, paths p, files f where f.virtualPath = p.name and p.shareId = s.shareId
   2.317 +
   2.318 +  *)
   2.319 +
   2.320 +  // add GID to query
   2.321 +  setlength(kw, length(kw)+1);
   2.322 +  kw[length(kw)-1] := m.peer.gid;
   2.323 +  q := q + ' and (s.gid = ?)';
   2.324 +
   2.325 +
   2.326 +
   2.327 +  q := 'select f.filename, f.hash, f.size from shares_visible_per_user s, paths p, files f where f.virtualPath = p.name and p.shareId = s.shareId ' + q + ' limit 100';
   2.328 +  log(llInfo, 'Search query: ' + q);
   2.329 +  rs := Database.executeQuery(q, kw);
   2.330 +  try
   2.331 +    while rs.next do
   2.332 +    begin
   2.333 +      log(llDebug, 'Sending a result');
   2.334 +      m.peer.enqueue(TMsgFileSearchReply.Create(m.searchid, rs[0], rs[1], strtoint64(rs[2])));
   2.335 +    end;
   2.336 +    log(llDebug, 'finished sending results');
   2.337 +  finally
   2.338 +    log(llDebug, 'closing resultset');
   2.339 +    rs.Free;
   2.340 +  end;
   2.341 +end;
   2.342 +
   2.343 +procedure TSearchPlugin.readFileSearchReply(m:TMsgFileSearchReply);
   2.344 +var s: TActiveSearch;
   2.345 +begin
   2.346 +  log(llDebug, 'Received FileSearchReply');
   2.347 +  log(llDebug, m.name + ' ' + inttostr(m.size) + ' ' +m.hash);
   2.348 +  s := activeSearches[inttostr(m.searchId)] as TActiveSearch;
   2.349 +  if s = nil then
   2.350 +    log(llWarning, 'Received reply summary without search.. timeout?')
   2.351 +  else
   2.352 +    notifier.postToController(TMsgCommandFileSearchReply.Create(m.searchId,
   2.353 +        m.peer.gid, m.name, m.hash, m.size));
   2.354 +end;
   2.355 +
   2.356 +
   2.357 +end.