<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Yun Fu&#039;s Worklog &#187; programming</title>
	<atom:link href="http://fuyun.org/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://fuyun.org</link>
	<description>a system engineer&#039;s blog</description>
	<lastBuildDate>Mon, 02 Jan 2012 05:43:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Add Solr Spatial Search for Django Haystack</title>
		<link>http://fuyun.org/2011/11/add-solr-spatial-search-for-djang-haystack/</link>
		<comments>http://fuyun.org/2011/11/add-solr-spatial-search-for-djang-haystack/#comments</comments>
		<pubDate>Sun, 20 Nov 2011 06:21:49 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[system]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=364</guid>
		<description><![CDATA[Solr has native support of spatial search in the latest release Solr 3.4. However, Django Haystack does not support it yet. Some very helpful discussions about the issue can be found in the Haystack Google group. But, the patch discussed &#8230; <a href="http://fuyun.org/2011/11/add-solr-spatial-search-for-djang-haystack/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Solr has native support of <a href="http://wiki.apache.org/solr/SpatialSearch">spatial search</a> in the latest release Solr 3.4. However, <a href="http://haystacksearch.org/">Django Haystack</a> does not support it yet. Some very helpful discussions about the issue can be found in <a href="http://groups.google.com/group/django-haystack/browse_thread/thread/d0e23d45c0baa300/2298b6cf43389e18">the Haystack Google group</a>. But, <a href="http://friendpaste.com/6y88Nn4tCyRkBmxOOdg8He">the patch </a> discussed in the post is about <a href="http://www.searchworkings.org/blog/-/blogs/ssp-2-0-spatial-search-plugin-for-solr">JTeam&#8217;s SSP plugin</a>, not the Solr <a href="http://wiki.apache.org/solr/SpatialSearch"> native spatial search</a>. I followed the discussion and did similar changes to support this.</p>
<p>Basically. we need two changes.<br />
1. Add a new Solr field type <a href="http://wiki.apache.org/solr/SpatialSearch#LatLonType">LatLonType</a> into the schema generated by Haystack.<br />
2. Support search parameters for spatial queries such as <code>&#038;fq={!geofilt pt=45.15,-93.85 sfield=store d=5}</code>.</p>
<p>Here are the details of the changes:</p>
<p><strong>Step 1. Add LatLonType</strong></p>
<p>As described in <a href="http://wiki.apache.org/solr/SpatialSearch">spatial search wiki</a>, spatial fields should be defined as LatLonType. To support this, we need to add a type definition for LatLonType in Solr schema. Haystack generates schemas just as Django rendering HTML. It is based on a template file, <code>haystack/templates/search_configuration/solr.xml</code>. We need to add the following lines in section <code>"types"</code> and section <code>"fields"</code>.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;schema name=&quot;default&quot; version=&quot;1.1&quot;&gt;
  &lt;types&gt;
  ...
  &lt;!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. --&gt;
  &lt;fieldType name=&quot;location&quot; class=&quot;solr.LatLonType&quot; subFieldSuffix=&quot;_coordinate&quot;/&gt;
  &lt;fieldType name=&quot;tdouble&quot; class=&quot;solr.TrieDoubleField&quot; precisionStep=&quot;8&quot; omitNorms=&quot;true&quot; positionIncrementGap=&quot;0&quot;/&gt;
  &lt;/types&gt;
  &lt;fields&gt;
  ...
  &lt;!-- Type used to index the lat and lon components for the &quot;location&quot; FieldType --&gt;
  &lt;dynamicField name=&quot;*_coordinate&quot;  type=&quot;tdouble&quot; indexed=&quot;true&quot;  stored=&quot;false&quot;/&gt;
  ...
  &lt;/fields&gt;
</pre>
<p>Field type <code>"location"</code> needs <code>"*_coordinate"</code> fields to store latitude and longitude. Fields <code>"*_coordinate"</code> are of type <code>"tdouble"</code>. That&#8217;s why we need these 3 lines.</p>
<p>Correspondingly. we need to add a new search field type <code>LocationField</code> in <code>haystack/fields.py</code> as follows. We introduce two constructor parameters <code>model_lat_attr</code> and <code>model_lng_attr</code> to specify the names of latitude and longitude fields in the indexed Django model just as <a href="http://docs.haystacksearch.org/dev/searchfield_api.html#model-attr">model_attr</a> in SearchField.</p>
<pre class="brush: python; title: ; notranslate">
class LocationField(SearchField):
    field_type = 'location'

    def __init__(self, model_lat_attr=None, model_lng_attr=None, **kwargs):
        if kwargs.get('faceted') is True:
            raise SearchFieldError(&quot;%s can not be faceted.&quot; % self.__class__.__name__)
        super(LocationField, self).__init__(**kwargs)
        self.model_lat_attr = model_lat_attr
        self.model_lng_attr = model_lng_attr

    def prepare(self, obj):
        if self.model_lat_attr != None and self.model_lng_attr != None:
            lat = getattr(obj, self.model_lat_attr, None)
            lng = getattr(obj, self.model_lng_attr, None)
            if lat != None and lng != None:
                location = '%s,%s'%(obj.lat, obj.lng)
                return self.convert(location)
        return self.convert(super(LocationField, self).prepare(obj))

    def convert(self, value):
        if value is None:
            return None
        return unicode(value)
</pre>
<p>Notice the line <code>"field_type = 'location'"</code>. It tells Haystack that <code>LocationField</code> is of the location type we defined in the above schema. But to enable this, we also need to add the following line in <code>backends/solr_backend.py</code>. When executing <code>"manage.py build_solr_schema"</code>, the following method <code>build_schema</code> will be called.</p>
<pre class="brush: python; title: ; notranslate">
class SearchBackend(BaseSearchBackend):
    def build_schema(self, fields):
            ...
            elif field_class.field_type == 'location':
                field_data['type'] = 'location'
</pre>
<p>I don&#8217;t like this kind of hard coding change. It is not very object oriented. Ideally method <code>build_schema</code> should automatically use the <code>field_type</code> defined in <code>LocationField</code> and put it in schema. In that way, we do not need to change the Haystack code. Instead we can define the inherited <code>LocationField</code> in our own code. However, this is just the beginning. We have more hard coding changes in step 2.</p>
<p>With the above code changes, we can define search indices for Django models using LocationField. For example,</p>
<pre class="brush: python; title: ; notranslate">
class Store(models.Model):
    name = models.CharField(max_length=100)
    lat = models.DecimalField(max_digits=10, decimal_places=6)
    lng = models.DecimalField(max_digits=10, decimal_places=6)

class StoreIndex(RealTimeSearchIndex):
    name = CharField(model_attr='name', document=True)
    loc = LocationField(model_lat_attr='lat', model_lng_attr='lng')

site.register(Store, StoreIndex)
</pre>
<p><strong>Step 2. Add spatial search query support</strong></p>
<p><code>SearchQuerySet</code> is the user interface in Haystack to query Solr. To pass spatial search query parameters to Solr, we add a method <code>'spatial'</code> for <code>SearchQuerySet</code> in <code>haystack/query.py</code>.</p>
<pre class="brush: python; title: ; notranslate">
class SearchQuerySet(object):
    ...
    def spatial(self, **kwargs):
        &quot;&quot;&quot;Adds spatial search to the query&quot;&quot;&quot;
        clone = self._clone()
        clone.query.add_spatial(**kwargs)
        return clone
</pre>
<p><code>SearchQuerySet</code> is similar to Django <code>QuerySet</code>, mainly used for chaining queries such as method <code>spatial</code> we just added. The queries are accumulated and evaluated together later. Notice method <code>spatial</code> passes all parameters to method <code>add_spatial</code>, which is defined in <code>haystack/backends/__init__.py</code> as follows.</p>
<pre class="brush: python; title: ; notranslate">
from haystack.exceptions import SpatialError

class BaseSearchQuery(object):
    def __init__(self, using=DEFAULT_ALIAS):
        ...
        self.spatial_query = {}

    def add_spatial(self, **kwargs):
        if 'lat' not in kwargs or 'lng' not in kwargs or 'd' not in kwargs or 'sfield' not in kwargs:
            raise SpatialError(&quot;Spatial queries must contains args lat, lng, d and sfield&quot;)
        if 'filter' not in kwargs:
            kwargs['filter'] = 'geofilt'
        self.spatial_query.update(kwargs)

    def _clone(self, klass=None, using=None):
        ...
        clone.spatial_query = self.spatial_query.copy()
</pre>
<p>As you can see, to do a spatial search, we need to provide at least 4 parameters: <code>lat, lng, d, and sfield</code> as defined in the <a href="http://wiki.apache.org/solr/SpatialSearch">Solr wiki</a>. We can also specify what spatial filter to use, which can be either <code>geofilt</code> (default) or <code>bbox</code>. For example, the following query matches all items with latitude=45.15, longitude=-93.85, within 5 kilometers sorted by distance in ascending order. The filter in this example is <code>bbox</code>.</p>
<pre class="brush: python; title: ; notranslate">
SearchQuerySet().spatial(lat=45.15, lng=-93.85, d=3, sfield='loc', filter='bbox').order_by('geodist()')
</pre>
<p>To make this example work, we need to modify <code>haystack/backends/solr_backend.py</code> as follows, where we construct the Solr query finally.</p>
<pre class="brush: python; title: ; notranslate">
class SearchBackend(BaseSearchBackend):
    def search(self, query_string, sort_by=None, start_offset=0, end_offset=None,
               fields='', highlight=False, facets=None, date_facets=None, query_facets=None,
               narrow_queries=None, spelling_query=None,
               limit_to_registered_models=None, result_class=None,
               spatial_query=None, **kwargs):
        ...
        if spatial_query is not None:
            kwargs['pt'] = '%s,%s'%(spatial_query['lat'], spatial_query['lng'])
            kwargs['sfield'] = spatial_query['sfield']
            kwargs['d'] = spatial_query['d']
            if narrow_queries is None:
                narrow_queries = set()
            narrow_queries.add('{!%s}'% spatial_query['filter'])
        if narrow_queries is not None:
            kwargs['fq'] = list(narrow_queries)

class SearchQuery(BaseSearchQuery):
    def run(self, spelling_query=None):
        ...
        if self.spatial_query:
            kwargs['spatial_query'] = self.spatial_query
</pre>
<p>The final change we need to add is adding <code>SpatialError</code> in <code>haystack/exceptions.py</code>. The exception is used in the above code.</p>
<pre class="brush: python; title: ; notranslate">
class SpatialError(HaystackError):
    &quot;&quot;&quot;Raised when incorrect arguments have been provided for spatial.&quot;&quot;&quot;
    pass
</pre>
<p>All code changes in this blog can be found <a href="https://github.com/fuyun/django-haystack/tree/v1.2.5">here</a> on GitHub. It is based on Haystack v1.2.5.</p>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2011/11/add-solr-spatial-search-for-djang-haystack/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ruby MySQL adapter on Windows</title>
		<link>http://fuyun.org/2010/01/ruby-mysql-adapter-on-windows/</link>
		<comments>http://fuyun.org/2010/01/ruby-mysql-adapter-on-windows/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 10:05:24 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=241</guid>
		<description><![CDATA[It is very easy to install Ruby MySQL adapter using gem on Windows. But I found Ruby MySQL adapter does not work with MySQL 5.1 on my Windows box. When Ruby executed SQLs or Rails server got requests, I got &#8230; <a href="http://fuyun.org/2010/01/ruby-mysql-adapter-on-windows/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It is very easy to install Ruby MySQL adapter using gem on Windows.</p>
<pre class="brush: bash; title: ; notranslate">
gem install mysql
</pre>
<p>But I found Ruby MySQL adapter does not work with MySQL 5.1 on my Windows box. When Ruby executed SQLs or Rails server got requests, I got some errors like this</p>
<pre class="brush: bash; title: ; notranslate">
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/
connection_adapters/abstract_adapter.rb:39: [BUG] Segmentation fault
ruby 1.8.6 (2009-08-04) [i386-mingw32]

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
</pre>
<p>It seems the reason is that this version of mysql gem does not work with MySQL 5.1 lib. I saw some suggestions on Web to downgrade MySQL to 5.0 to solve the problem. However, I don&#8217;t want to downgrade MySQL. It turns out the solution is very simple. Download MySQL 5.0 noinstall version mysql-noinstall-5.0.89-win32.zip from <a href="http://dev.mysql.com/downloads/mysql/5.0.html">http://dev.mysql.com/downloads/mysql/5.0.html</a>. Extract libmysql.dll and copy it to C:\Ruby\bin. Then, the problem is solved. I am still running MySQL 5.1. But Ruby uses this MySQL 5.0 version dll.</p>
<p>My environment:  Ruby 1.8.6. Gem 1.3.5. MySQL gem version 2.8.1. Rails version is 2.3.5. Windows XP and MySQL 5.1.</p>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2010/01/ruby-mysql-adapter-on-windows/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Install MySQL for Python (MySQLdb) on Windows</title>
		<link>http://fuyun.org/2009/12/install-mysql-for-python-on-windows/</link>
		<comments>http://fuyun.org/2009/12/install-mysql-for-python-on-windows/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 09:38:58 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=231</guid>
		<description><![CDATA[It took me quite a while to figure out how to build and install MySQL for Python (MySQLdb) on Windows. I&#8217;d better write it down. There is no binary distribution of MySQLdb for Python 2.6 on Windows. I have to &#8230; <a href="http://fuyun.org/2009/12/install-mysql-for-python-on-windows/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It took me quite a while to figure out how to build and install <a href="http://sourceforge.net/projects/mysql-python/files/mysql-python/">MySQL for Python (MySQLdb)</a> on Windows. I&#8217;d better write it down.</p>
<p>There is no binary distribution of MySQLdb for Python 2.6 on Windows. I have to build it from the source. My environment is Windows XP. MySQL 5.1. Python 2.6 (windows version, not cygwin), and MySQL-python-1.2.3c1. Also, I have Microsoft Visual C++ 2008 Express Edition (Microsoft Visual Studio 9.0) installed, which is required to compile the C code in MySQL-python.</p>
<p>First of all, install <a href="http://pypi.python.org/pypi/setuptools">Python setuptools</a>, if you haven&#8217;t installed it. It is required in MySQL-python setup.py. I also added C:\Python26\Scripts into environment PATH, where easy_install is installed.</p>
<p>Then, make sure you have MySQL Developer Components installed. Download MySQL msi installer version, select &#8220;Developer Components&#8221; in Custom Setup. It will install C:\Program Files\MySQL\MySQL Server 5.1\include,  lib\debug and lib\opt  for you. They are not installed by default.</p>
<p>Uncompress MySQL-python-1.2.3c1.tar.gz into a directory. Open a command window (cmd), change to the directory.</p>
<p>Try to run,</p>
<p style="padding-left: 30px;"><em>setup.py build</em></p>
<p>I got this error in setup_windows.py:</p>
<p style="padding-left: 30px;"><em>in get_config<br />
serverKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, options['registry_key'])<br />
WindowsError: [Error 2] The system cannot find the file specified</em></p>
<p>So I edited site.cfg, changed the MySQL version from 5.0 to 5.1 (since I am using 5.1)</p>
<p style="padding-left: 30px;"><em>registry_key = SOFTWARE\MySQL AB\MySQL Server 5.1</em></p>
<p>You can use regedit to check which version you are using. It is specified at: HKEY_LOCAL_MACHINE/SOFTWARE/MySQL AB/MySQL Server 5.1.</p>
<p>Now try to build it again. I got this error:</p>
<p style="padding-left: 30px;"><em>build\temp.win32-2.6\Release\_mysql.pyd.manifest : general error c1010070: Failed to load and parse the manifest. The system cannot find  the file specified.<br />
error: command &#8216;mt.exe&#8217; failed with exit status 31</em></p>
<p>To fix this problem, go to C:\Python26\Lib\distutils, edit msvc9compiler.py, search for &#8216;MANIFESTFILE&#8217;, you will find the following line</p>
<p style="padding-left: 30px;"><em>ld_args.append(&#8216;/MANIFESTFILE:&#8217; + temp_manifest)</em></p>
<p>Then append the following line after the above line,</p>
<p style="padding-left: 30px;"><em>ld_args.append(&#8216;/MANIFEST&#8217;)</em></p>
<p>Then go back to run &#8220;setup.py build&#8221;, it will succeed. Finally, run</p>
<p style="padding-left: 30px;"><em>setup.py install</em></p>
<p>Test it in python</p>
<p style="padding-left: 30px;"><em>&gt;&gt;&gt; import MySQLdb<br />
&gt;&gt;&gt;</em></p>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2009/12/install-mysql-for-python-on-windows/feed/</wfw:commentRss>
		<slash:comments>104</slash:comments>
		</item>
		<item>
		<title>Cannot open libstdc++.so.5 on fedora 11</title>
		<link>http://fuyun.org/2009/11/cannot-open-libstdc-so-5-on-fedora-11/</link>
		<comments>http://fuyun.org/2009/11/cannot-open-libstdc-so-5-on-fedora-11/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 08:47:06 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=228</guid>
		<description><![CDATA[I just upgraded to fedora 11. When I installed java EE SDK, I got the following error > ./java_ee_sdk-5_07-linux-nojdk.bin ./java_ee_sdk-5_07-linux-nojdk.bin: error while loading shared libraries: libstdc++.so.5: cannot open shared object file: No such file or directory The default libstdc++ on &#8230; <a href="http://fuyun.org/2009/11/cannot-open-libstdc-so-5-on-fedora-11/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I just upgraded to fedora 11. When I installed java EE SDK, I got the following error</p>
<p>> ./java_ee_sdk-5_07-linux-nojdk.bin<br />
./java_ee_sdk-5_07-linux-nojdk.bin: error while loading shared libraries: libstdc++.so.5: cannot open shared object file: No such file or directory</p>
<p>The default libstdc++ on fedora is libstdc++.so.6 installed from libstdc++.i586. To solve the problem, install compat-libstdc++-33. For fedora 11, the package can be installed by</p>
<p>> yum install compat-libstdc++-33-3.2.3-66.i586</p>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2009/11/cannot-open-libstdc-so-5-on-fedora-11/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to read input files in maven junit</title>
		<link>http://fuyun.org/2009/11/how-to-read-input-files-in-maven-junit/</link>
		<comments>http://fuyun.org/2009/11/how-to-read-input-files-in-maven-junit/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 09:37:53 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=209</guid>
		<description><![CDATA[Sometimes we need to put unit test data into plain text files. For example, assume we want to test a parser using a json string as the test data. If we put the json string as a constant string in &#8230; <a href="http://fuyun.org/2009/11/how-to-read-input-files-in-maven-junit/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Sometimes we need to put unit test data into plain text files. For example, assume we want to test a parser using a json string as the test data. If we put the json string as a constant string in the java code, we end up with a lot of error-prone escaping characters. In that case, we may want to put the test string into a file as a resource and read the string from the file in junit.</p>
<p>In maven, we need to put the resource file in src/test/resources. Let me create a demo from scratch.</p>
<pre class="brush: plain; title: ; notranslate">
&gt; mvn archetype:create -DgroupId=org.fuyun -DartifactId=junitresdemo
&gt; find .
.
./junitresdemo
./junitresdemo/pom.xml
./junitresdemo/src
./junitresdemo/src/test
./junitresdemo/src/test/java
./junitresdemo/src/test/java/org
./junitresdemo/src/test/java/org/fuyun
./junitresdemo/src/test/java/org/fuyun/AppTest.java
./junitresdemo/src/main
./junitresdemo/src/main/java
./junitresdemo/src/main/java/org
./junitresdemo/src/main/java/org/fuyun
./junitresdemo/src/main/java/org/fuyun/App.java

&gt; cd junitresdemo
&gt; mkdir -p src/test/resources
&gt; vi src/test/resources/myres.txt
&gt; cat src/test/resources/myres.txt
test1=testdata
</pre>
<p>As you can see, I put my test data as a key-value pair in a property file. If your test data contains special characters such as escape char, you&#8217;d better handle file reading by yourself instead of using Properties as I am going to show.</p>
<p>Then I modify the automatically generated test code src/test/java/org/fuyun/AppTest.java as follows.</p>
<pre class="brush: java; title: ; notranslate">
package org.fuyun;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import java.io.InputStream;
import java.util.Properties;

public class AppTest extends TestCase {
    public AppTest( String testName ) {
        super( testName );
    }

    public static Test suite() {
        return new TestSuite( AppTest.class );
    }

    public void testApp() throws java.io.IOException {
        InputStream in =
            getClass().getClassLoader().getResourceAsStream(&quot;myres.txt&quot;);
        Properties p = new Properties();
        p.load(in);
        String mystr = p.getProperty(&quot;test1&quot;);
        assertEquals(&quot;testdata&quot;, mystr);
    }
}
</pre>
<p>To read the property file, we need to use getResourceAsStream. Actually this is why I want to write this blog. If you search on web, you may find that people talk about you can load the file using Class.getResourceAsStream(). So, I am supposed to write the line as</p>
<pre class="brush: java; title: ; notranslate">
        InputStream in = getClass().getResourceAsStream(&quot;myres.txt&quot;);
</pre>
<p>It can compile. But the test will fail. The InputStream variable <em>in</em> will be null, i.e., it cannot find myres.txt. Why? Why do we have to use the method defined in ClassLoader?</p>
<p>The difference between Class.getResourceAsStream and ClassLoader.getResourceAsStream is that Class.getResourceAsStream attempts to first resolve the file name by appending the package prefix (org/fuyun/) if the file name is not an absolute path, otherwise removes the leading &#8220;/&#8221; if the path is absolute. Then, it calls the ClassLoader&#8217;s getResourceAsStream to load the resolved file name. This is documented <a href="http://java.sun.com/j2se/1.5.0/docs/guide/lang/resources.html">here</a>.</p>
<p>For example, if I do the following hack, the test will pass temporarily.</p>
<pre class="brush: plain; title: ; notranslate">
&gt; mv target/test-classes/myres.txt target/test-classes/org/fuyun/.
&gt; mvn test
</pre>
<p>But to really fix it, we should revise the line by adding a leading &#8220;/&#8221; in the file name as follows.</p>
<pre class="brush: java; title: ; notranslate">
        InputStream in = getClass().getResourceAsStream(&quot;/myres.txt&quot;);
</pre>
<p>On the other hand, if you use ClassLoader.getResourceAsStream, the leading &#8220;/&#8221; will make it unable to find the file.</p>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2009/11/how-to-read-input-files-in-maven-junit/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>How to convert an integer to base64 in Python</title>
		<link>http://fuyun.org/2009/10/how-to-convert-an-integer-to-base64-in-python/</link>
		<comments>http://fuyun.org/2009/10/how-to-convert-an-integer-to-base64-in-python/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 09:36:35 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=175</guid>
		<description><![CDATA[I found  a bunch of solutions on web and noticed it may lead to entirely different results if you ignore a few assumptions. First of all, the input of base64 algorithm is an array of bytes, which is a string &#8230; <a href="http://fuyun.org/2009/10/how-to-convert-an-integer-to-base64-in-python/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I found  a bunch of solutions on web and noticed it may lead to entirely different results if you ignore a few assumptions.</p>
<p>First of all, the input of base64 algorithm is an array of bytes, which is a string in Python. Thus, before converting an integer to base64, you need to convert the integer to an array of bytes. To do so, you need to first decide the byte order: big endian or little endian. The best solution is using Python module struct. It can convert an integer to binary format in either byte order. Also, it can handle signed integers, etc.</p>
<p>I am using unsigned long long, which has 64 bits,  and little endian,  the simplest solution could be:</p>
<p>&gt;&gt;&gt;import struct</p>
<p>&gt;&gt;&gt; n = 12345</p>
<p>&gt;&gt;&gt; struct.pack(&#8216;&lt;Q&#8217;, n).encode(&#8220;base64&#8243;).strip()<br />
&#8216;OTAAAAAAAAA=&#8217;</p>
<p>However, the reason I need to use base64 here is that base64 is more compact than the decimal format of integers.  But the above example has a lot of A&#8217;s, which are caused by zeros padded in the unsigned long long. Also, I am using encode method provided by string to generate base64 in the above example. A better base64 support is module base64, which supports url safe version of base64.</p>
<p>The following example can solve these problems. Also, I remove the padding =&#8217;s here.</p>
<pre class="brush: python; title: ; notranslate">

import base64
import struct

def encode(n):
  data = struct.pack('&lt;Q', n).rstrip('\x00')
  if len(data)==0:
    data = '\x00'
  s = base64.urlsafe_b64encode(data).rstrip('=')
  return s

def decode(s):
  data = base64.urlsafe_b64decode(s + '==')
  n = struct.unpack('&lt;Q', data + '\x00'* (8-len(data)) )
  return n[0]
</pre>
<p>Notice that when stripping zeros, how to handle the integer zero itself? If we simply remove all tailing zeros, we will end up with an empty string here. Thus, I keep a byte zero if the integer is zero. In decode, we have to  pad zeros to variable data to 8 bytes for unpacking it as an unsigned long long. Notice the padding is in little endian order too.</p>
<p>Run some tests:</p>
<pre class="brush: plain; title: ; notranslate">
&gt;&gt;&gt; print encode(0)
AA

&gt;&gt;&gt; print decode('AA')
0

&gt;&gt;&gt; print encode(12345)
OTA

&gt;&gt;&gt; print decode('OTA')
12345
</pre>
<p>The code is for Python 2.5.</p>
<p>Finally, an interesting question. Is that true  any string constructed by  base64 characters is a valid base64 string?  See the following example,</p>
<pre class="brush: plain; title: ; notranslate">
&gt;&gt;&gt;print decode('100')
19927

&gt;&gt;&gt;print decode('101')
19927

&gt;&gt;&gt;print decode('102')
19927

&gt;&gt;&gt;print decode('103')
19927
</pre>
<p>The results are the same. Why? I would say only 100 is a valid base64 string. But python base64 decoder can tolerate the other 3. We know that 4 base64 chars (24 bits) represent 3 bytes. If we have only 3 base64 chars (18 bits) here, it can only represent 2 bytes (16 bits). Thus, the least significant 2 bits of the 3 chars (&#8220;101&#8243;-&#8221;102&#8243;) are ignored by base64 decoder.</p>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2009/10/how-to-convert-an-integer-to-base64-in-python/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>glassfish errors in netbeans</title>
		<link>http://fuyun.org/2009/10/glassfish-errors-in-netbeans/</link>
		<comments>http://fuyun.org/2009/10/glassfish-errors-in-netbeans/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 06:30:30 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=171</guid>
		<description><![CDATA[I don&#8217;t use IDE since I am used to editing in vim. I tried to adopt eclipse for java work several times. But I just could not keep using it. However, I recently started to see if I can adopt &#8230; <a href="http://fuyun.org/2009/10/glassfish-errors-in-netbeans/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t use IDE since I am used to editing in vim. I tried to adopt eclipse for java work several times. But I just could not keep using it. However, I recently started to see if I can adopt netbeans for java ee development. My environment is netbeans + glassfish + maven.</p>
<p>I experienced several problems in the beginning</p>
<p><strong>(1) NetBeans: No suitable Deployment Server is defined for the project or globally.</strong></p>
<p>I found the solution here: <a href="http://wiki.netbeans.org/JAXWSNB6Maven2GlassFishV2">http://wiki.netbeans.org/JAXWSNB6Maven2GlassFishV2</a></p>
<p>In Netbeans:</p>
<ol>
<li> Right-click the project and select <span style="font-family: monospace; white-space: pre;">Properties</span>. Navigate to the <span style="font-family: monospace; white-space: pre;">Run</span> tab.</li>
<li> In the Server field select GlassFish V2</li>
</ol>
<p><strong>(2) netbeans SEC5046: Audit: Authentication refused for [admin].</strong></p>
<p>Why do I see this error while I can still successfully deploy my application to glassfish from netbeans?</p>
<p>I found the solution here <a href="http://forums.java.net/jive/thread.jspa?threadID=35551">http://forums.java.net/jive/thread.jspa?threadID=35551</a></p>
<p>Just simply remove ~/.asadminpass</p>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2009/10/glassfish-errors-in-netbeans/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Connection Close in HttpClient</title>
		<link>http://fuyun.org/2009/09/connection-close-in-httpclient/</link>
		<comments>http://fuyun.org/2009/09/connection-close-in-httpclient/#comments</comments>
		<pubDate>Mon, 28 Sep 2009 07:26:53 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/wp/?p=81</guid>
		<description><![CDATA[I recently made a mistake using Java Jakarta Commons HttpClient. I decided to dig deeper into the issue. My code uses HttpClient to send HTTP requests to another machine. The load is very high. Over time, I often see exceptions &#8230; <a href="http://fuyun.org/2009/09/connection-close-in-httpclient/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I recently made a mistake using Java Jakarta Commons HttpClient. I decided to dig deeper into the issue.</p>
<p>My code uses HttpClient to send HTTP requests to another machine. The load is very high. Over time, I often see exceptions of &#8220;Too many open files&#8221; in logs. But the problem may auto recover. Using netstat, I found that there were a lot of tcp connections in CLOSE_WAIT state on the machine. So the problem is that the application did not close the connections.</p>
<p>My code is very similar to the example in <a href="http://hc.apache.org/httpclient-3.x/tutorial.html">HttpClient tutorial</a>.</p>
<pre class="brush: java; title: ; notranslate">
HttpClient client = new HttpClient();
GetMethod httpget = new GetMethod(&quot;http://www.whatever.com/&quot;);
try {
    client.executeMethod(httpget);
    ...
} finally {
    httpget.releaseConnection();
}
</pre>
<p>The code calls releaseConnection at the end as specified by the tutorial. But what does this method do?  To understand it, we need to understand what&#8217;s behind HttpClient object. Each HttpClient has an HttpConnectionManager responsible for maintaining connections. If we don&#8217;t pass an HttpConnectionManager to the constructor, HttpClient will initiate a SimpleHttpConnectionManager by default. SimpleHttpConnectionManager maintains a single connection and can only be used by a single thread. The main job of SimpleHttpConnectionManager is to keep the connection alive if the next request is to the same host. So the above releaseConnection call will not close the socket. If the next method to be executed is to a different host, it will close the prior connection at that time. Otherwise, it may reuse the connection.</p>
<p>The mistake I made is that I created  HttpClient objects on demand instead of reusing a single instance as documented <a href="http://hc.apache.org/httpclient-3.x/performance.html">here</a>. If the peer closes the socket first (by sending FIN), the connection will be in CLOSE_WAIT state on my side until my application layer closes the socket.  CLOSE_WAIT is a state that will not time out. (It is not TIME_WAIT.) It is application&#8217;s responsibility to close it. So how to force HttpClient to close the socket? Actually HttpConnectionManager interface does not define a way to close the socket. But SimpleHttpConnectionManager introduced shutdown method since 3.1. So one possible way to close the connection is as follows.</p>
<pre class="brush: java; title: ; notranslate">

HttpConnectionManager mgr = client.getHttpConnectionManager();
if (mgr instanceof SimpleHttpConnectionManager) {
    ((SimpleHttpConnectionManager)mgr).shutdown();
}
</pre>
<p>But why isn&#8217;t the problem deterministic?  Shouldn&#8217;t it never recover once the problem starts to happen? The magic is Java garbage collection. I reproduced the effect by forcing garbage collection. It will clean CLOSE_WAIT connections. But, to be accurate, JVM garbage collection does not handle socket closing by itself. It only frees memory. It is Socket object who closes sockets in finanize method as discussed <a href="http://forums.sun.com/thread.jspa?threadID=5326546">here</a>.</p>
<p>SimpleHttpConnectionManager is not thread safe. If you need to maintain a reusable HttpClient instance shared by multiple threads, you should use MultiThreadedHttpConnectionManager. For example,</p>
<pre class="brush: java; title: ; notranslate">

protected static HttpClient m_client = null;
 static {
    MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
    mgr.getParams().setDefaultMaxConnectionsPerHost(1000);
    mgr.getParams().setMaxTotalConnections(1000);
    m_client = new HttpClient(mgr);
 }
</pre>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2009/09/connection-close-in-httpclient/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Install pygtk</title>
		<link>http://fuyun.org/2009/09/%e4%b8%ad%e6%96%87%e7%9a%84%e6%b5%8b%e8%af%95/</link>
		<comments>http://fuyun.org/2009/09/%e4%b8%ad%e6%96%87%e7%9a%84%e6%b5%8b%e8%af%95/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 10:37:13 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/wp/?p=26</guid>
		<description><![CDATA[First, download gtk from http://www.gtk.org/download-windows.html I downloaded the all-in-one bundle http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.16/gtk+-bundle_2.16.6-20090911_win32.zip unzip the file to c:\gtk Then, I modify windows environment variable PATH by appending C:\gtk\bin to it.  (Right click &#8220;My Computer&#8221;, click &#8220;Properties&#8221;,   &#8220;Advanced&#8221;, &#8220;Environment Variables&#8221;, edit &#8220;path&#8221;) &#8230; <a href="http://fuyun.org/2009/09/%e4%b8%ad%e6%96%87%e7%9a%84%e6%b5%8b%e8%af%95/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>First, download gtk from</p>
<p><a href="pycairo-1.4.12-2.win32-py2.6.exe    pygtk-2.12.1-3.win32-py2.6.exe pygobject-2.14.2-2.win32-py2.6.exe">http://www.gtk.org/download-windows.html</a></p>
<p>I downloaded the all-in-one bundle</p>
<p><a href="http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.16/gtk+-bundle_2.16.6-20090911_win32.zip">http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.16/gtk+-bundle_2.16.6-20090911_win32.zip</a></p>
<p>unzip the file to c:\gtk</p>
<p>Then, I modify windows environment variable PATH by appending C:\gtk\bin to it.  (Right click &#8220;My Computer&#8221;, click &#8220;Properties&#8221;,   &#8220;Advanced&#8221;, &#8220;Environment Variables&#8221;, edit &#8220;path&#8221;)<br />
Go to <a href="http://www.pygtk.org/downloads.html">http://www.pygtk.org/downloads.html</a>, download the latest version pycairo, pygobject, pygtk. (I am using python 2.6).</p>
<p style="padding-left: 30px;">pycairo-1.4.12-2.win32-py2.6.exe</p>
<p style="padding-left: 30px;">pygobject-2.14.2-2.win32-py2.6.exe</p>
<p style="padding-left: 30px;">pygtk-2.12.1-3.win32-py2.6.exe</p>
<p>Run them one by one. The python installation on Windows is very easy, they can all find Python 2.6 from registration and automatically install the package to python lib directory.</p>
<p>Now I run python, I can do</p>
<pre class="brush: python; title: ; notranslate">

import gtk
</pre>
<p>If possible, I want to try <a href="http://code.google.com/p/pywebkitgtk/">http://code.google.com/p/pywebkitgtk/</a><br />
However, it seems quite troublesome to build it on windows:<br />
<a href="http://coding.derkeiler.com/Archive/Python/comp.lang.python/2008-10/msg01587.html">http://coding.derkeiler.com/Archive/Python/comp.lang.python/2008-10/msg01587.html</a><br />
<a href="http://coding.derkeiler.com/Archive/Python/comp.lang.python/2008-10/msg01723.html">http://coding.derkeiler.com/Archive/Python/comp.lang.python/2008-10/msg01723.html</a><br />
<a href="http://webkit.org/building/tools.html">http://webkit.org/building/tools.html</a><br />
<a href="http://www.python.org/doc/2.5.2/ext/win-cookbook.html">http://www.python.org/doc/2.5.2/ext/win-cookbook.html</a></p>
<p>related <a href="http://aruiz.typepad.com/siliconisland/2006/12/allinone_win32_.html">http://aruiz.typepad.com/siliconisland/2006/12/allinone_win32_.html</a></pre>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2009/09/%e4%b8%ad%e6%96%87%e7%9a%84%e6%b5%8b%e8%af%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chit &#8211; a useful ruby util</title>
		<link>http://fuyun.org/2009/08/chit-a-useful-ruby-util/</link>
		<comments>http://fuyun.org/2009/08/chit-a-useful-ruby-util/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 00:35:38 +0000</pubDate>
		<dc:creator>yfu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/wp/?p=20</guid>
		<description><![CDATA[I found an interesting ruby util &#8211; chit. it can retrieve cheat sheets from repositories powered by git! http://wiki.github.com/robin/chit/user-s-guide so far I haven&#8217;t found any especially useful cheat sheets there. but it looks interesting and promising. what&#8217;s the difference between &#8230; <a href="http://fuyun.org/2009/08/chit-a-useful-ruby-util/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I found an interesting ruby util &#8211; chit. it can retrieve cheat sheets from repositories powered by git!</p>
<p><a href="http://wiki.github.com/robin/chit/user-s-guide">http://wiki.github.com/robin/chit/user-s-guide</a></p>
<p>so far I haven&#8217;t found any especially useful cheat sheets there. but it looks interesting and promising.</p>
<p>what&#8217;s the difference between a cheat sheet and a man page? man pages spend too much effort to define options formally. cheat sheets give you examples directly without any explanation. that&#8217;s why i prefer cheat sheets.</p>
]]></content:encoded>
			<wfw:commentRss>http://fuyun.org/2009/08/chit-a-useful-ruby-util/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

