RVMがアップデートできない

何気なくRVMをアップデートしようと思ったのだが、以下のエラーが発生した。
今、途方に暮れている中。

$ rvm get latest

Original installed RVM version:

rvm 1.5.2 by Wayne E. Seguin (wayneeseguin@gmail.com) [http://rvm.beginrescueend.com/]

rvm-<html>
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   165    0   165    0     0    333      0 --:--:-- --:--:-- --:--:--     0
ERROR:
.tar.gz downloaded does not match it's md5 checksum <html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/0.8.54</center>
</body>
./html>
    Aborting RVM Installation.

RVMのアップデート方法が変わってた

久しぶりにRVMをアップデートしようと思って、「rvm update」を実行してみたらエラーが出た。

$ rvm version

rvm 1.2.8 by Wayne E. Seguin (wayneeseguin@gmail.com) [http://rvm.beginrescueend.com/]

$ rvm update
ERROR: rvm update has been removed. See 'rvm get' and rvm 'rubygems' CLI API instead

どうやら「rvm update」は廃止されたらしい。
「rvm help get」で使い方を調べて、次のようにコマンドを実行するとアップデートできた。

$ rvm get latest
$ rvm reload
$ rvm version

rvm 1.5.2 by Wayne E. Seguin (wayneeseguin@gmail.com) [http://rvm.beginrescueend.com/]

0と1を次々返す方法

0と1を次々返す方法
Algorithm - 0と1を次々と返す簡単なお仕事
この記事を見て自分でもやってみる。

flipflop.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def flipflop(p=False):
    def ret():
        ret.p = not ret.p
        return ret.p
    ret.p = not p
    return ret

if __name__ == "__main__":
    f = flipflop()
    print f()
    print f()
    print f()
    print f()
    print f
$ python -V
Python 2.6.5

$ python flipflop.py
False
True
False
True
<function ret at 0xb7f6d0d4>

MongoDBのmap/reduceを試してみる。

以前(http://d.hatena.ne.jp/stog/20100531/1275317576)作成したコレクションをmap/reduceを使って"type"別に集計してみる。

コレクションの中身はこんな感じ。

$ mongo mytest
MongoDB shell version: 1.4.4
url: mytest
connecting to: mytest
type "help" for help
>
> db.members2.find()
{ "_id" : ObjectId("4c03c632b4742d2998000000"), "birthday" : 342057600, "type" : "human", "name" : "おがわ", "sex" : "M" }
{ "_id" : ObjectId("4c03c632b4742d2998000001"), "birthday" : 130550400, "type" : "human", "name" : "たかはし", "sex" : "F" }
{ "_id" : ObjectId("4c03c632b4742d2998000002"), "birthday" : 1042588800, "type" : "human", "name" : "たなか", "sex" : "M" }
{ "_id" : ObjectId("4c03c632b4742d2998000003"), "birthday" : -291600000, "type" : "human", "name" : "さとう", "sex" : "F" }
{ "_id" : ObjectId("4c03c632b4742d2998000004"), "birthday" : 1118102400, "type" : "dog", "name" : "ポチ", "sex" : "F" }
{ "_id" : ObjectId("4c03c632b4742d2998000005"), "birthday" : 807840000, "type" : "dog", "name" : "タロ", "sex" : "M" }
{ "_id" : ObjectId("4c03c632b4742d2998000006"), "birthday" : 1230076800, "type" : "cat", "name" : "タマ", "sex" : "F" }
{ "_id" : ObjectId("4c03c633b4742d2998000007"), "birthday" : 914544000, "type" : "cat", "name" : "ミケ", "sex" : "M" }
{ "_id" : ObjectId("4c03c633b4742d2998000008"), "birthday" : 0, "type" : "human", "name" : "John", "sex" : "M" }
{ "_id" : ObjectId("4c03c633b4742d2998000009"), "birthday" : -927676800, "type" : "human", "name" : "Michael", "sex" : "M" }
{ "_id" : ObjectId("4c03c633b4742d299800000a"), "birthday" : 927158400, "type" : "human", "name" : "Robert", "sex" : "M" }
{ "_id" : ObjectId("4c03c633b4742d299800000b"), "birthday" : 1259971200, "type" : "human", "name" : "David", "sex" : "M" }
{ "_id" : ObjectId("4c03c633b4742d299800000c"), "birthday" : -86400, "type" : "human", "name" : "James", "sex" : "M" }
{ "_id" : ObjectId("4c03c633b4742d299800000d"), "birthday" : 481939200, "type" : "human", "name" : "Mary", "sex" : "F" }
{ "_id" : ObjectId("4c03c633b4742d299800000e"), "birthday" : -448588800, "type" : "human", "name" : "Barbara", "sex" : "F" }
{ "_id" : ObjectId("4c03c633b4742d299800000f"), "birthday" : 979948800, "type" : "human", "name" : "Anne", "sex" : "F" }
{ "_id" : ObjectId("4c03c633b4742d2998000010"), "birthday" : -765849600, "type" : "human", "name" : "Maria", "sex" : "F" }
{ "_id" : ObjectId("4c03c633b4742d2998000011"), "birthday" : 249696000, "type" : "human", "name" : "Susan", "sex" : "F" }
>


まずは、mongodbの対話環境でやってみる。

$ mongo mytest
MongoDB shell version: 1.4.4
url: mytest
connecting to: mytest
type "help" for help
>
> var m = function(){ emit(this.type, 1); };
> var r = function(k, vals){ var sum=0; for(var i in vals) sum += vals[i]; return sum; };
> res = db.members2.mapReduce(m, r);
{
        "result" : "tmp.mr.mapreduce_1278193998_9",
        "timeMillis" : 39,
        "counts" : {
                "input" : 18,
                "emit" : 18,
                "output" : 3
        },
        "ok" : 1,
}
>
> db[res.result].find();
{ "_id" : "cat", "value" : 2 }
{ "_id" : "dog", "value" : 2 }
{ "_id" : "human", "value" : 14 }
>


今度は、Pythonで集計してみる。
test_mapReduce.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pymongo

conn = pymongo.Connection()
db = conn["mytest"]
coll = db["members2"]

# type別に集計するためのmap,reduceを定義。(javascriptコードを文字列で渡す)
m = pymongo.code.Code("function(){ emit(this.type, 1); }")
r = pymongo.code.Code("""
    function(k, vals){
        var sum = 0;
        for(var i in vals) sum += vals[i];
        return sum;
    }
""")

result = coll.map_reduce(m, r)
for doc in result.find():
    print doc

conn.disconnect()


以下、実行結果。

$ python test_mapReduce.py
{u'_id': u'cat', u'value': 2.0}
{u'_id': u'dog', u'value': 2.0}
{u'_id': u'human', u'value': 14.0}


参考:
http://www.mongodb.org/display/DOCSJP/MapReduce
http://api.mongodb.org/python/1.7%2B/examples/map_reduce.html

sqlite3-ruby 1.3.0のインストールが失敗する。

まず、環境はこんな感じ。

# cat /etc/redhat-release
CentOS release 5.4 (Final)

# rpm -aq | egrep '^sqlite'
sqlite-3.3.6-5
sqlite-devel-3.3.6-5

# ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-linux]

# gem -v
1.3.7


gemでsqlite3-rubyのインストールを試みるが以下のように失敗する。

# gem install sqlite3-ruby
Building native extensions.  This could take a while...
ERROR:  Error installing sqlite3-ruby:
        ERROR: Failed to build gem native extension.

/usr/local/bin/ruby extconf.rb
checking for sqlite3.h... yes
checking for sqlite3_libversion_number() in -lsqlite3... yes
checking for rb_proc_arity()... no
checking for sqlite3_column_database_name()... no
checking for sqlite3_enable_load_extension()... no
checking for sqlite3_load_extension()... no
creating Makefile

make
gcc -I. -I. -I/usr/local/lib/ruby/1.8/i686-linux -I. -I/usr/local/include -I/opt/local/include -I/usr/include  -D_FILE_OFFSET_BITS=64  -fPIC -g -O2  -O3 -Wall -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline  -c statement.c
statement.c: In function ‘initialize’:
statement.c:53: 警告: implicit declaration of function ‘sqlite3_prepare_v2’
statement.c: In function ‘bind_param’:
statement.c:261: error: ‘sqlite3_int64’ undeclared (first use in this function)
statement.c:261: error: (Each undeclared identifier is reported only once
statement.c:261: error: for each function it appears in.)
make: *** [statement.o] エラー 1


Gem files will remain installed in /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.3.0 for inspection.
Results logged to /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.3.0/ext/sqlite3/gem_make.out


sqlite3-ruby-1.3.0について小一時間ほどググったりして調べてみたが結局よく分からなかった。

ちなみに、sqlite3-rubyの1つ前のバージョン(1.2.5)であればインストールできた。

# gem search sqlite3-ruby -ra

*** REMOTE GEMS ***

sqlite3-ruby (1.3.0 ruby x86-mingw32 x86-mswin32-60, 1.2.5 ruby x86-mingw32 x86-mswin32, 1.2.4, 1.2.3 ruby mswin32 x86-mingw32, 1.2.2 ruby mswin32, 1.2.1 ruby mswin32, 1.2.0 ruby mswin32, 1.1.0 ruby mswin32, 1.0.1 ruby mswin32, 1.0.0 ruby mswin32, 0.9.0 ruby mswin32, 0.6.0, 0.5.0)
# gem install sqlite3-ruby -v '1.2.5'
Building native extensions.  This could take a while...
Successfully installed sqlite3-ruby-1.2.5
1 gem installed

curb(Rubyのcurlバインディング)で並列リクエストを試す

gemでインストールしたcurb(Rubycurlバインディング)のrdocを見ていたらCurl::Multiっていうクラスがあって、並列でURLリクエストできそうだったので試してみた。
※2010/06/15現在、WEB上に置いてあるcurbのオンラインドキュメントは結構古いようで(CURB_VERSION定数をみると"0.1.4"って書いてある)この頃はまだCurl::Multiが未実装っぽい。


直近でインストールしたcurbのライブラリバージョンは0.7.6

$ gem list curb -d

*** LOCAL GEMS ***

curb (0.7.6, 0.7.5)
    Authors: Ross Bamford, Todd A. Fisher
    Rubyforge: http://rubyforge.org/projects/curb
    Homepage: http://curb.rubyforge.org/
    Installed at (0.7.6): /usr/local/lib/ruby/gems/1.8
                 (0.7.5): /usr/local/lib/ruby/gems/1.8

    Ruby libcurl bindings


以下、テストスクリプト

test_curb.rb

#!/usr/bin/env ruby
# -*- coding:utf8 -*-
require 'rubygems'
require 'curb'

MyResponse = Struct.new(:url, :code, :body, :time)

responses = []
requests = [
  'http://dailynews.yahoo.co.jp/fc/rss.xml',
  'http://feeds.builder.japan.zdnet.com/builder/rss',
  'http://feeds.feedburner.com/hatena/b/hotentry',
  'http://japan.internet.com/rss/rdf/topics.rdf',
  'http://rss.rssad.jp/rss/wiredvision/feed/atom.xml',
  'http://rss.rssad.jp/hogehoge/hogehoge.xml', # 存在しないコンテンツのURL
  'http://hogehoge.example.com/hogehoge.xml'   # 存在しないホストのURL
]


puts "Start"
time_begin = Time.now

m = Curl::Multi.new
m.pipeline = true

requests.each do |url|
  m.add(
    Curl::Easy.new(url) do |curl|
      curl.follow_location = true
      curl.on_complete do |ch|
        responses << MyResponse.new(url, ch.response_code, ch.body_str, ch.total_time)
      end
    end
  )
end

m.perform do
  puts "idling... can do some work here, including add new requests"
end

responses.each do |res|
  puts res.url
  puts "  code = #{res.code}"
  puts "  body.size = #{res.body.size}"
  puts "  time = #{res.time}"
  puts '---'
end

puts "End time:#{Time.now - time_begin}"
puts


実行結果

$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-linux]

$ ruby test_curb.rb
Start
http://hogehoge.example.com/hogehoge.xml
  code = 0
  body.size = 0
  time = 0.0
---
http://rss.rssad.jp/hogehoge/hogehoge.xml
  code = 404
  body.size = 1509
  time = 0.020261
---
http://japan.internet.com/rss/rdf/topics.rdf
  code = 200
  body.size = 5714
  time = 0.026651
---
http://rss.rssad.jp/rss/wiredvision/feed/atom.xml
  code = 200
  body.size = 107973
  time = 0.044281
---
http://dailynews.yahoo.co.jp/fc/rss.xml
  code = 200
  body.size = 3465
  time = 0.046129
---
http://feeds.builder.japan.zdnet.com/builder/rss
  code = 200
  body.size = 44936
  time = 0.07544
---
http://feeds.feedburner.com/hatena/b/hotentry
  code = 200
  body.size = 100764
  time = 0.187272
---
End time:0.188435


curbが入ってない環境で(Ruby標準添付ライブラリだけで)同じようなことをやるならNet::HTTPとThreadを使って↓こんな感じか。多分。

test_thread.rb

#!/usr/bin/env ruby
# -*- coding:utf8 -*-
require 'uri'
require 'net/http'
Net::HTTP.version_1_2

MyResponse = Struct.new(:url, :code, :body, :time)

responses = []
requests = [
  'http://dailynews.yahoo.co.jp/fc/rss.xml',
  'http://feeds.builder.japan.zdnet.com/builder/rss',
  'http://feeds.feedburner.com/hatena/b/hotentry',
  'http://japan.internet.com/rss/rdf/topics.rdf',
  'http://rss.rssad.jp/rss/wiredvision/feed/atom.xml',
  'http://rss.rssad.jp/hogehoge/hogehoge.xml', # 存在しないコンテンツのURL
  'http://hogehoge.example.com/hogehoge.xml'   # 存在しないホストのURL
]


puts "Start"
time_begin = Time.now

threads = []
requests.each do |url|
  threads << Thread.new do
    time_b = Time.now
    begin
      res = Net::HTTP.get_response(URI.parse(url))
      code = res.code
      body = res.body
    rescue StandardError => e
      code = 0
      body = ''
    end
    responses << MyResponse.new(url, code, body, Time.now - time_b)
  end
end

threads.each do |t|
  t.join
end

responses.each do |res|
  puts res.url
  puts "  code = #{res.code}"
  puts "  body.size = #{res.body.size}"
  puts "  time = #{res.time}"
  puts '---'
end

puts "End time:#{Time.now - time_begin}"
puts

実行結果

$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-linux]

$ ruby test_thread.rb
Start
http://hogehoge.example.com/hogehoge.xml
  code = 0
  body.size = 0
  time = 0.001616
---
http://rss.rssad.jp/hogehoge/hogehoge.xml
  code = 404
  body.size = 1509
  time = 0.009805
---
http://japan.internet.com/rss/rdf/topics.rdf
  code = 200
  body.size = 5714
  time = 0.018922
---
http://dailynews.yahoo.co.jp/fc/rss.xml
  code = 200
  body.size = 3465
  time = 0.034052
---
http://rss.rssad.jp/rss/wiredvision/feed/atom.xml
  code = 200
  body.size = 107973
  time = 0.048426
---
http://feeds.builder.japan.zdnet.com/builder/rss
  code = 200
  body.size = 44936
  time = 0.102508
---
http://feeds.feedburner.com/hatena/b/hotentry
  code = 200
  body.size = 100764
  time = 0.189887
---
End time:0.196962