2011年3月29日火曜日

mavenのレポジトリをGoogle code上に作る

MavenのレポジトリをGoogle code上に作る方法。 ここに書いてあった。ためしてないけど、パスワードをベタでファイルに書くのか。。Google CodeのアカウントはGoogleのアカウントだから、これはちょっといやだなあ。

2011年3月24日木曜日

ラベル付けとそれを使ったmount

SATAとPATA両方あるマシンでブートドライブじゃないほうのドライブが/dev/sdb になったり /dev/sdaになったり安定しない。ラベルをつければいいと言うことなのでつけてみた。e2labelコマンドでラベルをつける
$ e2label /dev/sdb1 /repo
/etc/fstab でそれを参照。
LABEL=/repo   /repo  ext2 defaults  1 2

2011年3月23日水曜日

gnome ディレクトリ名を英語表記に。

ubuntu インストールするたびにやるので。「デスクトップ」などの日本語ディレクトリを英語にするおまじない。
 LANG=C xdg-user-dirs-gtk-update

2011年3月21日月曜日

sbt

Scalaの開発環境、Eclipseがいつまでたっても安定してくれないようなので、sbtというのを使ってみる。統合環境ではなく、ビルドとテストを補助する環境で、ここにある。こちらこちらの記事を参考に試してみる。

環境をつくる

空のディレクトリを作って、その中で sbtとうつ。新しいプロジェクトを作るか聞いてくるのでsとするといろいろできる。
$ sbt
Project does not exist, create new project? (y/N/s) s
Getting Scala 2.7.7 ...
:: retrieving :: org.scala-tools.sbt#boot-scala
 confs: [default]
 2 artifacts copied, 0 already retrieved (9911kB/281ms)
Getting org.scala-tools.sbt sbt_2.7.7 0.7.4 ...
:: retrieving :: org.scala-tools.sbt#boot-app
 confs: [default]
 15 artifacts copied, 0 already retrieved (4096kB/385ms)

コンパイルと実行

プログラムは src/main/scala/ 以下に書く。書いて sbt内のプロンプトで、run とやるとコンパイルして実行してくれる。compileだけならコンパイルまで。更新のあったファイルを自動的に検出して依存関係を見て(たぶん)コンパイルするようだ。 さらに ~run, ~compileとすると継続的にファイルを監視して実行してくれる。つまり、書き換えてセーブすると、コンパイルしてくれるてことだ。当然不完全な状況でセーブするとコンパイルエラーがでる。気持ち悪いが馴れか。

Scalaのバージョンを変える

sbt は複数のScalaのバージョンに対応していて、コンパイラを管理してくれる。複数のバージョンに対してクロスビルドすることも可能。ターゲットを変えるには次のようにする。複数指定することも可能らしい。
> set.scala.versions 2.8.1
> reload
こうすると2.8.1のコンパイラをとりに行ってくれる。べんりー。

ライブラリの導入

プロジェクトを設定するとで自動的にmavenのライブラリを取ってきてくれたりする模様。project/以下にbuildというディレクトリを作って、そこに、scalaファイルを書くと、それを自動的にプロジェクトの定義として読むと言う仕掛けらしい。
import sbt._

class MyProject(info: ProjectInfo) extends DefaultProject(info) {
  val scalaTest = "org.scalatest" % "scalatest" % "1.3"
}
で、reload, update とやる。
> reload
[info] Recompiling project definition...
[info]    Source analysis: 1 new/modified, 0 indirectly invalidated, 0 removed.
[info] Building project test 1.0 against Scala 2.8.1
[info]    using MyProject with sbt 0.7.4 and Scala 2.7.7
> update
[info] 
[info] == update ==
[info] downloading http://scala-tools.org/repo-releases/org/scalatest/scalatest/1.3/scalatest-1.3.jar ...
[info]  [SUCCESSFUL ] org.scalatest#scalatest;1.3!scalatest.jar (4751ms)
[info] :: retrieving :: test#test_2.8.1 [sync]
[info]  confs: [compile, runtime, test, provided, system, optional, sources, javadoc]
[info]  1 artifacts copied, 0 already retrieved (1755kB/116ms)
[info] == update ==
[success] Successful.
[info] 
[info] Total time: 8 s, completed Mar 21, 2011 10:41:05 PM
レポジトリから自動的にライブラリをダウンロードしている。すごいなー。

テスト

ScalaTestを入れたのでテストをすることができる。テストプログラムは、src/test/scala/ 以下に書く。 で、sbtのプロンプトからtestとやるとテストが実行されると。

2011年3月17日木曜日

gdata でpicasaを操作

People FInder の入力作業に協力しようとしたのだけど、未作業の写真をなかなか見つけられないので、コメント数が1以下の写真だけを調べるスクリプトを書いてみた。といっても、ここにあるスクリプトほぼそのままだが。
import gdata.photos.service
import gdata.media
import gdata.geo

email=xxxxx
password=xxxx

gd_client = gdata.photos.service.PhotosService()
gd_client.email = email
gd_client.password = password
gd_client.source = 'exampleCo-exampleApp-1'
gd_client.ProgrammaticLogin()

username="tohoku.anpi"

albums = gd_client.GetUserFeed(user=username)
for album in albums.entry:
  print 'title: %s, number of photos: %s, id: %s' % (album.title.text,
      album.numphotos.text, album.gphoto_id.text)
  photos = gd_client.GetFeed(
      '/data/feed/api/user/%s/albumid/%s?kind=photo' % (
          username, album.gphoto_id.text))
  for photo in photos.entry:
      comments = gd_client.GetFeed('/data/feed/api/user/%s/albumid/%s/photoid/%s?kind=comment&max-results=10' % (username, album.gphoto_id.text, photo.gphoto_id.text))
      if len(comments.entry) < 2:
          print 'Photo title:', photo.title.text, len(comments.entry)

