はてなブックマーク - Xcodeを(あまり)使わないでiPhoneアプリの開発
    このエントリーをはてなブックマークに追加

    こんにちは、そしてはじめての人ははじめまして。
    たぶん、Fusic社員の中野です。

    Fusic Advent Calendarということで、何か記事を書かなければいけなくなりました。他の人の記事はなんか難しそうな記事ばかりなので、軽くプレッシャーです。

    さて、iPhoneアプリを作っている人は、おそらく”Xcode”を使っている人がほとんどではないかなと思っています。弊社でも数人iPhoneアプリを作っている技術者がいますが、ほぼXcodeを使用しています。

    XcodeといえばMacについてくる無料の開発環境でとても便利なツールなんですが、「Emacs・Vimで開発したい!」もしくは「Xcodeを立ち上げるのもめんどくさい!」という人もいるかと思います。そこでそんな人たちのために、Xcodeを(あまり)使用せずに行うiPhoneアプリの開発のTipsをご紹介できたらとおもいます。

    検証環境

    • Mac OSX 10.5.8
    • iPhone Simulator SDK 3.0

    ※ OSのバージョンや環境によって違います

    iPhoneアプリ作成

    まず、今回の例として使用するiPhoneアプリの雛形をXcodeで作成します。Xcodeを起動して、「ファイル」->「新規プロジェクト」で「新規プロジェクト」ダイアログが表示されます。そのダイアログで「View-based Application」を選択してプロジェクトをどっかに保存してください。作成すると、以下のようにiPhone用テンプレートが作成されると思います。

    作成したら、メニューの「ビルド」->「ビルド」を選択して、一度、iPhoneアプリを作成します。

    iphonesimを作成

    次に、コマンドラインからiPhoneシミュレータを立ち上げるために、ここからソースコードをダウンロードして、”iphonesim”というツールを作成します。(ダウンロードして解凍すると、Xcodeのプロジェクトが入ってますので、お使いの環境にあわせてビルドをしてください。)

    コマンドラインからiPhoneシミュレータの起動

    ビルドしてできたiphonesimを利用し、はじめに作成したテスト用のiPhoneアプリをiPhoneシミュレータ内で起動させます。

    # iphoneアプリのプロジェクトのパスが"~/Desktop/Fac/Test"だった場合
    $ pwd
    /Users/nakano/Downloads/iphonesim/build/Debug
    $ ./iphonesim launch ~/Desktop/Fac/Test/build/Debug-iphonesimulator/Test.app
    [DEBUG] App Spec: 〜
    [DEBUG] SDK Root: 〜
    [DEBUG] Session started

    何もエラーがなければ、iPhoneシミュレータが立ち上がりiPhoneアプリが表示されると思います。

    いろいろ

    Q: Xcodeしか使ってないじゃん!ソースコードを編集してビルドするときはどうすんのよ?
    A:xcodebuildというコマンドでビルドできます。

    $ xcodebuild -configuration Debug -sdk iphonesimulator3.0
    Q:デバッグは?
    A:iPhoneアプリのPIDが取れますので、gdb –pid=PIDでデバッグできます。iphonesim+gdbを使ってのデバッグはちょっとしたコツが必要です。今回はデバッグ方法については割愛しますが、要望があれば次の回にでも補足できたらなと思います。
    Q:Interface Builderを使いたい!
    A:お察し下さい。

    Emacsをお使いの方は”emacs-xcode.el”やAutoCompleteの”ac-source-company-xcode”など利用すれば、開発自体も便利になると思います。 そして、これらをうまく利用すれば、Xcodeに負けないぐらいのiPhoneアプリの開発ができるelispができそうだなーなんて考えてます。

    それでは、次の担当の人にバトンタッチ〜。

      はてなブックマーク - PostgreSQLでクロス集計! tablefunc crosstab
      このエントリーをはてなブックマークに追加

      皆様こんにちは、
      新婚初日のウィークdayから午前帰宅で新妻にメールで泣かれた安元です。

      結婚式の前後でAdvent Calendarに当たるなんて、
      きっと日頃の行いがいいからだと思います!
      早くも2回目になっているのは気のせいです。

      閑話休題

      本日のお題はクロス集計です。
      SQLを実行した結果は、基本的に下に々伸びるものです。
      あなたも思ったことがあるのでは無いでしょうか?
      「SQLの結果が横に伸びれば。。。。」
      そうなんです、SQLの結果を横に伸ばすことが出来れば、クロス集計が行えるんです。
      今日はそんなお話です。

      まずはサクッとyumでpostgresql-contribをインストールしましょう
      このpostgresql-contribには、postgreSQLをいろいろと便利にしてくれる関数などのSQLが格納されています

      yum install postgresql-contrib

      インストールが完了したら、以下のコマンドでDBに関数を生成します
      postgrsql-contribの設置場所は環境に合わせて変更してください。

      psql -U postgres -f /usr/share/doc/postgresql-contrib-8.4.1/tablefunc.sql dbname 
      SET
      CREATE FUNCTION
      CREATE FUNCTION
      CREATE TYPE
      CREATE TYPE
      CREATE TYPE
      CREATE FUNCTION
      CREATE FUNCTION
      CREATE FUNCTION
      CREATE FUNCTION
      CREATE FUNCTION
      CREATE FUNCTION
      CREATE FUNCTION
      CREATE FUNCTION
      CREATE FUNCTION

      さて準備がととのいました。
      pgAdminなどでDBを確認してみてください。関数などが増えているはずです。

      今回使用するのは以下のようなデータです。
      ID|氏名|性別|登録日
      12/1~12/5までに登録があったユーザーと性別が登録されています。
      このデータから、日付と性別でクロス集計して見ましょう。

      
       id |  name   | sex |       created
      ----+---------+-----+---------------------
       1 | USER001 | f   | 2010-12-01 00:00:00
       2 | USER002 | t   | 2010-12-05 00:00:00
       3 | USER003 | t   | 2010-12-01 00:00:00
       4 | USER004 | t   | 2010-12-02 00:00:00
       5 | USER005 | f   | 2010-12-02 00:00:00
       6 | USER006 | t   | 2010-12-04 00:00:00
       7 | USER007 | t   | 2010-12-05 00:00:00
       8 | USER008 | f   | 2010-12-04 00:00:00
       9 | USER009 | f   | 2010-12-04 00:00:00
      10 | USER010 | t   | 2010-12-01 00:00:00
      11 | USER011 | f   | 2010-12-04 00:00:00
      12 | USER012 | t   | 2010-12-04 00:00:00
      13 | USER013 | f   | 2010-12-04 00:00:00
      14 | USER014 | t   | 2010-12-05 00:00:00
      15 | USER015 | t   | 2010-12-02 00:00:00
      16 | USER016 | t   | 2010-12-05 00:00:00
      17 | USER017 | f   | 2010-12-02 00:00:00
      18 | USER018 | t   | 2010-12-01 00:00:00
      19 | USER019 | t   | 2010-12-02 00:00:00
      20 | USER020 | t   | 2010-12-05 00:00:00
      (20 rows)
      

      ①GROUP BYによる日付ごと、性別ごとの人数を集計

      集計といえば、GROUP BYとCOUNT()ですね。

      
      SELECT
      	created,
      	sex,
      	count(id)
      FROM
      	customer
      GROUP BY
      	created,
      	sex
      ORDER BY
      	created,
      	sex ;
             created       | sex | count
      ---------------------+-----+-------
       2010-12-01 00:00:00 | f   |     1
       2010-12-01 00:00:00 | t   |     3
       2010-12-02 00:00:00 | f   |     2
       2010-12-02 00:00:00 | t   |     3
       2010-12-04 00:00:00 | f   |     4
       2010-12-04 00:00:00 | t   |     2
       2010-12-05 00:00:00 | t   |     5
      (7 rows)
      

      ②crosstab関数の利用

      ①で生成したSQLをcrosstab関数に投げ込みます

      
      SELECT
      	*
      FROM
      	crosstab(
                      -- ここから①のSQL
                      'SELECT
                              created,
                              sex,
                              count(id)
                       FROM
                              customer
                      GROUP BY
                              created,
                              sex
                     ORDER BY
                             created,
                             sex'
                      -- ここまで
      ) AS customer(
              -- 最終的に出力するデータの型を指定します
              days timestamp,
              male bigint,
              female bigint
      );
      
              days         | male | female
      ---------------------+------+--------
       2010-12-01 00:00:00 |    1 |      3
       2010-12-02 00:00:00 |    2 |      3
       2010-12-04 00:00:00 |    4 |      2
       2010-12-05 00:00:00 |    5 |
      (4 rows)
      

      さあ、これだけで、縦に日付、横に性別をもったクロス集計が出来上がっています!

      SELECT * FROM crosstab('GROUP化SQL') AS (結果表のデータ型指定)

      たったこれだけで、あとはPHPなりRubyなりでぐるっとforeachでも回せば、
      集計表の出力が行えます。
      ただのグループ化よりも、はるかに簡潔なプログラムになることうけあいです!

      余談ですが、このままでは12/3日の集計が出ていませんね。。。
      12/3はだれも入会しなかったのでしょう。データないものはGROUP BYでも集計できません。
      先日ご紹介したgenerate_seriesも合わせて利用して見ましょう

      
      SELECT
      	days,
      	coalesce(F,0) AS male,
      	coalesce(T,0) AS female
      FROM
      	crosstab(
      'SELECT
      	days,
      	sex,
      	count(id)
      FROM
      (
      	SELECT
      		date(''2010-12-1'') + a::int as days
      	FROM
      		generate_series(0,4) as a
      ) as generate
      LEFT OUTER JOIN
      	customer
      ON
      	(generate.days = customer.created)
      GROUP BY 
      	days,
      	sex
      ORDER BY 
      	days,
      	sex
      '
      ) AS customer(
      	days date,
      	F bigint,
      	T bigint
      );
      
          days    | male | female
      ------------+------+--------
       2010-12-01 |    1 |      3
       2010-12-02 |    2 |      3
       2010-12-03 |    0 |      0
       2010-12-04 |    4 |      2
       2010-12-05 |    5 |      0
      (5 rows)
      

      これで3日と5日の「0」も集計できました。
      FOR文やIF分の分岐が多い、またネストが多くなる場面で使用すると
      驚くほどの速度向上が見込めることがありますので、おためしあれ。

        はてなブックマーク - サービスは止まっていないのにネットワークエラーが・・・なぜ?
        このエントリーをはてなブックマークに追加

        奥さまの名前は CentOS、旦那さまの名前はしんちゃん。
        ごく普通のサーバに、ごく普通にインストールし、ごく普通の納品をしました。
        でも、ただひとつ違っていたのは、ifconfig を叩くと………エラーが発生していたのです!

        *・゜゚・*:.。..。.:*・゜゚・*:.。. (n‘∀‘)η

        はじめての人もそうでない人もはじめまして。 河野と申します。

        Advent Calendar はスタートの火蓋が切られたばかりにも関わらず、私だけが二週目に突入しました。
        マッハ号もかくやといったところです。

        さて、本日は「サービスは止まっていないのにネットワークエラーが増え続ける」という奇妙な問題を解決した際のお話を皆様にしたいと思います。

        尚、サーバはCentOS となります。

        エラーの増加

        サンプルに偏りがあるのを承知で言いますが「サービスは止まっていないのにネットワークエラーが増え続ける」。
        そういった事象はあまり無いのではないかと思われます。
        ネットワークにエラーがある場合は、サービスどころかネットワーク自体が疎通出来なくなる事が多いのではないでしょうか?

        ところが今回のエラーは以下のような特徴を持っていました。

        • リモートからサーバへのアクセスが可能
        • ローカルから外部へのアクセスが可能
        • パケットのエラーが増え続ける

        エラー発生当初、サービスに支障が出ていないので、今後の経過を見るという判断になりました。

        このサーバには Munin というサーバ動作ログを視覚的に閲覧することの出来るソフトウェアをインストールしていたのですが、見るたびにサーバのエラーは増えていきました。

        # ifconfig
        eth0      Link encap:Ethernet  HWaddr 00:03:0D:34:8F:AD
                  inet addr:10.1.0.1  Bcast:10.255.255.255  Mask:255.0.0.0
                  inet6 addr: fe80::203:dff:fe34:8fad/64 Scope:Link
                  UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
                  RX packets:5505120 errors:869 dropped:0 overruns:0 frame:869
                  TX packets:563000 errors:0 dropped:0 overruns:0 carrier:0
                  collisions:30 txqueuelen:1000
                  RX bytes:900322789 (858.6 MiB)  TX bytes:102707436 (97.9 MiB)
                  Interrupt:209 Base address:0xd800

        ※ ↑は執筆時に仮想サーバにてエラーを発生させてみたものです

        問題の調査

        色々と調査した結果、Auto-Negotiation 機能に問題があるのではないかという結論に至りました。

        ethtool コマンドで eth0 を調査した結果 half-duplex(半二重)になっていたからです。

        # ethtool eth0
        Settings for eth0:
                Supported ports: [ TP MII ]
                Supported link modes:   10baseT/Half 10baseT/Full
                                        100baseT/Half 100baseT/Full
                Supports auto-negotiation: Yes
                Advertised link modes:  10baseT/Half 10baseT/Full
                                        100baseT/Half 100baseT/Full
                Advertised auto-negotiation: No
                Speed: 100Mb/s
                Duplex: Half
                Port: MII
                PHYAD: 1
                Transceiver: internal
                Auto-negotiation: off
                Supports Wake-on: pg
                Wake-on: d
                Current message level: 0x000000c5 (197)
                Link detected: yes

        このサーバの eth1 はバックアップ装置と直繋ぎしておりこちらの通信モードは full-duplex(全二重)に設定されています。

        この結果から eth0 と繋がれているスイッチが full-duplex 固定に設定されており Auto-Negotiation 設定時に通信モードを返さなかった為、デフォルトの半2重設定を行ったと考えられました。

        問題の解決

        そうと分かればサーバ側の eth0 の設定を full-duplex 固定にしてしまえばいいだけの話です。

        ローカル環境で確認後、本番で行なった変更は ifcfg-eth0 の最後に以下の一文を加えるだけ。

        # vim /etc/sysconfig/network-scripts/ifcfg-eth0
        ETHTOOL_OPTS="autoneg off speed 100 duplex full"

        但し、ネットワークリスタートする必要があります。

        ちなみに eth-tool コマンドでも設定可能です。

        ● eth0 の autonegotiation を off

        # ethtool -s eth0 autoneg off

        ● eth0 の duplex を full にする

        # ethtool -s eth0 duplex full

        こちらは再起動を行なうと設定が消えますので、再起動後も設定を反映する場合は上記のようにデバイスの設定ファイルに設定を記述してください。

        最後に

        今回一番困ったのは「利用者からは問題がないように見える」点です。
        無視するわけにもいかないが、無視できる範囲のエラーなので、システムを停止することが難しいサーバや、社内システムだと止めるほどでも無いかもしれません。

        今回のエラーはサーバを設置してすぐだったため、トラフィックが増えてエラーが無視できなくなってくる前に対応する事にしました。

        どういったエラーでも対応すべきか、無視できるかは熟慮・検討する必要があるかと思いますが、今回のエラーは判断に迷う内容でした。

        結論からするとエラーは対応すべきものと私は思います。 が、技術的視点以外からの判断が加わってくると対応しないという結論もあるかもしれませんね。