2012/05/02


BigQueryが正式版としてリリースされたようです。
Google、ビッグデータ分析サービス「BigQuery」を一般公開 - ITmedia ニュース

米Googleは11月14日(現地時間)、同社のクラウド上でいわゆる「ビッグデータ」を分析する企業向けサービス「Google BigQuery Service」のプレビュー版を公開したと発表した。正式版は有料になる見込みだが、現在は無料で利用できる。

http://www.itmedia.co.jp/news/articles/1111/15/news028.html
サンプルデータも幾つかある様で、githubのリポジトリ情報を格納している物もあったので試しにGo言語からクエリを発行して問い合わせてみた。 以下コード。 package main

import (
    "code.google.com/p/goauth2/oauth"
    "code.google.com/p/google-api-go-client/bigquery/v2"
    "encoding/gob"
    "fmt"
    "log"
    "net/http"
    "net/http/httptest"
    "net/url"
    "os"
    "os/exec"
    "path/filepath"
    "runtime"
    "time"
)

func osUserCacheDir() string {
    switch runtime.GOOS {
    case "darwin":
        return filepath.Join(os.Getenv("HOME"), "Library""Caches")
    case "linux""freebsd":
        return filepath.Join(os.Getenv("HOME"), ".cache")
    }
    log.Printf("TODO: osUserCacheDir on GOOS %q", runtime.GOOS)
    return "."
}

func tokenFromWeb(config *oauth.Config) *oauth.Token {
    ch := make(chan string)
    randState := fmt.Sprintf("st%d", time.Now())
    ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
        if req.URL.Path == "/favicon.ico" {
            http.Error(rw, ""404)
            return
        }
        if req.FormValue("state") != randState {
            log.Printf("State doesn't match: req = %#v", req)
            http.Error(rw, ""500)
            return
        }
        if code := req.FormValue("code"); code != "" {
            fmt.Fprintf(rw, "<h1>Success</h1>Authorized.")
            rw.(http.Flusher).Flush()
            ch <- code
            return
        }
        log.Printf("no code")
        http.Error(rw, ""500)
    }))
    defer ts.Close()

    config.RedirectURL = ts.URL
    authUrl := config.AuthCodeURL(randState)
    go openUrl(authUrl)
    log.Printf("Authorize this app at: %s", authUrl)
    code := <-ch
    log.Printf("Got code: %s", code)

    t := &oauth.Transport{
        Config:    config,
        Transport: http.DefaultTransport,
    }
    _, err := t.Exchange(code)
    if err != nil {
        log.Fatalf("Token exchange error: %v", err)
    }
    return t.Token
}

func openUrl(url string) {
    try := []string{"xdg-open""google-chrome""open"}
    for _, bin := range try {
        err := exec.Command(bin, url).Run()
        if err == nil {
            return
        }
    }
    log.Printf("Error opening URL in browser.")
}

func tokenCacheFile(config *oauth.Config) string {
    return filepath.Join(osUserCacheDir(), url.QueryEscape(
        fmt.Sprintf("go-api-demo-%s-%s-%s", config.ClientId, config.ClientSecret, config.Scope)))
}

func tokenFromFile(file string) (*oauth.Token, error) {
    f, err := os.Open(file)
    if err != nil {
        return nil, err
    }
    t := new(oauth.Token)
    err = gob.NewDecoder(f).Decode(t)
    return t, err
}

func saveToken(file string, token *oauth.Token) {
    f, err := os.Create(file)
    if err != nil {
        log.Printf("Warning: failed to cache oauth token: %v", err)
        return
    }
    defer f.Close()
    gob.NewEncoder(f).Encode(token)
}

func getOAuthClient(config *oauth.Config) *http.Client {
    cacheFile := tokenCacheFile(config)
    token, err := tokenFromFile(cacheFile)
    if err != nil {
        token = tokenFromWeb(config)
        saveToken(cacheFile, token)
    } else {
        log.Printf("Using cached token %#v from %q", token, cacheFile)
    }

    t := &oauth.Transport{
        Token:     token,
        Config:    config,
        Transport: http.DefaultTransport,
    }
    return t.Client()
}

func main() {

    var config = &oauth.Config{
        ClientId:     "XXXXXXXXXXXXX.apps.googleusercontent.com",
        ClientSecret: "YYYYYYYYYYYYYYYYYYYYYYYY",
        Scope:        bigquery.BigqueryScope,
        AuthURL:      "https://accounts.google.com/o/oauth2/auth",
        TokenURL:     "https://accounts.google.com/o/oauth2/token",
    }

    bigqueryService, err := bigquery.New(getOAuthClient(config))
    if err == nil {
        table, err := bigqueryService.Jobs.Query("XXXXXXXXXXXXX", &bigquery.QueryRequest {
            Query: "SELECT repository_description FROM [publicdata:samples.github_timeline] where repository_url = 'https://github.com/mattn/growl-for-linux'",
        }).Do()
        if err == nil {
            for _, row := range table.Rows {
                for _, f := range row.F {
                    println(f.V)
                }
            }
        }
    }
}
XXXXXXXXXXXXX にはプロジェクトIDを(ClientIDの一部になってるみたい)、YYYYYYYYYYYYYYYYYYYYYYYY には ClientSecret を埋めて実行して下さい。発行しているクエリは以下。 SELECT repository_description FROM [publicdata:samples.github_timeline] where repository_url = 'https://github.com/mattn/growl-for-linux'
これを実行すると以下のデータが得られた。 Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
実行はそれほど速くありませんでした。巨大なデータをオンラインで扱えるインフラとしては面白いかなーと思った。
ただ最近の API は OAuth な物が多く、実行するにはアクセストークンが必要になり、アクセストークンを得るにはブラウザを起動する必要がある。今回 Go言語のdatabase/sqlドライバの一つに加えようと思ってけどちょっと難しいかも。どっちかっていうとユーザ単位にアクセストークンを取らせる様なコンシューマサービス向けなのかな。
Posted at by



