﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-enhydraboy</title><link>http://www.cnblogs.com/enhydraboy/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 05 Jul 2009 22:08:31 GMT</lastBuildDate><pubDate>Sun, 05 Jul 2009 22:08:31 GMT</pubDate><ttl>60</ttl><item><title>[ZT]MSN Messenger的口令获取源代码, MSNMessenger的口令是经过DPAPI加密后保存在注册表中</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/12/01/71533.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Wed, 01 Dec 2004 06:47:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/12/01/71533.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/71533.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/12/01/71533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/71533.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/71533.html</trackback:ping><description><![CDATA[来自http://www.msning.com/bbs/index.php?showtopic=15654<br/><br/>/* MSNMessenger的口令是经过DPAPI加密后保存在注册表中的<br/>* 这个程序演示解码过程<br/>* tombkeeper[0x40]nsfocus[0x2e]com<br/>* tombkeeper[0x40]xfocus[0x2e]net<br/>* 2004.08.11<br/>*/<br/>#include &lt;Windows.h&gt;<br/><br/>#pragma comment(lib, &quot;Advapi32.lib&quot;)<br/>#define FCHK(a) if (!(a)) {printf(#a &quot; failed\n&quot;); return 0;}<br/>typedef struct _CRYPTOAPI_BLOB {<br/>DWORD cbData;<br/>BYTE* pbData;<br/>} DATA_BLOB;<br/>typedef struct _CRYPTPROTECT_PROMPTSTRUCT {<br/>DWORD cbSize;<br/>DWORD dwPromptFlags;<br/>HWND hwndApp;<br/>LPCWSTR szPrompt;<br/>} CRYPTPROTECT_PROMPTSTRUCT, *PCRYPTPROTECT_PROMPTSTRUCT;<br/>typedef BOOL (WINAPI *PCryptUnprotectData)(<br/>DATA_BLOB* pDataIn,<br/>LPWSTR* ppszDataDescr,<br/>DATA_BLOB* pOptionalEntropy,<br/>PVOID pvReserved,<br/>CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,<br/>DWORD dwFlags,<br/>DATA_BLOB* pDataOut<br/>);<br/>PCryptUnprotectData CryptUnprotectData = NULL;<br/><br/>int main(void)<br/>{<br/>int ret;<br/>HMODULE hNtdll;<br/>HKEY hKey;<br/>DWORD dwType;<br/>char Data[0x100] = {0};<br/>DWORD dwSize;<br/>DATA_BLOB DataIn;<br/>DATA_BLOB DataOut;<br/>ret = RegOpenKeyEx<br/>(<br/>HKEY_CURRENT_USER,<br/>&quot;Software\\Microsoft\\MSNMessenger&quot;,<br/>0,<br/>KEY_READ,<br/>&amp;hKey<br/>);<br/>if( ret != ERROR_SUCCESS ) return 1;<br/>ret = RegQueryValueEx<br/>(<br/>hKey,<br/>&quot;Password.NET Messenger Service&quot;,<br/>NULL,<br/>&amp;dwType,<br/>Data,<br/>&amp;dwSize<br/>);<br/>if( ret != ERROR_SUCCESS ) return 1;<br/>FCHK ((hNtdll = LoadLibrary (&quot;Crypt32.dll&quot;)) != NULL);<br/>FCHK ((CryptUnprotectData = (PCryptUnprotectData)<br/>GetProcAddress (hNtdll, &quot;CryptUnprotectData&quot;)) != NULL);<br/>DataIn.pbData = Data + 2; //口令密文从第二位开始<br/>DataIn.cbData = dwSize-2;<br/>CryptUnprotectData<br/>(<br/>&amp;DataIn,<br/>NULL,<br/>NULL,<br/>NULL,<br/>NULL,<br/>1,<br/>&amp;DataOut<br/>);<br/>base64_decode (DataOut.pbData, Data, strlen(DataOut.pbData));<br/>printf ( &quot;MSN Password: %s\n&quot;, Data);<br/>return 0;<br/>}<br/>//copied from GNU libc - libc/resolv/base64.c<br/>int base64_decode (char const *src, char *target, size_t targsize)<br/>{<br/>static const char Base64[] =<br/>&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;;<br/>static const char Pad64 = ‘=‘;<br/>int tarindex, state, ch;<br/>char *pos;<br/>state = 0;<br/>tarindex = 0;<br/>while ((ch = *src++) != ‘\0‘)<br/>{<br/>if (isspace (ch)) /* Skip whitespace anywhere. */<br/>continue;<br/>if (ch == Pad64)<br/>break;<br/>pos = strchr (Base64, ch);<br/>if (pos == 0) /* A non-base64 character. */<br/>return (-1);<br/>switch (state)<br/>{<br/>case 0:<br/>if (target)<br/>{<br/>if ((size_t) tarindex &gt;= targsize)<br/>return (-1);<br/>target[tarindex] = (pos - Base64) &lt;&lt; 2;<br/>}<br/>state = 1;<br/>break;<br/>case 1:<br/>if (target)<br/>{<br/>if ((size_t) tarindex + 1 &gt;= targsize)<br/>return (-1);<br/>target[tarindex] |= (pos - Base64) &gt;&gt; 4;<br/>target[tarindex + 1] = ((pos - Base64) &amp; 0x0f) &lt;&lt; 4;<br/>}<br/>tarindex++;<br/>state = 2;<br/>break;<br/>case 2:<br/>if (target)<br/>{<br/>if ((size_t) tarindex + 1 &gt;= targsize)<br/>return (-1);<br/>target[tarindex] |= (pos - Base64) &gt;&gt; 2;<br/>target[tarindex + 1] = ((pos - Base64) &amp; 0x03) &lt;&lt; 6;<br/>}<br/>tarindex++;<br/>state = 3;<br/>break;<br/>case 3:<br/>if (target)<br/>{<br/>if ((size_t) tarindex &gt;= targsize)<br/>return (-1);<br/>target[tarindex] |= (pos - Base64);<br/>}<br/>tarindex++;<br/>state = 0;<br/>break;<br/>default:<br/>abort ();<br/>}<br/>}<br/>/*<br/>* We are done decoding Base-64 chars. Let‘s see if we ended<br/>* on a byte boundary, and/or with erroneous trailing characters.<br/>*/<br/>if (ch == Pad64)<br/>{ /* We got a pad char. */<br/>ch = *src++; /* Skip it, get next. */<br/>switch (state)<br/>{<br/>case 0: /* Invalid = in first position */<br/>case 1: /* Invalid = in second position */<br/>return (-1);<br/>case 2: /* Valid, means one byte of info */<br/>/* Skip any number of spaces. */<br/>for ((void) NULL; ch != ‘\0‘; ch = *src++)<br/>if (!isspace (ch))<br/>break;<br/>/* Make sure there is another trailing = sign. */<br/>if (ch != Pad64)<br/>return (-1);<br/>ch = *src++; /* Skip the = */<br/>/* Fall through to &quot;single trailing =&quot; case. */<br/>/* FALLTHROUGH */<br/>case 3: /* Valid, means two bytes of info */<br/>/*<br/>* We know this char is an =. Is there anything but<br/>* whitespace after it?<br/>*/<br/>for ((void) NULL; ch != ‘\0‘; ch = *src++)<br/>if (!isspace (ch))<br/>return (-1);<br/>/*<br/>* Now make sure for cases 2 and 3 that the &quot;extra&quot;<br/>* bits that slopped past the last full byte were<br/>* zeros. If we don‘t check them, they become a<br/>* subliminal channel.<br/>*/<br/>if (target &amp;&amp; target[tarindex] != 0)<br/>return (-1);<br/>}<br/>}<br/>else<br/>{<br/>/*<br/>* We ended by seeing the end of the string. Make sure we<br/>* have no partial bytes lying around.<br/>*/<br/>if (state != 0)<br/>return (-1);<br/>}<br/>return (tarindex);<br/>}<br/>//<A href="http://www.vchelp.net/itbookreview/view_paper.asp?paper_id=103" target="_blank">透视木马开发技术</A> <img src ="http://www.cnblogs.com/enhydraboy/aggbug/71533.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47989/" target="_blank">Twitter无处不在 魔兽世界Twitter发送器插件发布</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>ADO Connection Strings[转贴]</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/11/04/60253.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Thu, 04 Nov 2004 02:18:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/11/04/60253.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/60253.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/11/04/60253.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/60253.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/60253.html</trackback:ping><description><![CDATA[摘要: 仅为了以后自己查询方便。http://www.codeproject.com/database/connectionstrings.aspBy Carlos Antollini OverviewGenerally one of the first steps when you are trying to work with databases is open it. You can find se&nbsp;&nbsp;<a href='http://www.cnblogs.com/enhydraboy/archive/2004/11/04/60253.html'>阅读全文</a><img src ="http://www.cnblogs.com/enhydraboy/aggbug/60253.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47988/" target="_blank">Firefox 3.5匆忙推出漏洞多 Mozilla本月将更新</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>农民造“飞碟”后记</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/11/02/59514.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Tue, 02 Nov 2004 01:23:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/11/02/59514.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/59514.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/11/02/59514.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/59514.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/59514.html</trackback:ping><description><![CDATA[&#160;&#160;&#160;&#160;&#160; 前日在新闻晨报（10/30日，A6版）上看到，近日的珠海航展会上，杜大哥的自制飞碟已经参展了。本人不再想重复对于这件事的看法，详见&#160;<A id="viewpost1_TitleUrl" href="/enhydraboy/articles/10470.html">农民造“飞碟”有感</A>&#160;<br/>&#160;&#160;&#160;&#160;&#160; 该报刊登的北航专家的质疑正验证了5个月前我的观点。这个目前采用汽车发动机的“飞碟”，只不过采用了垂直动力技术而非水平动力技术，没有任何实用价值。就如我所说的其无非是一个靠“飞碟”的外观唬唬人罢了的东西。而下面一则关于当事人接受记者的采访的报道中，大致也就是当事人大谈其认为的商业前景，当然最后离不了一个钱字而已。<br/>&#160;&#160;&#160;&#160;&#160; 如果不是造一个蝶形会飞的东西，也不会引起这么多人的关注，炒作的前因后果大体也就如此。然而对于任何事的质疑是必须的，任何经不起“挑战”的东西，大多也没有什么前途。<br/>&#160;&#160;&#160;&#160;&#160; 近日，有几位“傻叉”不离口的网友，也正兴致勃勃地关注此事，并且把“叉”随意泼洒。对此行径，只能哧之以鼻。如果其有任何自认为有意义的东西，竟可洋洋洒洒发表一通，又何必脑涨通红且自甘堕落地要从“叉”之类的地方找些快感。也许他们忘记了，他们也是从“叉”这个地方诞生的。<br/>&#160;&#160;&#160;&#160; 当然，对于此类的“叉”先生的“叉”言论，只能采用一个办法“叉叉”(delete)。<br/><img src ="http://www.cnblogs.com/enhydraboy/aggbug/59514.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47987/" target="_blank">预测：Twitter最可能收购的十家公司</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>Tomcat's Thread Pool Source(BT)</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/09/29/47872.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Wed, 29 Sep 2004 06:46:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/09/29/47872.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/47872.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/09/29/47872.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/47872.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/47872.html</trackback:ping><description><![CDATA[/*<BR> *&nbsp; Copyright 1999-2004 The Apache Software Foundation<BR> *<BR> *&nbsp; Licensed under the Apache License, Version 2.0 (the "License");<BR> *&nbsp; you may not use this file except in compliance with the License.<BR> *&nbsp; You may obtain a copy of the License at<BR> *<BR> *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.apache.org/licenses/LICENSE-2.0<BR> *<BR> *&nbsp; Unless required by applicable law or agreed to in writing, software<BR> *&nbsp; distributed under the License is distributed on an "AS IS" BASIS,<BR> *&nbsp; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<BR> *&nbsp; See the License for the specific language governing permissions and<BR> *&nbsp; limitations under the License.<BR> */<BR><BR>package org.apache.tomcat.util.threads;<BR><BR>import java.util.*;<BR>import org.apache.commons.logging.Log;<BR>import org.apache.commons.logging.LogFactory;<BR>import org.apache.tomcat.util.res.StringManager;<BR><BR>/**<BR> * A thread pool that is trying to copy the apache process management.<BR> *<BR> * @author Gal Shachor<BR> */<BR>public class ThreadPool&nbsp; {<BR><BR>&nbsp;&nbsp;&nbsp; private static Log log = LogFactory.getLog(ThreadPool.class);<BR><BR>&nbsp;&nbsp;&nbsp; private static StringManager sm =<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringManager.getManager("org.apache.tomcat.util.threads.res");<BR><BR>&nbsp;&nbsp;&nbsp; private static boolean logfull=true;<BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Default values ...<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public static final int MAX_THREADS = 200;<BR>&nbsp;&nbsp;&nbsp; public static final int MAX_THREADS_MIN = 10;<BR>&nbsp;&nbsp;&nbsp; public static final int MAX_SPARE_THREADS = 50;<BR>&nbsp;&nbsp;&nbsp; public static final int MIN_SPARE_THREADS = 4;<BR>&nbsp;&nbsp;&nbsp; public static final int WORK_WAIT_TIMEOUT = 60*1000;<BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Where the threads are held.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected ControlRunnable[] pool = null;<BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * A monitor thread that monitors the pool for idel threads.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected MonitorRunnable monitor;<BR><BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Max number of threads that you can open in the pool.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected int maxThreads;<BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Min number of idel threads that you can leave in the pool.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected int minSpareThreads;<BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Max number of idel threads that you can leave in the pool.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected int maxSpareThreads;<BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Number of threads in the pool.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected int currentThreadCount;<BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Number of busy threads in the pool.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected int currentThreadsBusy;<BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Flag that the pool should terminate all the threads and stop.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected boolean stopThePool;<BR><BR>&nbsp;&nbsp;&nbsp; /* Flag to control if the main thread is 'daemon' */<BR>&nbsp;&nbsp;&nbsp; protected boolean isDaemon=true;<BR><BR>&nbsp;&nbsp;&nbsp; /** The threads that are part of the pool.<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Key is Thread, value is the ControlRunnable<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected Hashtable threads=new Hashtable();<BR><BR>&nbsp;&nbsp;&nbsp; protected Vector listeners=new Vector();<BR><BR>&nbsp;&nbsp;&nbsp; /** Name of the threadpool<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected String name = "TP";<BR><BR>&nbsp;&nbsp;&nbsp; /**<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Sequence.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected int sequence = 1;<BR><BR><BR>&nbsp;&nbsp;&nbsp; /**<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Constructor.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public ThreadPool() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads = MAX_THREADS;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxSpareThreads = MAX_SPARE_THREADS;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minSpareThreads = MIN_SPARE_THREADS;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadCount = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadsBusy = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stopThePool = false;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR><BR>&nbsp;&nbsp;&nbsp; /** Create a ThreadPool instance.<BR>&nbsp;&nbsp;&nbsp;&nbsp; *<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @param jmx True if you want a pool with JMX support. A regular pool<BR>&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; will be returned if JMX or the modeler are not available.<BR>&nbsp;&nbsp;&nbsp;&nbsp; *<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @return ThreadPool instance. If JMX support is requested, you need to<BR>&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp; call register() in order to set a name.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public static ThreadPool createThreadPool(boolean jmx) {<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( jmx ) {<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class.forName( "org.apache.commons.modeler.Registry");<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class tpc=Class.forName( "org.apache.tomcat.util.threads.ThreadPoolMX");<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadPool res=(ThreadPool)tpc.newInstance();<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return res;<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch( Exception ex ) {<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new ThreadPool();<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public synchronized void start() {<BR>	stopThePool=false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadCount&nbsp; = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadsBusy&nbsp; = 0;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adjustLimits();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool = new ControlRunnable[maxThreads];<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; openThreads(minSpareThreads);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (maxSpareThreads &lt; maxThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; monitor = new MonitorRunnable(this);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public MonitorRunnable getMonitor() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return monitor;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public void setMaxThreads(int maxThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.maxThreads = maxThreads;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public int getMaxThreads() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return maxThreads;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public void setMinSpareThreads(int minSpareThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.minSpareThreads = minSpareThreads;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public int getMinSpareThreads() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return minSpareThreads;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public void setMaxSpareThreads(int maxSpareThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.maxSpareThreads = maxSpareThreads;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public int getMaxSpareThreads() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return maxSpareThreads;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public int getCurrentThreadCount() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return currentThreadCount;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public int getCurrentThreadsBusy() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return currentThreadsBusy;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public boolean isDaemon() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return isDaemon;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public static int getDebug() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /** The default is true - the created threads will be<BR>&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; in daemon mode. If set to false, the control thread<BR>&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; will not be daemon - and will keep the process alive.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public void setDaemon( boolean b ) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isDaemon=b;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public boolean getDaemon() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return isDaemon;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public void setName(String name) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.name = name;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public String getName() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return name;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public int getSequence() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return sequence++;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public void addThread( Thread t, ControlRunnable cr ) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; threads.put( t, cr );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for( int i=0; i<LISTENERS.SIZE(); tpl.threadStart(this, removeThread( Thread t threads.remove(t); for( i<listeners.size(); i++ tpl.threadEnd(this, addThreadPoolListener( ThreadPoolListener listeners.addElement( tpl="(ThreadPoolListener)listeners.elementAt(i);" Enumeration getThreads(){ return threads.keys(); run(Runnable You may wonder what you see here ... basically I am trying maintain stack This way locality kept there is better chance find residues memory next time it runs. Executes given Runnable on in pool, block needed. runIt(ThreadPoolRunnable if(null="=" r) NullPointerException(); c.runIt(r); private findControlRunnable() ControlRunnable c="findControlRunnable();" ( throw IllegalStateException(); Obtain free from pool. synchronized(this) (currentThreadsBusy="=" currentThreadCount) All maxThreads) Not all were open, Open up max number of idel int toOpen="currentThreadCount" minSpareThreads; openThreads(toOpen); logFull(log, currentThreadCount, maxThreads); Wait for a become idel. this.wait(); was just Throwable -- but no other exceptions can be thrown wait, right? So catch ignore this one, it?ll never actually happen, since nowhere do say pool.interrupt(). catch(InterruptedException e) log.error(?Unexpected exception?, e); log.debug(?Finished waiting: CTC="+currentThreadCount +&#10;&#9;&#9;&#9;&#9;  " , CTB=" + currentThreadsBusy);&#10;                    }&#10;                    // Pool was stopped. Get away of the pool.&#10;                    if( stopThePool) {&#10;                        break;&#10;                    }&#10;                }&#10;            }&#10;            // Pool was stopped. Get away of the pool.&#10;            if(0 == currentThreadCount || stopThePool) {&#10;                throw new IllegalStateException();&#10;            }&#10;                    &#10;            // If we are here it means that there is a free thread. Take it.&#10;            int pos = currentThreadCount - currentThreadsBusy - 1;&#10;            c = pool[pos];&#10;            pool[pos] = null;&#10;            currentThreadsBusy++;&#10;&#10;        }&#10;        return c;&#10;    }&#10;&#10;    private static void logFull(Log loghelper, int currentThreadCount,&#10;                                int maxThreads) {&#10;&#9;if( logfull ) {&#10;            log.error(sm.getString(" threadpool.busy?, Integer(currentThreadCount), new Integer(maxThreads))); logfull="false;" else if( log.isDebugEnabled() ) log.debug(?All threads busy currentThreadCount ? + maxThreads ); Stop public shutdown() if(!stopThePool) stopThePool if (monitor !="null)" monitor.terminate(); for(int i="0;" < (currentThreadCount 1) ; i++) try pool[i].terminate(); catch(Throwable t) Do nothing... The show must go on, we are and nothing should stop that. log.error(?Ignored exception while shutting down pool?, t); currentThreadsBusy pool="0;" notifyAll(); ** Called by the monitor="null;" thread to harvest idle threads. * protected synchronized void checkSpareControllers() if(stopThePool) { return; } if((currentThreadCount - currentThreadsBusy)> maxSpareThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int toFree = currentThreadCount -<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadsBusy -<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxSpareThreads;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0 ; i &lt; toFree ; i++) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ControlRunnable c = pool[currentThreadCount - currentThreadsBusy - 1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.terminate();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool[currentThreadCount - currentThreadsBusy - 1] = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadCount --;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /**<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Returns the thread to the pool.<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Called by threads as they are becoming idel.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected synchronized void returnController(ControlRunnable c) {<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(0 == currentThreadCount || stopThePool) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.terminate();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // atomic<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadsBusy--;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool[currentThreadCount - currentThreadsBusy - 1] = c;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notify();<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /**<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Inform the pool that the specific thread finish.<BR>&nbsp;&nbsp;&nbsp;&nbsp; *<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Called by the ControlRunnable.run() when the runnable<BR>&nbsp;&nbsp;&nbsp;&nbsp; * throws an exception.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected synchronized void notifyThreadEnd(ControlRunnable c) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadsBusy--;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadCount --;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notify();<BR>&nbsp;&nbsp;&nbsp; }<BR><BR><BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * Checks for problematic configuration and fix it.<BR>&nbsp;&nbsp;&nbsp;&nbsp; * The fix provides reasonable settings for a single CPU<BR>&nbsp;&nbsp;&nbsp;&nbsp; * with medium load.<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected void adjustLimits() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(maxThreads &lt;= 0) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads = MAX_THREADS;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (maxThreads &lt; MAX_THREADS_MIN) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.warn(sm.getString("threadpool.max_threads_too_low",<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Integer(maxThreads),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Integer(MAX_THREADS_MIN)));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads = MAX_THREADS_MIN;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(maxSpareThreads &gt;= maxThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxSpareThreads = maxThreads;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(maxSpareThreads &lt;= 0) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(1 == maxThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxSpareThreads = 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxSpareThreads = maxThreads/2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(minSpareThreads &gt;&nbsp; maxSpareThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minSpareThreads =&nbsp; maxSpareThreads;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(minSpareThreads &lt;= 0) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(1 == maxSpareThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minSpareThreads = 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minSpareThreads = maxSpareThreads/2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /** Create missing threads.<BR>&nbsp;&nbsp;&nbsp;&nbsp; *<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @param toOpen Total number of threads we'll have open<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; protected void openThreads(int toOpen) {<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(toOpen &gt; maxThreads) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; toOpen = maxThreads;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = currentThreadCount ; i &lt; toOpen ; i++) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool[i - currentThreadsBusy] = new ControlRunnable(this);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentThreadCount = toOpen;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /** @deprecated */<BR>&nbsp;&nbsp;&nbsp; void log( String s ) {<BR>	log.info(s);<BR>	//loghelper.flush();<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; /** <BR>&nbsp;&nbsp;&nbsp;&nbsp; * Periodically execute an action - cleanup in this case<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public static class MonitorRunnable implements Runnable {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadPool p;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread&nbsp;&nbsp;&nbsp;&nbsp; t;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int interval=WORK_WAIT_TIMEOUT;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean&nbsp;&nbsp;&nbsp; shouldTerminate;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MonitorRunnable(ThreadPool p) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.p=p;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.start();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void start() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldTerminate = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t = new Thread(this);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.setDaemon(p.getDaemon() );<BR>	&nbsp;&nbsp;&nbsp; t.setName(p.getName() + "-Monitor");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.start();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setInterval(int i ) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.interval=i;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Sleep for a while.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(this) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.wait(WORK_WAIT_TIMEOUT);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Check if should terminate.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // termination happens when the pool is shutting down.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(shouldTerminate) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Harvest idle threads.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.checkSpareControllers();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch(Throwable t) {<BR>		&nbsp;&nbsp;&nbsp; ThreadPool.log.error("Unexpected exception", t);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void stop() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.terminate();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>	/** Stop the monitor<BR>	 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public synchronized void terminate() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldTerminate = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.notify();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /**<BR>&nbsp;&nbsp;&nbsp;&nbsp; * A Thread object that executes various actions ( ThreadPoolRunnable )<BR>&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; under control of ThreadPool<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public static class ControlRunnable implements Runnable {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<BR>	 * ThreadPool where this thread will be returned<BR>	 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private ThreadPool p;<BR><BR>	/**<BR>	 * The thread that executes the actions<BR>	 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private ThreadWithAttributes&nbsp;&nbsp;&nbsp;&nbsp; t;<BR><BR>	/**<BR>	 * The method that is executed in this thread<BR>	 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private ThreadPoolRunnable&nbsp;&nbsp; toRun;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Runnable toRunRunnable;<BR><BR>	/**<BR>	 * Stop this thread<BR>	 */<BR>	private boolean&nbsp;&nbsp;&nbsp; shouldTerminate;<BR><BR>	/**<BR>	 * Activate the execution of the action<BR>	 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private boolean&nbsp;&nbsp;&nbsp; shouldRun;<BR><BR>	/**<BR>	 * Per thread data - can be used only if all actions are<BR>	 *&nbsp; of the same type.<BR>	 *&nbsp; A better mechanism is possible ( that would allow association of<BR>	 *&nbsp; thread data with action type ), but right now it's enough.<BR>	 */<BR>	private boolean noThData;<BR><BR>	/**<BR>	 * Start a new thread, with no method in it<BR>	 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ControlRunnable(ThreadPool p) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; toRun = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldTerminate = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldRun = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.p = p;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t = new ThreadWithAttributes(p, this);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.setDaemon(true);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.setName(p.getName() + "-Processor" + p.getSequence());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.addThread( t, this );<BR>	&nbsp;&nbsp;&nbsp; noThData=true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.start();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean _shouldRun = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean _shouldTerminate = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadPoolRunnable _toRun = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (true) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Wait for work. */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (this) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (!shouldRun &amp;&amp; !shouldTerminate) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.wait();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _shouldRun = shouldRun;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _shouldTerminate = shouldTerminate;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _toRun = toRun;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_shouldTerminate) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ThreadPool.log.isDebugEnabled())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadPool.log.debug("Terminate");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Check if should execute a runnable.&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (noThData) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_toRun != null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object thData[] = _toRun.getInitData();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.setThreadData(p, thData);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ThreadPool.log.isDebugEnabled())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadPool.log.debug(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Getting new thread data");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; noThData = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_shouldRun) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_toRun != null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _toRun.runIt(t.getThreadData(p));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (toRunRunnable != null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; toRunRunnable.run();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ThreadPool.log.isDebugEnabled())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadPool.log.debug("No toRun ???");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Throwable t) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadPool.log.error(sm.getString<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ("threadpool.thread_error", t, toRun.toString()));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * The runnable throw an exception (can be even a ThreadDeath),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * signalling that the thread die.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * The meaning is that we should release the thread from<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * the pool.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldTerminate = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldRun = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.notifyThreadEnd(this);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_shouldRun) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldRun = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Notify the pool that the thread is now idle.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.returnController(this);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Check if should terminate.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * termination happens when the pool is shutting down.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_shouldTerminate) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException ie) { /* for the wait operation */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // can never happen, since we don't call interrupt<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadPool.log.error("Unexpected exception", ie);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.removeThread(Thread.currentThread());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Run a task<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param toRun<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public synchronized void runIt(Runnable toRun) {<BR>	&nbsp;&nbsp;&nbsp; this.toRunRunnable = toRun;<BR>	&nbsp;&nbsp;&nbsp; // Do not re-init, the whole idea is to run init only once per<BR>	&nbsp;&nbsp;&nbsp; // thread - the pool is supposed to run a single task, that is<BR>	&nbsp;&nbsp;&nbsp; // initialized once.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // noThData = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldRun = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.notify();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Run a task<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param toRun<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public synchronized void runIt(ThreadPoolRunnable toRun) {<BR>	&nbsp;&nbsp;&nbsp; this.toRun = toRun;<BR>	&nbsp;&nbsp;&nbsp; // Do not re-init, the whole idea is to run init only once per<BR>	&nbsp;&nbsp;&nbsp; // thread - the pool is supposed to run a single task, that is<BR>	&nbsp;&nbsp;&nbsp; // initialized once.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // noThData = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldRun = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.notify();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void stop() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.terminate();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void kill() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.stop();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public synchronized void terminate() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldTerminate = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.notify();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /** Debug display of the stage of each thread. The return is html style,<BR>&nbsp;&nbsp;&nbsp;&nbsp; * for display in the console ( it can be easily parsed too )<BR>&nbsp;&nbsp;&nbsp;&nbsp; *<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @return<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public String threadStatusString() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer sb=new StringBuffer();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Iterator it=threads.keySet().iterator();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append("
<UL>");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while( it.hasNext()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append("
<LI>");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadWithAttributes twa=(ThreadWithAttributes)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; it.next();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append(twa.getCurrentStage(this) ).append(" ");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append( twa.getParam(this));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append( "\n");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append("</LI></UL>");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return sb.toString();<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /** Return an array with the status of each thread. The status<BR>&nbsp;&nbsp;&nbsp;&nbsp; * indicates the current request processing stage ( for tomcat ) or<BR>&nbsp;&nbsp;&nbsp;&nbsp; * whatever the thread is doing ( if the application using TP provide<BR>&nbsp;&nbsp;&nbsp;&nbsp; * this info )<BR>&nbsp;&nbsp;&nbsp;&nbsp; *<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @return<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public String[] getThreadStatus() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String status[]=new String[ threads.size()];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Iterator it=threads.keySet().iterator();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for( int i=0; ( i<STATUS.LENGTH Thread for( i++ ThreadPoolListener return This is better it="threads.keySet().iterator();" ( of int a be ) threads ? public i="0;" < are and t); ** the to * void { } Return an array with current ?param? XXX name each thread. typically last request. @return String[] getThreadParam() String status[]="new" String[ threads.size()]; Iterator i<status.length && it.hasNext()); ThreadWithAttributes twa="(ThreadWithAttributes)" it.next(); Object o="twa.getParam(this);" status[i]="twa.getCurrentStage(this);" null : o.toString(); status; Interface allow applications notified when created stopped. static interface threadStart( threadEnd( ThreadPool tp, pre><BR><img src ="http://www.cnblogs.com/enhydraboy/aggbug/47872.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47986/" target="_blank">网易澄清:与暴雪合资公司仅提供技术支持</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>使用 jakata DBCP package 作 DB Connection pooling[ZT]</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/09/22/45479.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Wed, 22 Sep 2004 03:16:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/09/22/45479.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/45479.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/09/22/45479.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/45479.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/45479.html</trackback:ping><description><![CDATA[<SPAN class=javascript id=text44045>一般來說，在多人使用的系統中，應用程式若沒有運用 Connection pooling 的機制，會造成很大的效能問題，Connection 開開關關，除了慢，也會耗損資料庫伺服器的資源。大部分的 AP Server 都有提供 Connection pooling 的機制，程式設計師並無須去顧慮這個機制是如何運作的，只要懂得設定相關的參數即可。<BR><BR>假如說，某種狀況下，我們必須自行建置 Connection pooling 的機制時，該如何進行呢？自己寫當然是非常不划算的，況且也不一定寫的好，在這裡，我們使用 jakata project 裡的一個子專案 DBCP，來快速的建置一個隨處可用的 Connection pooling 機制。<BR><BR>在 Tomcat 裡，DBCP 是內建的，用來管理 DB Connection pooling。這個機制是可移植且可獨立出來使用的，要在你的運用程式中加上 DBCP 的功能，你必須至 <A class=ilink href="http://jakarta.apache.org/commons/index.html" target=_blank>http://jakarta.apache.org/commons/index.html</A> 這個網址，找到該網頁內的 Components，共有三個必須下載：Collections 、 DBCP 、 Pool 。DBCP 是運用 Collections 及 Pool 這二個基礎的 Components 所設計出來的。當然，如果你有安裝 Tomcat server，最佳的方式是至 $TOMCAT_HOME/common/lib/ 目錄下去取得，保證版本的配合度不會出現問題。在 Tomcat server 裡，以 Tomcat 5.0.19 版內附的最新版本，這三個 Components 的檔名分別是 commons-collections.jar 、 commons-pool-1.1.jar 及 commons-dbcp-1.1.jar。<BR><BR>取得使用 DBCP 必備的 jar 檔後，請記得將這些 jar 檔，放置到 CLASSPATH 中，或直接放至 $JAVA_HOME/jre/lib/ext/ 目錄內。不過，由於 DBCP 有運用到 DataSource 的功能，而這功能是 J2EE 才有的，所以你還必須去下載 J2EE 的一個 javax.jar 檔。<BR><BR>環境建置好之後，接下來就可以開始設計 Connection Pooling 的機制，在這兒，我們介紹最簡單的作法，只要幾行指令就可以完成了，請看範例區裡的程式及其說明。<BR><BR>完成這個程式後，接下來在你的應用程式裡，用 DBConnect.getConnection() 來取得 DB Connection，就能享受到 Connection Pooling 的功能了。<BR><BR>在實際的運作中，這個範例有加上偵錯指令，會顯示出目前 Connection Pool 裡，有多少個 Idle 的 Connection 及多少個 Active 的 Connection，可供作為系統運作的參數調整依據。<BR><BR>範例： <BR><PRE class=codeStyle>01 package util;<BR>02 <BR>03 import java.sql.*;<BR>04 import javax.naming.*;<BR>05 import javax.sql.*;<BR>06 <BR>07 import org.apache.commons.dbcp.BasicDataSource;<BR>08 <BR>09 public class DBConnect {<BR>10   static DataSource dataSource = null;<BR>11 <BR>12   public static DataSource setupDataSource( String sDrvName, String sUserName,<BR>13       String sPwd, String connectURI ) {<BR>14       BasicDataSource ds = new BasicDataSource();<BR>15       ds.setDriverClassName( sDrvName );<BR>16       ds.setUsername( sUserName );<BR>17       ds.setPassword( sPwd );<BR>18       ds.setUrl( connectURI );<BR>19       ds.setMaxActive( 50 );<BR>20       ds.setMaxIdle( 10 );<BR>21       ds.setMaxWait( 10000 ); // 10 seconds<BR>22       return ds;<BR>23   }<BR>24 <BR>25 <BR>26   // static init of the class<BR>27   static {<BR>28     try {<BR>29       System.setProperty( "jdbc.drivers", "oracle.jdbc.driver.OracleDriver" );<BR>30       Class.forName( "oracle.jdbc.driver.OracleDriver" );<BR>31 <BR>32       dataSource = setupDataSource( "oracle.jdbc.driver.OracleDriver", "username",<BR>33         "password", "jdbc:oracle:thin:@192.168.0.1:1521:SID" );<BR>34     }<BR>35     catch (Exception e) {<BR>36       System.out.println( "DBConnect.java =&gt; Unable to load driver."  + e.getMessage() );<BR>37     }<BR>38   }<BR>39 <BR>40   /**<BR>41    * 空的建構元，不作任何處理動作。<BR>42    */<BR>43   public DBConnect() {}<BR>44 <BR>45   /**<BR>46    * 取得 DB Connection.<BR>47    */<BR>48   public static Connection getConnection() throws SQLException,ClassNotFoundException {<BR>49     BasicDataSource bds = (BasicDataSource) dataSource;<BR>50     System.out.println("NumActive: " + bds.getNumActive() + ","<BR>51       + "NumIdle: " + bds.getNumIdle() );<BR>52     return dataSource.getConnection();<BR>53   }<BR>54 }</PRE></SPAN><img src ="http://www.cnblogs.com/enhydraboy/aggbug/45479.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47985/" target="_blank">杰克逊悼念仪式或成史上最大规模Web活动</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>数据类型的不匹配可能会导致索引失效</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/08/25/36422.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Wed, 25 Aug 2004 06:15:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/08/25/36422.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/36422.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/08/25/36422.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/36422.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/36422.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sybase和SQL Server在这一点上有所不同，如果条件比较中的数据类型不匹配的话，可能会引起索引失效，导致潜在的Performance问题。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 简单说明如下：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">Create</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">Table</SPAN><SPAN style="COLOR: #000000">&nbsp;Test(<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top>c1&nbsp;</SPAN><SPAN style="FONT-WEIGHT: bold; COLOR: #000000">int</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #808080">not</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">,<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top>c2&nbsp;</SPAN><SPAN style="FONT-WEIGHT: bold; COLOR: #000000">money</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">default</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="FONT-WEIGHT: bold; COLOR: #800000">0</SPAN><SPAN style="COLOR: #000000">,<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top>c3&nbsp;</SPAN><SPAN style="FONT-WEIGHT: bold; COLOR: #000000">varchar</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="FONT-WEIGHT: bold; COLOR: #800000">20</SPAN><SPAN style="COLOR: #000000">),<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">constraint</SPAN><SPAN style="COLOR: #000000">&nbsp;PK_Test&nbsp;</SPAN><SPAN style="COLOR: #0000ff">primary</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">key</SPAN><SPAN style="COLOR: #000000">(c1))<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">go</SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">create</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">index</SPAN><SPAN style="COLOR: #000000">&nbsp;ind_c2_Test&nbsp;</SPAN><SPAN style="COLOR: #0000ff">on</SPAN><SPAN style="COLOR: #000000">&nbsp;Test(c2)<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">go</SPAN></DIV></DIV>
<P>插入一些数据后，我们可以测试如下：<BR>1&gt; set showplan on<BR>2&gt; go<BR>1&gt; declare @var_int int<BR>2&gt; select @var_int=2<BR>3&gt; select * from Test where <A href="mailto:c1=@var_int">c1=@var_int</A><BR>4&gt; go</P>
<P>QUERY PLAN FOR STATEMENT 1 (at line 1).</P>
<P><BR>&nbsp;&nbsp;&nbsp; STEP 1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The type of query is DECLARE.</P>
<P><BR>QUERY PLAN FOR STATEMENT 2 (at line 2).</P>
<P><BR>&nbsp;&nbsp;&nbsp; STEP 1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The type of query is SELECT.</P>
<P><BR>QUERY PLAN FOR STATEMENT 3 (at line 3).</P>
<P><BR>&nbsp;&nbsp;&nbsp; STEP 1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The type of query is SELECT.</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM TABLE<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Test<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Nested iteration.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Using Clustered Index.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Index : PK_Test<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Forward scan.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Positioning by key.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Keys are:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c1&nbsp; ASC<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Using I/O Size 2 Kbytes for data pages.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; With LRU Buffer Replacement Strategy for data pages.</P>
<P>(1 row affected)<BR>&nbsp;c1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c3<BR>&nbsp;----------- ------------------------ --------------------<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 129.14 Hellen</P>
<P>(1 row affected)<BR>我们看到，sybase的执行计划会使用clustered index来读取数据。<BR><BR>下面，采用money类型来进行测试<BR>1&gt; declare @var_money money<BR>2&gt; select @var_money=2<BR>3&gt; select * from Test where <A href="mailto:c1=@var_money">c1=@var_money</A><BR>4&gt; go</P>
<P>QUERY PLAN FOR STATEMENT 1 (at line 1).</P>
<P><BR>&nbsp;&nbsp;&nbsp; STEP 1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The type of query is DECLARE.</P>
<P><BR>QUERY PLAN FOR STATEMENT 2 (at line 2).</P>
<P><BR>&nbsp;&nbsp;&nbsp; STEP 1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The type of query is SELECT.</P>
<P><BR>QUERY PLAN FOR STATEMENT 3 (at line 3).</P>
<P><BR>&nbsp;&nbsp;&nbsp; STEP 1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The type of query is SELECT.</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM TABLE<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Test<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Nested iteration.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Table Scan.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Forward scan.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Positioning at start of table.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Using I/O Size 2 Kbytes for data pages.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; With LRU Buffer Replacement Strategy for data pages.</P>
<P>(1 row affected)<BR>&nbsp;c1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c3<BR>&nbsp;----------- ------------------------ --------------------<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 129.14 Hellen</P>
<P>(1 row affected)<BR><BR>我们可以看到，sybase没有采用索引，而是采用了全表扫描。<BR><BR>实际上，Sybase并不是类型不一致就一定不会使用索引，而是有一个匹配原则，原则上是只要索引列的类型优先级高于搜索条件的数据类型，就会使用索引。<BR>这个优先级，可以通过查询系统表master.dbo.systypes.<BR>1&gt; select hierarchy,name from master.dbo.systypes<BR>2&gt; order by 1<BR>3&gt; go<BR>&nbsp;hierarchy name<BR>&nbsp;--------- ------------------------------<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 floatn<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2 float<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3 datetimn<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4 datetime<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5 real<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6 numericn<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7 numeric<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8 decimaln<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9 decimal<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10 moneyn<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 11 money<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12 smallmoney<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 13 smalldatetime<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14 intn<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 15 int<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16 smallint<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 17 tinyint<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 18 bit<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 19 univarchar<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 20 unichar<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 22 sysname<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 22 varchar<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 22 nvarchar<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 23 char<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 23 nchar<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 24 timestamp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 24 varbinary<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 25 binary<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 26 text<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 27 image<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 99 extended type<BR><BR><BR></P>
<P><BR>&nbsp;</P><img src ="http://www.cnblogs.com/enhydraboy/aggbug/36422.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47984/" target="_blank">《商业周刊》:Mozilla的志愿者开发模式被复制</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>msnlib中的MimeMessage.parse代码需要修改</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/08/02/29500.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Mon, 02 Aug 2004 09:03:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/08/02/29500.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/29500.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/08/02/29500.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/29500.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/29500.html</trackback:ping><description><![CDATA[msnlib源代码中MimeMessage的parse是通过<BR>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">BufferedReader&nbsp;br</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;BufferedReader(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;StringReader(raw));<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top>addProperty(&nbsp;br.readLine());&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;MIME-Version</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addProperty(&nbsp;br.readLine());&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;Content-Type<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN></DIV></DIV>来获得每一行的内容，但是发现br.readline是以\r(0X0A),\n(0X0D)中的任何一个字符即认为是行结束符。<BR>这样，在获取48字节头的时候，如果字节内容正好包括0D的时候，就会发生截取出来的头少于48个字节而引起indexbound错误。<BR>因此，修改如下：<BR>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">package&nbsp;rath.msnm.msg;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top>import&nbsp;java.io.</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">;<BR><IMG id=Codehighlighter1_42_188_Open_Image onclick="this.style.display='none'; Codehighlighter1_42_188_Open_Text.style.display='none'; Codehighlighter1_42_188_Closed_Image.style.display='inline'; Codehighlighter1_42_188_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_42_188_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_42_188_Closed_Text.style.display='none'; Codehighlighter1_42_188_Open_Image.style.display='inline'; Codehighlighter1_42_188_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_42_188_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_42_188_Open_Text><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;&lt;p&gt;Title:&nbsp;&lt;/p&gt;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;&lt;p&gt;Description:&nbsp;&lt;/p&gt;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;&lt;p&gt;Copyright:&nbsp;Copyright&nbsp;(c)&nbsp;2004&lt;/p&gt;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;&lt;p&gt;Company:&nbsp;&lt;/p&gt;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;@author&nbsp;unascribed<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;@version&nbsp;1.0<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG id=Codehighlighter1_253_1155_Open_Image onclick="this.style.display='none'; Codehighlighter1_253_1155_Open_Text.style.display='none'; Codehighlighter1_253_1155_Closed_Image.style.display='inline'; Codehighlighter1_253_1155_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_253_1155_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_253_1155_Closed_Text.style.display='none'; Codehighlighter1_253_1155_Open_Image.style.display='inline'; Codehighlighter1_253_1155_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;MimeMessageBufferedReader&nbsp;extends&nbsp;BufferedReader&nbsp;</SPAN><SPAN id=Codehighlighter1_253_1155_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_253_1155_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;String&nbsp;charcode;<BR><IMG id=Codehighlighter1_344_392_Open_Image onclick="this.style.display='none'; Codehighlighter1_344_392_Open_Text.style.display='none'; Codehighlighter1_344_392_Closed_Image.style.display='inline'; Codehighlighter1_344_392_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_344_392_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_344_392_Closed_Text.style.display='none'; Codehighlighter1_344_392_Open_Image.style.display='inline'; Codehighlighter1_344_392_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;MimeMessageBufferedReader(Reader&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">,String&nbsp;charcode)&nbsp;</SPAN><SPAN id=Codehighlighter1_344_392_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_344_392_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;super(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.charcode&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">charcode;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG id=Codehighlighter1_464_512_Open_Image onclick="this.style.display='none'; Codehighlighter1_464_512_Open_Text.style.display='none'; Codehighlighter1_464_512_Closed_Image.style.display='inline'; Codehighlighter1_464_512_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_464_512_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_464_512_Closed_Text.style.display='none'; Codehighlighter1_464_512_Open_Image.style.display='inline'; Codehighlighter1_464_512_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;MimeMessageBufferedReader(Reader&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;sz,String&nbsp;charcode)&nbsp;</SPAN><SPAN id=Codehighlighter1_464_512_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_464_512_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;super(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">,sz);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.charcode</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">charcode;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;String&nbsp;readLine()<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws&nbsp;IOException<BR><IMG id=Codehighlighter1_579_1153_Open_Image onclick="this.style.display='none'; Codehighlighter1_579_1153_Open_Text.style.display='none'; Codehighlighter1_579_1153_Closed_Image.style.display='inline'; Codehighlighter1_579_1153_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_579_1153_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_579_1153_Closed_Text.style.display='none'; Codehighlighter1_579_1153_Open_Image.style.display='inline'; Codehighlighter1_579_1153_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_579_1153_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_579_1153_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CharArrayWriter&nbsp;caw</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;CharArrayWriter(</SPAN><SPAN style="COLOR: #000000">6</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ByteArrayOutputStream&nbsp;bo</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;ByteArrayOutputStream();<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;c</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.read();<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(c</SPAN><SPAN style="COLOR: #000000">==-</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">)<BR><IMG id=Codehighlighter1_729_754_Open_Image onclick="this.style.display='none'; Codehighlighter1_729_754_Open_Text.style.display='none'; Codehighlighter1_729_754_Closed_Image.style.display='inline'; Codehighlighter1_729_754_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_729_754_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_729_754_Closed_Text.style.display='none'; Codehighlighter1_729_754_Open_Image.style.display='inline'; Codehighlighter1_729_754_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_729_754_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_729_754_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG id=Codehighlighter1_773_1099_Open_Image onclick="this.style.display='none'; Codehighlighter1_773_1099_Open_Text.style.display='none'; Codehighlighter1_773_1099_Closed_Image.style.display='inline'; Codehighlighter1_773_1099_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_773_1099_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_773_1099_Closed_Text.style.display='none'; Codehighlighter1_773_1099_Open_Image.style.display='inline'; Codehighlighter1_773_1099_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">while</SPAN><SPAN style="COLOR: #000000">(c</SPAN><SPAN style="COLOR: #000000">!=-</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_773_1099_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_773_1099_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG id=Codehighlighter1_790_931_Open_Image onclick="this.style.display='none'; Codehighlighter1_790_931_Open_Text.style.display='none'; Codehighlighter1_790_931_Closed_Image.style.display='inline'; Codehighlighter1_790_931_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_790_931_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_790_931_Closed_Text.style.display='none'; Codehighlighter1_790_931_Open_Image.style.display='inline'; Codehighlighter1_790_931_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(c</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">13</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_790_931_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_790_931_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;d</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.read();<BR><IMG id=Codehighlighter1_836_863_Open_Image onclick="this.style.display='none'; Codehighlighter1_836_863_Open_Text.style.display='none'; Codehighlighter1_836_863_Closed_Image.style.display='inline'; Codehighlighter1_836_863_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_836_863_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_836_863_Closed_Text.style.display='none'; Codehighlighter1_836_863_Open_Image.style.display='inline'; Codehighlighter1_836_863_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(d</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">10</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_836_863_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_836_863_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">break</SPAN><SPAN style="COLOR: #000000">;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #0000ff">else</SPAN><SPAN style="COLOR: #000000"><BR><IMG id=Codehighlighter1_877_923_Open_Image onclick="this.style.display='none'; Codehighlighter1_877_923_Open_Text.style.display='none'; Codehighlighter1_877_923_Closed_Image.style.display='inline'; Codehighlighter1_877_923_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_877_923_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_877_923_Closed_Text.style.display='none'; Codehighlighter1_877_923_Open_Image.style.display='inline'; Codehighlighter1_877_923_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_877_923_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_877_923_Open_Text><SPAN style="COLOR: #000000">{caw.write(c);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;caw.write(d);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG id=Codehighlighter1_936_966_Open_Image onclick="this.style.display='none'; Codehighlighter1_936_966_Open_Text.style.display='none'; Codehighlighter1_936_966_Closed_Image.style.display='inline'; Codehighlighter1_936_966_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_936_966_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_936_966_Closed_Text.style.display='none'; Codehighlighter1_936_966_Open_Image.style.display='inline'; Codehighlighter1_936_966_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #0000ff">else</SPAN><SPAN id=Codehighlighter1_936_966_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_936_966_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;caw.write(c);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;bt</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;String(caw.toCharArray()).getBytes(charcode);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bo.write(bt);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;caw.reset();<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.read();<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;String(bo.toByteArray(),charcode);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV></DIV><BR><SPAN id=Codehighlighter1_50_180_Open_Text></SPAN>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;parse(&nbsp;String&nbsp;raw&nbsp;)&nbsp;throws&nbsp;Exception<BR><IMG id=Codehighlighter1_50_187_Open_Image onclick="this.style.display='none'; Codehighlighter1_50_187_Open_Text.style.display='none'; Codehighlighter1_50_187_Closed_Image.style.display='inline'; Codehighlighter1_50_187_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_50_187_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_50_187_Closed_Text.style.display='none'; Codehighlighter1_50_187_Open_Image.style.display='inline'; Codehighlighter1_50_187_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_50_187_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_50_187_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MimeMessageBufferedReader&nbsp;br&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;MimeMessageBufferedReader(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;StringReader(raw),rath.msnm.msnmConstant.getCharacterCode());<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><IMG src="http://www.cnblogs.com/images/dot.gif"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV></DIV><BR><img src ="http://www.cnblogs.com/enhydraboy/aggbug/29500.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47977/" target="_blank">Mono 的Virtual PC 虚拟机</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>我的MSN机器人终于有了自己的头像</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/07/08/22341.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Thu, 08 Jul 2004 02:50:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/07/08/22341.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/22341.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/07/08/22341.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/22341.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/22341.html</trackback:ping><description><![CDATA[总结，以免以后忘记。<IMG src="http://www.cnblogs.com/Emoticons/tongue_smile.gif"><BR>1 要用ILN设置自己的头像信息，头像信息是用一个&lt;MSNOBJECT&gt;来表示的<BR>2 当RC发现了以后（往往是和你建立对话Session的时候），会向你发送一个P2PMSGR的INVITE消息<BR>3 SC在收到INVITE后，要回应一个INVITE ACKnowledge，并且再发送一个MSNLIP/1.0 200 OK的消息。<BR>4 RC收到SC的MSNLIP/1.0 200 OK，会回应一个200 ok ACKnowledge消息。<BR>5 SC收到来自RC的&nbsp;200 ok ACKnowledge消息,就可以开始发送头像内容的消息了。首先，要发送一个Data prep消息，提供sessionid,baseid内容。然后，要把图片文件按照1202字节来拆分。不必等待RC回应Data prep acknowledge消息。<BR>6 RC接收到Data prep后，会回应一个Data prep acknowledge消息，完图片内容后，会回应一个bye消息。<BR>7 SC回答一个类型是0x40的消息（I receive byte message）。<BR><BR>2到7就是发送头像信息的p2p协议的过程。都是由SS(Switchboard server)作为Agent的。我的msn都是运行在内网的缘故，不清楚如果有公网ip的话，是不是就没有SS的事，不过，据我估计，msn的发送头像是必须要通过SS的。<BR><BR>
<img src="http://www.msning.com/bbs/uploads/30/post-7510-1091072177.png"><img src ="http://www.cnblogs.com/enhydraboy/aggbug/22341.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47970/" target="_blank">19岁天才黑客发布首个iPhone 3GS破解软件</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>Field6的类型说明</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/07/07/22056.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Wed, 07 Jul 2004 07:25:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/07/07/22056.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/22056.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/07/07/22056.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/22056.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/22056.html</trackback:ping><description><![CDATA[Field6的类型说明：<BR>0x00 00 00 00 00 No flags <BR>0x01 01 00 00 00 Unkown <BR>0x02 02 00 00 00 Acknowledgement <BR><B>0x04 04 00 00 00 Waiting for a reply </B><BR>0x08 08 00 00 00 Error (binairy level?) <BR>0x10 10 00 00 00 Unkown <BR>0x20 20 00 00 00 Data for DP/CE <BR>0x40 40 00 00 00 Bye ack (he who got BYE) <BR>0x80 80 00 00 00 Bye ack (he who sent BYE) <BR>0x1000030 30 00 00 01 Data for FT <!--QuoteEnd--><img src ="http://www.cnblogs.com/enhydraboy/aggbug/22056.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47969/" target="_blank">新浪邮箱大本营粉墨登场！Sina.cn开放注册</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>MSN协议中关于Send DP的研究</title><link>http://www.cnblogs.com/enhydraboy/archive/2004/06/29/19391.html</link><dc:creator>Enhydraboy</dc:creator><author>Enhydraboy</author><pubDate>Tue, 29 Jun 2004 01:03:00 GMT</pubDate><guid>http://www.cnblogs.com/enhydraboy/archive/2004/06/29/19391.html</guid><wfw:comment>http://www.cnblogs.com/enhydraboy/comments/19391.html</wfw:comment><comments>http://www.cnblogs.com/enhydraboy/archive/2004/06/29/19391.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/enhydraboy/comments/commentRss/19391.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/enhydraboy/services/trackbacks/19391.html</trackback:ping><description><![CDATA[<P>MSN6中，可以定义自己的头像。那么自己做的机器人其实也可以显示头像。jmsn没有提供这个特性。<BR>只能自己修改代码了。<BR>关键是协议。我跟踪了msn的通讯协议，发现，首先，你要向服务器申明你的头像信息。这个信息是在&lt;<A href="http://www.cnblogs.com/enhydraboy/archive/2004/06/23/17996.aspx">msnobj</a>&gt;实体内实现的。</P>
<P>对方的msn messenger会发现你有头像信息，会通过SS向你发送msn p2p的invite msnmsng请求。然后你回应，传送头像二进制流。就是一个p2p通讯的过程。<BR>目前，还在研究中。发现，每个p2p消息中，都包含了一个48字节的一个头。至于是什么内容，今天刚刚得到一位朋友的指点。<BR>1.&nbsp; This is a DWORD and contains the SessionID, which is zero when the Clients are negotiating&nbsp; about the session. This field is only used when actually sending data (DP&#8217;s, CE&#8217;s etc). The&nbsp; value of this field in Ink messages is always 64!<BR><BR>2.&nbsp; This field is again a DWord, which identifies the message (the so called Base Identifier). In&nbsp; Ink this field has the same value in all messages. In other transfers this value will range&nbsp; from BaseID - 3 to BaseID + 3. The number can range between 4 and 4,25 billion <BR>(4 ~ 4 250 000 000).<BR><BR>3. This field is a QWord, and contains the offset of the data you are sending, if the size is over&nbsp; 1202 bytes. For example, if you send 2404 bytes, the first message would contain the value&nbsp; zero (seeing you haven&#8217;t send something yet), and the second message would have the value&nbsp; 1202, because you just send 1202 bytes.<BR><BR>4. This field is once again a QWord, and contains the size of total data being send in this total. If there is no data you can leave this to zero and often the Flag field (field 6) should be set to the value of 2.<BR><BR>5. This field is a DWord and contains the size of the data being send in this message. Note that &#8220;data&#8221; does NOT include the headers, only the data send between the Header and the Footer! For example, when sending a 5000 bytes file, field four would contain the value of 5000, and this field would contain only 1202, because you can&#8217;t transfer more than 1202 bytes in one message. This field and the fourth field are equal to each other when you aren&#8217;t sending actually file data (or Ink data in our case).<BR><BR><BR>6. The sixth field, DWord, is the Flag field. The value of this field is 0 when no Flags are&nbsp; specified. It will be 2 when the message is a reply to another message, 8 if there&#8217;s an error in&nbsp; the binary fields of the received packet. The Flag will contain the value 32 if you are sending&nbsp; DP or CE data, and the value 16777264 when it&#8217;s data of a file transfer. <BR><BR>7. This DWord contains the BaseID of the previous received message, *if* the SessionID is not&nbsp; included in the binary headers, nor in the data sent in this message. Seeing the SessionID is&nbsp; specified when sending Ink you can just put a random number here (1 ~ 1 000 000 000&nbsp; would be good enough).<BR><BR>8. This field (A DWord) contains the value of the seventh field of the previous received message.<BR><BR>9. The ninth field is a QWord, and contains the value of the fourth field of the previous received&nbsp; message.<BR><BR>10. This DWord comes AFTER the data, and therefore it&#8217;s the Footer. This DWord contains the&nbsp; value zero when there is no actual file data (DP&#8217;s, CE&#8217;s etc) being send. It has the value 1&nbsp; hen you send DP&#8217;s, CE&#8217;s or other data, and it has the value 3 when sending Ink.<!--QuoteEnd--></P><img src ="http://www.cnblogs.com/enhydraboy/aggbug/19391.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47968/" target="_blank">IE市场份额首次跌破60%</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item></channel></rss>