2011年3月16日水曜日

Hadoop のHDFS上のファイルを読む

サイドファイルにObjectOutputStreamで書いたものはObjectInputStreamで読めばいい。 dirname 以下のfilterにひっかかるファイルからオブジェクトを読み出すのはこうする。
  Configuration conf = new Configuration();
  FileSystem fs = FileSystem.get(URI.create("hdfs://localhost:9000/"), conf);
  for (FileStatus status: fs.listStatus(new Path(dirname), filter)) {
   InputStream is = fs.open(status.getPath());
   ObjectInputStream ois = new ObjectInputStream(is); 
   Object o = ois.readObject();
   System.out.println(o);
  }
filter はこんな風に取得。filePrefix に指定した文字を含むファイルを選ぶ。この実装だとprefix になってないけど。
 static PathFilter getPathFilter(final String filePrefix){
  PathFilter filter = new PathFilter() {
   public boolean accept(Path path) {
    return path.getName().contains(filePrefix);
   }
  };
  return filter;
 }

普通に書き出したファイルの場合

サイドデータじゃなくて、普通にcontext.writeした場合は読み方が変わってくる。SequenceFile.Readerで読む。
  Configuration conf = new Configuration();

  FileSystem fs = FileSystem.get(URI.create("hdfs://localhost:9000/"), conf);
  for (FileStatus status: fs.listStatus(new Path(dirname), filter)) {
   SequenceFile.Reader reader = new SequenceFile.Reader(fs, status.getPath(), conf);
   Text key = new Text();
                        Text value = new Text();
   while (reader.next(key, value){
                               ....
   }
  }
この読み方は、ValueがWritableの時にしか使えない。Serializable の場合はつぎのようにする。 nextでkeyだけ読んで、getCurrentValueでvalueを読む。このときにconfにJavaSerializationを追加しておかないと、エラーになるので注意。
  Configuration conf = new Configuration();
  conf.set("io.serializations", 
    JavaSerialization.class.getName() + "," +
    WritableSerialization.class.getName());

  FileSystem fs = FileSystem.get(URI.create("hdfs://localhost:9000/"), conf);
  for (FileStatus status: fs.listStatus(new Path(dirname), filter)) {
   SequenceFile.Reader reader = new SequenceFile.Reader(fs, status.getPath(), conf);
   Text key = new Text();
   while (reader.next(key)){
    System.out.println(key.toString());
    ChlacTest.Result res = new ChlacTest.Result();
    res = (Result) reader.getCurrentValue(res);
    System.out.println(String.format("%d %d %f", res.rx, res.time_frame, res.alpha));
   }
  }

2011年3月14日月曜日

googleで地名から緯度経度を取得

$  curl "http://maps.google.com/maps/geo?q=千代田区外神田"
{
  "name": "千代田区外神田",
  "Status": {
    "code": 200,
    "request": "geocode"
  },
  "Placemark": [ {
    "id": "p1",
    "address": "Japan, Tokyo Chiyoda外神田",
    "AddressDetails": {
   "Accuracy" : 4,
   "Country" : {
      "AdministrativeArea" : {
         "AdministrativeAreaName" : "東京都",
         "Locality" : {
            "DependentLocality" : {
               "DependentLocalityName" : "外神田"
            },
            "LocalityName" : "千代田区"
         }
      },
      "CountryName" : "日本",
      "CountryNameCode" : "JP"
   }
},
    "ExtendedData": {
      "LatLonBox": {
        "north": 35.7100074,
        "south": 35.6918852,
        "east": 139.7856097,
        "west": 139.7215803
      }
    },
    "Point": {
      "coordinates": [ 139.7535951, 35.6940027, 0 ]
    }
  } ]
}

2011年3月11日金曜日

hadoop side effect file

hadoopではファイルを正式なアウトプットの他に作ることができる。 getWorkOutputPath を使う。ディレクトリは正式なアウトプットの出力先と同じなので注意。
 public static class R1 extends
 Reducer {
  public void reduce(Text key, Iterable values,
  Context context) throws IOException, InterruptedException {
   context.write(key, values.iterator().next());
   Path path = FileOutputFormat.getWorkOutputPath(context); 
   Path fpath = new Path(path, "sidefile" + key.toString());  
    OutputStream os = fpath.getFileSystem(context.getConfiguration()).create(fpath);
   PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));
   pw.println("hello");
   pw.flush();
   pw.close();
   os.close();
  }
 }

2011年3月9日水曜日

Hadoop job 管理

ps 相当
> hadoop job -list
kill
> hadoop job -kill xxxxxxxx

2011年3月8日火曜日

screen

設定

デフォルトだとC-aがエスケープなのだけど、emacsとコンフリクトするのでC-zに設定し直す。下記を~/.screenrc に。
escape ^z^z

デタッチ と アタッチ

C-z d でデタッチ。screen -ls で確認すると、セッションが見える。 >|| $ screen -ls There is a screen on: 6398.pts-11.xxxx (Detached) 1 Socket in /var/run/screen/S-xxxx. ||< screen -r でアタッチ。複数のセッションがある場合には先頭のpts番号(この場合は6398)を指定。

仮想画面

  • C-z c で仮想画面追加
  • C-z w で仮想画面のリストを最下段に表示
  • C-z 番号 でその番号の仮想画面に移動。
  • C-z space で順番に仮想画面を移動。
  • C-z n, C-z p で前後に移動。 nはspace と同じ。

コピーモード

screen ではスクロールをscreenが処理してるので端末のスクロールバーが使えない。面倒。 そのかわりコピーモードというのがあってそれで過去のログをみることができる。 C-z [ でコピーモードに入る。エスケープで抜ける。