2012/04/29


Ubuntu 12.04 をインストールしたのですが、vimがコンパイル出来なくておかしいなと思ってたらどうやらlibncurses-devが/usr/lib/の下にインストールされていないのが問題の様で...
dpkg -L libncurses5-dev したら /usr/lib/i386-linux-gnu/libncurses.a こんな所に入ってた。って事で LDFLAGS=-L/usr/lib/i386-linux-gnu ./configure すればok
Posted at by



2012/04/27


Vim使ってる人の多くはマウスを触らずキーボードだけで操作する人が多いかと思います。僕もその一人でして、Windows使っていてもマウスは殆ど触りません。 ウィンドウを操作する場合は
目的キー
最大化 ALT + Space & x
ALTキーとスペースキー押した後で x
元のサイズに戻す ALT + Space & r
ALTキーとスペースキー押した後で r
ウィンドウを閉じる ALT + F4
ALTキーとF4
ただし複数のウィンドウを扱うアプリケーションでは CTRLキーとW
こんな感じに。普段コマンドプロンプトで生活しているので
目的キー
コピー ALT + Space & ek
ALTキーとスペースキー押した後で ek
カーソルキーで移動し、シフトキーとカーソルキーで範囲を広げます。選択し終わったらエンターキー
元のサイズに戻す ALT + Space & ep
ALTキーとスペースキー押した後で ep
UNIX系ツールとこういった操作を覚えれば誰でもコマンドプロンプトで生活出来ます。

今日はそんな話じゃなくて、普段Vimを使っていると色んな事をVimから実行したくなってきます。
  • エクスプローラ起動
  • ブラウザ起動
  • TwitVim起動
  • FavStarなんて見ようかしら
その都度、キーマッピングを書いても良いのですが、その度にキーアサインしてるとキーが幾つあっても足りません。あと忘れる事が多い。
そこでランチャー書いてみました。普段リポジトリ内のファイルにアクセスする際、パスが遠いと面倒なので CtrlP(以前書いた紹介記事はこちら) というプラグインを使っているのですが、このプラグインには unite.vim の様に拡張を書ける仕組みがあるのです。 オフィシャルからもバッファや最近触ったファイル(MRU)を選択出来るエクステンションが提供されているのですが、皆さんに紹介の意味も込めて今日適当に何個か作ってみました。
mattn/ctrlp-mark - GitHub
https://github.com/mattn/ctrlp-mark
マーク一覧が表示され、選択するとマークされたファイルの指定位置を開きます。
mattn/ctrlp-register - GitHub
https://github.com/mattn/ctrlp-register
レジスタ一覧が表示され、選択するとレジスタに格納されたテキストをペーストします。「あ、undo中に書き換えて大事な修正消しちゃった...」って時はレジスタに残ってる可能性もあるので便利かもしれません。まぁ普段Vim使ってる人は知ってますよね。

で、横道にそれ過ぎましたが話を戻してランチャーですが
mattn/ctrlp-launcher - GitHub
https://github.com/mattn/ctrlp-launcher
Windowsで動作確認してますが、たぶんUNIXでも動きます。まずこれを起動するキーマッピングを一つ定義して下さい。コマンドは「CtrlPLauncher」になっているので nnoremap <c-e> :<c-u>CtrlPLauncher<cr>
とでも書いておくと良いと思います。起動すると初回は何も出ません。唯一、「--edit-menu--」という候補のみが表示されます。これを選ぶと~/.ctrlp-launcherが開くのでここに以下の様にコマンドを定義します。 # [タイトル(空白含んでOK)] [タブ文字(複数可能] [実行するコマンド]
FavStar             FavStar mattn_jp
Browser             call feedkeys("\<Plug>(openbrowser-open)")
Explorer            !start rundll32 url.dll,FileProtocolHandler .
Command Prompt      !start cmd
System Property     !start c:/windows/system32/control.exe system.cpl
Task Manager        !start taskmgr
Service Manager     !c:/windows/system32/services.msc
Internet Explorer   !start iexplore

# vim:set ts=4
コマンド名と、複数のタブ、実行コマンドのカラムで構成されます。中身は utf-8 で記述する必要があります。先頭が「#」の行は無視されます。
コマンドはVimのコマンドラインで実行出切る物が書けます。なのでTwitVimのコマンドや、他のCtrlPエクステンションの実行にも使えます。
例えばキーを送りたいなら normal コマンドを書いても良いですしfeedkeysを使って URLを開く    call feedkeys(":OpenBrowser ")
コマンドラインの途中入力みたいな事も出来ます。このファイルは毎回読みに行くのでコマンド定義ファイルを書き換える度に再起動する必要はありません。僕の環境では CTRL + E で定義したので、CtrlE って呼んでます(うそです呼んでません)。
起動するとこんな感じになります。
CtrlE
CtrlPはマルチバイト文字が入力出来ないので様は良いですが絞り込み出来ないのでやらない方が良いです。

何か文字を打てば絞り込まれますし、CTRL+J と CTRL+K で上下に移動も出来ます。エンターキーを押すと対応したコマンドが実行されます。

やりたい事が多いのに、キーがバッティングし過ぎて困る人は便利かもしれません。良かったらどうぞ。
Posted at by