OmniAICreator/Qiita-1.07M huggingface dataset:
Adobe Air SDK For iOS でアプリ開発する際のメモリリークの件

Adobe Flash Professional CS6 でiOSアプリを開発する際メモリリークでアプリが急に落ちることがあります。場合によってアプリが起動できない場合もあります。その直接原因はメモリリークだと思いますが、リークする原因はAirSDKの問題かiOS自身の問題かはっきり分かりませんが、コードの書き方によりその問題を回避することもできます。
メモリリークといえば、宣言した変数、オブジェクトなどがGCがメモリを回収する際参照回数が1以上であれば、そのオブジェクトは回収対象にならなくて残ってしまいリークが始まるんです。
通常Flash PlayerまたはAIRから自動的にGCを行っています。Air for iOSも同様だと思いますが、ある特定の条件でGCする際アプリが落ちてしまいます。
例えば次のMySubMovというインスタンスを使ってnullにしなかった場合、メモリリークが起きてしまいます。
<code>
public class MySubMov extends MovieClip {
      var myVar:Number;
      var myInt:int;
      var myStr:String;
}
</code>
Air SDKから開発したiOSアプリのメモリリークを検知する方法としてSystem.gc()（強制GC）を実行する方法があります。リークが始まる最中にSystem.gc()するとアプリがすぐ落ちますので、System.gc()をうまく使えばリークする場所を特定することができます。
上記のクラスのリークする直接原因はNumber型の変数を利用してnullで開放してないからです。
ActionScript3でNumberのデフォルト値はNaNで、nullではない、それが原因でしょうか、Air for iOSのNumber型に対するGCにはバグ？が有りかもしれないので、Air SDK for iOSでアプリを開発する際Number型の使用に気をつけましょう。浮動小数点はAction Script3版のBigDecimalを使ったほうがいいと思います。そしてできれば、クラスごとにdispose()メソッドを用意し、使い終わったオブジェクトについては必ずdispose()しましょう。
管理しやすいシェル設定ファイルの設計例

単純に変数を羅列する設定ファイルだと1設定1ファイルとせざるを得ず、結果、ファイル数が膨大になって管理が大変になる。以下のようなファイル構成とすることで、管理しやすく、しかも結合度の低い設定ファイルとすることができる。
なお、設計者は元同僚。

# 設計例

```bash:sample.conf
#No	profile	command	argument
1	profile1	command.exe	arg1
2	profile1	command.exe	arg2
3	profile1	command.exe	arg3
4	profile2	command.exe	arg4
5	profile2	command.exe	arg5
6	profile3	command.exe	arg6
```

```bash:profile1
LANG=C
```

```bash:profile2
LANG=jajs_SJIS
```

```bash:profile3
LANG=C
PATH=$PATH:/home/sampleuser
```

```bash:sample.sh
inputf=$1
No=$2
while read line
do
    # コメント行と空行を無視する
    if echo $line | grep -e '^#' -e '^$' >/dev/null; then
        continue
    fi

    # 行指定した場合に、指定行以外を無視する
    if [ -n $No -a "`echo $line | awk '{print $1}'`" != $No ]; then
        continue
    fi

    # 以下処理行

    profile=`echo $line | awk '{print $2}'`
    command=`echo $line | awk '{print $3}'`
    argument=`echo $line | awk '{print $4}'`
    
    . $profile
    $command $argument
    
done < ${inputf}
```

```bash:実行方法
# ./sample.sh sample.conf [1-3]
第二引数（No）を指定するとその行のみを実行する。指定しないと全行を実行する。
```

複数のソフトウェアの環境変数をまとめて設定する場合に使用する。具体的には、profileに共通設定を、sample.confの各行に個別設定を記載する。
自分の保守するシステムの一部シェルでこの仕組みを使っているが、設定値の追加・変更・削除がとてもしやすい。

なお、エッセンスを伝えることが目的の投稿のためコードは厳密ではありません。あしからず。
Nutanix Community Editionのインストール後にやること

無事にNutanix Community Edition(以下、CEと記載します)のインストール完了後、仮想マシンを作成するまでに行なうべき幾つかの作業をご紹介します。

* [ストレージの初期設定](http://qiita.com/shmza/items/2325aa321aeebc16b15d)
* ISOリポジトリの構成
* 仮想ネットワークの作成
* 仮想マシンの作成
ストレージの初期設定

Nutanix CEのクラスタ構築直後は、各ディスクは共有ストレージとして使用可能な状態になっていません。以下の手順で設定を行います。
(Nutanixのストレージの概念や構造については、こちらの記事をご参照ください)

### StoragePoolの作成
最初にStoragePoolを作成します。StoregePoolとはNutanixのストレージ管理の構成要素の一つで、Nutanixクラスタ内の物理ディスクの集合です。
Nutanixでは、1つのNutanixクラスタにたいして1つのStoragePool作成し、全てのディスクをそこに組込むことを推奨しています。

以下、ステップバイステップの作成手順です。

* Prismにログインする
PrismはNutanixクラスターのWebベースの管理コンソールです。Nutanixの基本的な操作はこちらから行います。
インストール時に設定したCVM(Controller VM)のIPをアドレスにウェブブラウザで接続します。(HTTPで接続するとHTTPSの9443ポートにリダイレクトされます)

![Prism_login.png](https://qiita-image-store.s3.amazonaws.com/0/83432/f7a26418-962c-8777-50a0-476936fdc844.png)


* 左上のプルダウンメニューからStorageメニューを選択する

![Storageメニュー](https://qiita-image-store.s3.amazonaws.com/0/83432/3703bfc4-ec97-123f-7c4e-e74007ba9b2a.png)

ストレージ管理画面に遷移します。

* 右上の"+ StoragePool"を選択する

![+StoragePool](https://qiita-image-store.s3.amazonaws.com/0/83432/83ada6d5-d6a4-d9a9-f3e8-398aede699b8.png)

StoragePoolを作成する設定画面がポップアップします。

![ストレージプール作成画面](https://qiita-image-store.s3.amazonaws.com/0/83432/2aab705d-246a-add3-cdae-53d5ca3014d4.png)

* デフォルト設定のままで問題ないので、名前をつけてSaveボタンを押す

名前をつける必要があります。私は"sp1"という名前にしました。
これでStoragePoolが作成されました。

引き続きContainerを作成します。

### Containerの作成
ContainerはNutanixのストレージ管理単位で、実際に仮想マシンファイルやISOイメージなどを保存する領域です。また、幾つかのストレージポリシー(重複排除や圧縮など）は、このContainerに対して設定します。

以下、ステップバイステップの作成手順です。今回は、仮想マシンファイルを保存する"VMs"とISOイメージを保存する"ISO"の2つのコンテナをデフォルト設定で作成します。

まずはストレージ管理画面に移動してください。

* 右上の"+ Container"を選択する
![+Container](https://qiita-image-store.s3.amazonaws.com/0/83432/55144a07-d548-ad84-7f6f-f9f3c40ce28c.png)

Containerを作成する設定画面がポップアップします。

* Containerの名前をつけて保存する
![コンテナ作成画面](https://qiita-image-store.s3.amazonaws.com/0/83432/8b452147-9fa9-cf8c-add0-ee886809a087.png)

左下のAdvanced Settingをクリックすることで、各種ストレージポリシーの設定が出来ますが、今回はデフォルトのままで作成します。私はISOsとVMsの2つのコンテナを作成しました。

***
次のステップはISOリポジトリの構成です。
Android端末での動作確認中にエラー表示無くアプリが強制終了した場合の対処法

## 1つ目
AQUOS Xx 304SH (Android 4.4.2) にアプリをインストールして動作確認をしていたところ、GridViewをスクロールしている途中にソフトキーのバックボタンが効かなくなり、最終的に「問題が発生したため、◯◯を終了します。」のダイアログが表示されること無くアプリが強制終了するという事案が発生しました。

今まで動作確認中にこのようにはなったことがなく、メモリの使用状態が上がってきた頃にアプリが強制終了させられたため実機側に問題があると思い一度再起動してみたところ、上記の現象は発生しなくなりました。

デバッグに使用していた端末ですが1,000時間以上は稼働していたと思うので、しばらく電源を切っていないと思ったら再起動することをお勧めします。

手元に AQUOS Xx 304SH と AQUOS CRYSTAL 305SH (Android 4.4.2) があるのですが、アプリを終了した後プログレスバーが表示され、なかなかホーム画面に戻らなくなるという予兆があったので、端末の動作が遅くなってきたときが電源を切ってリセットするタイミングだと思います。

## 2つ目
1. `onCreate()` で Fragment を `add()` する Activity を作成する
2. 設定 > 開発者向けオプション > アクティビティを保持しない をONにして Activity の遷移 OR ホームボタンタップでアプリをバックグラウンドにする :left_right_arrow: アプリをフォアグラウンドに戻す を繰り返す
3. Activity は破棄されるが Fragment は生きているという状態になる
4. 破棄された Activity に戻ると `onCreate()` が再度呼ばれ Fragment が `add()` される
5. さらに Activity の遷移を繰り返すと同じ Fragment が2、3、4...個と生成されていく
6. 最終的にメモリの限界が来てアプリが落ちる

ということがあるので Fragment が存在している場合は何もしないようにするという対応が必要になります。

```
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getSupportFragmentManager().findFragmentByTag("FragmentTag") == null) {
        getSupportFragmentManager().beginTransaction().add(R.id.activity_fragment_container, new Fragment(), "FragmentTag").commit();
    }
}
```
railsでメールを相手が開封したかどうかを知るには

メールの開封率を知りたかったので実装しようとしたら困った、「相手がメール開いたかどうかってどうやったらわかるんだ」と、、、しかもググり方が難しくなかなかヒットしてくれなかったのでメモとして残すことにしました。

##メールの開封率を測定するには
開封率を測定するには、TEXT形式ではなくHTML形式メールを配信する必要があります。なぜなら、メール内に埋め込んだ小さな画像スクリプトを読み込ませることによってメールの開封数をカウントしているらしいからです。
だた最近、近年スパム対策などで、メーラーによってはイメージ（画像）の読み込みをブロックする機能が搭載されているものもあるらしく、ブロック機能によってイメージが読み込まれないこともあるらしいので気をつけたいところです。こうなってしますと例えメールが開封されたとしても開封としてカウントすることができないのですからね。。

###つまり
開封率を測定　→　display_noneした画像のリクエストが跳んだ数ってことですかねー、これで問題解決しました。他にやりかた知っている方がおりましたらご教授お願いします。
CentOS7で、109キー日本語レイアウトを有効にする

この資料は、個人的な備忘録の位置づけです。また、正式な設定方法とは限りません。


# 109キー日本語レイアウトのキーボード

109キー日本語レイアウトのキーボード(OADG 109Aキーボード)は、Windowsキーのついたキーボードです。[PCオープン・アーキテクチャー推進協議会(OADG)](https://ja.wikipedia.org/wiki/PC%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3%E3%83%BB%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%83%BC%E6%8E%A8%E9%80%B2%E5%8D%94%E8%AD%B0%E4%BC%9A)で標準化されています。
> 参考：
> https://ja.wikipedia.org/wiki/キー配列
> http://qa.elecom.co.jp/faq_detail.html?id=5262

# CentOS7で109キー日本語レイアウトのキーボードを使う

以下のコマンドで設定する。

1. `localectl set-keymap jp106`　　とりあえず、日本語106キーボードに設定する。
2. `localectl set-keymap jp-OADG109A`　　そのあとに、日本語109キーボードに設定しなおす。
3. `localectl`　　設定値を確認すると、以下のようになっている。

```lang:localectlの結果
   System Locale: LANG=us.utf8
       VC Keymap: jp-OADG109A
      X11 Layout: jp
       X11 Model: jp106
     X11 Options: terminate:ctrl_alt_bksp
```

# おまけ：System Localeを変更する
以下のコマンドで設定する。

1. `localectl set-locale LANG=ja_JP.utf8`　　UTF8の日本語の場合
2. `localectl`　　設定値を確認すると、以下のようになっている。

```lang:localectlの結果
   System Locale: LANG=ja_JP.utf8
       VC Keymap: jp-OADG109A
      X11 Layout: jp
       X11 Model: jp106
     X11 Options: terminate:ctrl_alt_bksp
```
[メモ]PHP 5.3から5.6までに追加された機能

# 本題の前に
## 背景
まもなくPHP7がリリースされているという話を見て、"現時点(2015年5月時点)で最新のPHPってどんな機能が追加されているのだろうか？"とふと思い[PHPマニュアルの付録](http://php.net/manual/ja/appendices.php)をさらっと見てみたところ、思いのほか知らない機能があることに気付きました。

自戒の意味も込めて、個人的に気になった"各バージョン毎の追加機能"を簡単にまとめて社内勉強会のLTで発表してみたら、思いのほかウケがよかったので、作ったスライドの内容を公開してみます。

## 前提
- LTで発表する内容として作ったので、ピックアップして簡易的にまとめており詳細に触れてはいません。詳細を知りたい場合は、[PHPマニュアルの付録](http://php.net/manual/ja/appendices.php)を参照してください。
- 関数の追加・変更や、バージョン毎の互換性等に関しては特に触れていません。
- タイトルにもある通り、PHP5.3以降に絞って書いています。 

# 本題
## PHP 5.3
- 無名関数の対応
- 名前空間のサポート
- クラスの外でconstを利用して定数を定義できる。
  - 元々、クラスの外での定数はdefineを使って定義できました。  
    defineとの違いとしては、名前空間の影響を受けることが挙げられます。
- 三項演算子の短縮形(?:)が利用可能  
  - `ex) $member = $djyugg ?: “other”;`
  - 上記の場合、\$djyuggの値をbooleanにキャストして、trueの場合は\$djyuggの値を代入、falseの場合は"other"を代入といった動作になります。
- goto文の対応

## PHP 5.4

- Traitのサポート
- 配列の短縮形([])サポート  

```php
var members = [];
```

- インスタンス生成時にメンバにアクセス可能になる

```php
(new Hoge())->fuga()
```
- 2進数フォーマットの対応
  - `ex) 0b10011101`
- PHPモジュールにWebサーバが組み込まれる
  - あくまで開発支援用

## PHP 5.5
- foreachでlist()が利用可能
- generatorの対応
- try-catchでfinallyが利用可能
- arrayリテラルとstringリテラルのデリファレンス  
  - “string”[2] で”r”が出力される。  
  - 1バイト単位でしか参照できないようで、マルチバイト文字で同じことをやると化けます…
- OPcache 拡張モジュールの追加
  - ソースコードを事前に中間コードにコンパイルしてメモリにキャッシュしてくれる機能。  
    php.iniで有効・無効を設定できます。  

## PHP 5.6

- constでの定数定義時に式が利用可能  

```php  
const CONST_VALUE = 1;  
const CONST_VALUE_SECOND = CONST_VALUE * 2
```

- 可変個引数関数(...演算子)  

```php
public function input_check($user, … $parameters)
```

- 累乗演算子 ** の追加
- 名前空間の機能として、useを使った関数・定数のインポート・エイリアス定義が可能

## 参考
- [PHPマニュアル 付録](http://php.net/manual/ja/appendices.php)
package.elの設定と使い方

# 設定
設定ファイル`~/.emacs.d/init.d`に追加

```el:init.el
(when (require 'package nil t)
  (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/"))
  (package-initialize))
```

# 使い方
`M-x package-install` か `M-x package-list-packages` でインストール
インストール後 `M-x package-initialize` で使用可能[^1]
[^1]: autoloads.elがあれば

# インストールしたパッケージ
## auto-complete
## coffee-mode
## emmet-mode
## flycheck
## magit
## sass-mode
## web-mode
FAT32とNTFSの違い

# 3行で
- FAT32が古くて、NTFSが新しい
- FAT32では4GB以上のファイルを扱うことができないが、NTFSでは最大16TBのファイルを管理することができる
- FAT32では2TB以上のドライブを管理できないが、NTFSは256TBまでのドライブを管理できる。ただし、理論上はさらに多くの容量を管理できる

# 付記: 共通点
- FAT32、NTFS共にWindowsで採用されているファイルシステムである

# 詳しくは
- http://michisugara.jp/archives/2012/file_system.html
Skype の SQLiteファイル main.db の構造

## Skype の発言内容を読み取りたい
Skype API 等もあるがもっと高速に読みたい。
Skype が使用しているデータベースファイルの構造を、手当たり次第データを漁ることにより解析した。

## main.db を読む
Linux, Mac に Skype をインストールしてあれば、
```/home/{Linuxユーザ名}/.Skype/{Skypeユーザ名}/main.db```
というファイルができているはず。

このファイルは SQLite のファイルなので、SQLite のコマンドにより中身を読み取ることができる。

## SQLite コマンド
インストールされていなければ yum 等でインストールする。

```
# yum -y install sqlite
```

sqlite3 コマンドで main.db にアクセスする。

```
$ sqlite3 /home/Hoge/.Skype/Fuga/main.db
SQLite version 3.6.20
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> 
```

## テーブル一覧
.table コマンドでテーブル一覧を見ることができる。

```
sqlite> .table
Accounts          ChatMembers       DbMeta            SMSes
Alerts            Chats             LegacyMessages    Transfers
AppSchemaVersion  ContactGroups     MediaDocuments    VideoMessages
CallMembers       Contacts          Messages          Videos
Calls             Conversations     Participants      Voicemails
```

## コンタクト一覧
```
sqlite> .schema Contacts
CREATE TABLE Contacts (id INTEGER NOT NULL PRIMARY KEY, ..., skypename TEXT, ..., fullname TEXT, ...);
......
```

- skypename … ID
- fullname … 表示名

```
sqlite> SELECT skypename, fullname FROM Contacts LIMIT 10;
kobayan-tokyo|k.kobayashi
kobabot|こばぼっと
......
```

## トピック一覧
![Image9.png](https://qiita-image-store.s3.amazonaws.com/0/25555/18973a6e-eb34-80ef-d60c-551641d63bcb.png)

いわゆる「窓」一覧は「Conversations」テーブルから確認することができる。

```
sqlite> .schema Conversations
CREATE TABLE Conversations (id INTEGER NOT NULL PRIMARY KEY, ..., identity TEXT, ..., displayname TEXT, ..., last_activity_timestamp INTEGER, ...);
......
```

- identity    … トピック識別子
- displayname … 表示名
- last_activity_timestamp … 最終更新時刻

```
sqlite> SELECT id, identity, displayname FROM Conversations ORDER BY last_activity_timestamp DESC LIMIT 10;
1212|xxxxxx|窓1
1213|yyyyyy|窓2
1200|zzzzzz|窓3
.......
```


## トピック内発言一覧
```
sqlite> .schema Messages
CREATE TABLE Messages (id INTEGER NOT NULL PRIMARY KEY, ..., chatname TEXT, ..., from_dispname TEXT, ..., timestamp INTEGER, ..., body_xml TEXT, ...);
....
```

- chatname … トピック識別子
- from_dispname … 発言者
- timestamp … 発言時刻
- body_xml … 発言内容

たとえば上述の「窓1」(identity = 'xxxxxx')の発言一覧を取得したければ、

```
sqlite> SELECT timestamp, from_dispname, body_xml FROM Messages WHERE chatname = 'xxxxxx' ORDER BY timestamp LIMIT 5;
1434871603|kobayashi|hello
1434871611|kobayashi|test
1434871640|kobayashi|testtest
1434871640|kobayashi|こんにちは
1434871641|kobayashi|g
```

のような感じ。


## 応用

今回の解析結果を元に、Skype の発言内容をブラウザから閲覧・検索できる [qskype](https://github.com/kobake/qskype) というものを作ってみた。これの完成間近に [Skype for Web](https://web.skype.com/) が発表されてしまったが他意は無い。

![qskype.png](https://qiita-image-store.s3.amazonaws.com/0/25555/70412402-30f9-ba70-5449-ed8cfc167764.png)

- [kobake/qskype](https://github.com/kobake/qskype)
GoogleMapのオープンソース版地図アプリ（OSRM）のインストール

関連して以下も参考にしてください

> * [初めて地図周りの技術に触れた時に作ったまとめ資料 - Qiita] (http://qiita.com/laqiiz/items/7d256108920ff7afbf08)
* [住所（市区町村番地）から緯度経度を取得する - Qiita](http://qiita.com/laqiiz/items/842fe2a32e80bac92364)


# OSRMとは

![osrmtop.png](https://qiita-image-store.s3.amazonaws.com/0/6463/bb25b88a-7d58-826a-52f5-b519059e416d.png)

OSRM(Open Source Routing Machine)はフリーの経路検索アプリです。
GoogleMapは非常に便利ですが、利用回数に制限があるため大量検索を行う場合はこちらの構築も検討してみてはどうでしょうか？

http://project-osrm.org/


# インストール内容

* OSRMのバックエンドモジュールのみインストールします
    * なのでトップにあるような地図画像は残念ながら今回は出力できません（無念です）

# 環境情報

Ubuntu14.10を用います。
ちなみにCPUはハイパースレッディング込みで8コアのパワーがあるのを用います。

>```sh:バージョン情報
% cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.10
DISTRIB_CODENAME=utopic
DISTRIB_DESCRIPTION="Ubuntu 14.10"
```

# 手順

参考情報のサイト通り進めました。

## 依存パッケージ

```sh:依存パッケージインストール
sudo apt-get install build-essential git cmake pkg-config libprotoc-dev libprotobuf8 \
protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev \
libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev \
libzip-dev libboost-all-dev lua5.1 liblua5.1-0-dev libluabind-dev libluajit-5.1-dev libtbb-dev
```

## OSRMダウンロード
```sh:OSRMをGithubからクローン
 % mkdir ~/osrm
 % cd osrm
 % git clone https://github.com/Project-OSRM/osrm-backend.git
```

## OSRMのビルド
```sh:OSRMのビルド
 % cd osrm-backend
 % mkdir -p build
 % cd build
 % cmake ..
 % make
```
## 地図情報の取得

Open Street Mapから日本に絞って地図情報を取得します。
以下のサイトにアクセスしてダウンロードするURLをメモします。
（結構サイズが大きいので、直接wgetします）

http://download.geofabrik.de/
 > asia > japan のデータを選択します

![openstreetmapdata.png](https://qiita-image-store.s3.amazonaws.com/0/6463/c4aaf2ff-045a-ce1a-5c95-25e3a00d7d85.png)

![japan.png](https://qiita-image-store.s3.amazonaws.com/0/6463/130242ab-71b2-c460-8d03-8ffd54e5ff42.png)


```sh:OSMの日本地図をダウンロード
# サーバにDL
wget http://download.geofabrik.de/asia/japan-latest.osm.pbf
```

## 地図情報pbfを変換

少し時間がかかって5分位要しました。

```sh:データ変換
# pbfのデータをosrmが認識する形式に変換
 % ln -s osrm-backend/profile.lua
 % ls -s osrm-backend/lib
 % ln -s osrm-backend/build/osrm-extract
 % ln -s osrm-backend/build/osrm-prepare

# 変換実行
# Extracting the Road Network
./osrm-extract data/japan-latest.osm.pbf
```

## ルーティング計算

これが無茶苦茶時間かかりました。
2-3時間オーダで放ったらかししていたら終わっていたぐらいです。

```sh:グラフ情報を生成
# Creating the Hierarchy
# extractingで作ったデータを指定するようです
 % ./osrm-prepare data/japan-latest.osm
```

## 起動

```sh:OSRMの起動
# Running the Engine
nohup ./osrm-routed data/japan-latest.osrm &
```

## 疎通確認

サーバにアクセスして疎通します。
デフォルトポートは5000です。

> http://FQDB:5000/locate?loc=35.65858,139.745433

```json:検索結果
{"mapped_coordinate":[35.658356,139.745087],"status":0}
``` 

ステータスは正常終了が0みたいです。
locateはどういうAPIかというと、取り込んだ地図情報で最も近いノードを返してくれるようです。

# 参考情報

基本的に本家のWiki通り進めたらうまくいきました
https://github.com/Project-OSRM/osrm-backend/wiki/Building-on-Ubuntu
https://github.com/Project-OSRM/osrm-backend/wiki/Building-OSRM
https://github.com/Project-OSRM/osrm-backend/wiki/Running-OSRM

# 今後

* 引き続きOSRMのAPIや仕様について調査しまとめていきます :star2:
Javaの文字列結合効率化を確認

Javaで大量のテキストを処理する機会があったので、文字列結合の効率化について復習しておこう。

#環境＆やること
* Java1.8
* [JODE](http://jode.sourceforge.net)でデコンパイルして動きを見よう

#文字列結合いろいろ
* "+"を使う
* String.concat()を使う
* StringBuffer/StringBuilderを使う

```java:文字列結合
String a = "aaa";
String b = "bbb";
String str;
//"+"を使う
str = a + b;
//concatを使う
str = a.concat(b);
//StringBuilderを使う
str = new StringBuilder(a).append(b).toString();
``` 
concat()は新しくStringをnewして返すメソッド。
StringBuffer/Builderは可変長文字列を扱うクラスで、appendされた文字列をせっせとバッファに詰め込みます（いちいちnewしない）。
問題なのが"+"で、これはコンパイラの最適化によって書き換わります。使い方を間違えると大変。

#ダメな例
早速やらかしてみましょう。

```java:元
String str = "";
//やらかした例
for(int i = 0; i < 10000; i++){
  str += a + b;
}
```
```java:デコンパイル
String str = "";
for (int i = 0; i < 10000; i++)
	    str = new StringBuilder(str).append(a).append(b).toString();
```
StringBuilderを使った文字列結合は速いんですが、そもそもStringBuilderをnewすること自体はそれなりにコストがかかります。ループの中でnewしちゃだめです。

```java:インスタンス使いまわす
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.setLength(0);
    str = sb.append(str).append(a).append(b).toString();
}
```
#定数の結合
もう一つ注意点。
定数は最適化の段階で一つにまとめてくれます。なので最速。最速というか結合じゃないし。

```java:元
final String FA = "finalA";
final String FB = "finalB";
String a = "A";
String b = "B";
String str = "";

str = "A" + "B";   //文字列
str = a + b;       //変数の結合
str = FA + FB;     //定数の結合
str = a + FA + FB; //変数+定数
str = FA + FB + a; //定数+変数
```
```java:デコンパイル
str = "AB";
str = new StringBuilder(a).append(b).toString();
str = "finalAfinalB";
str = new StringBuilder(a).append("finalA").append("finalB").toString();
str = new StringBuilder("finalAfinalB").append(a).toString();
```
ただ、定数と変数が混ざった下2行を見てみると、変数が混ざる前は結合されてますが、変数以降はappendになってますね。

#まとめ
* ループ内での"+"を使った文字列結合は注意
* 定数と変数を混ぜる場合も注意
* そうは言っても何万回も繰り返さない処理なら可読性UPのために"+"使ってもいいよね

##なんで今さら？
Q. Javaプログラマーにとっては何を今更という内容かもしれないが、なんで書いた？

A. 自分で書いたコード見直してたら思いっきりやらかしてたから。
docker上のnginxから、別のコンテナのwebへリバースプロキシさせる

APのコンテナが複数あって、それを1つのnginxからリバースプロキシして振り分けることをしてみる。

まず、APコンテナは以下のDockerfileとする。

```text:ap1/Dockerfile
FROM debian:8.1
MAINTAINER 74th<site@j74th.com>

RUN apt-get update
RUN apt-get install -y apache2 libapache2-mod-php5

EXPOSE 80

VOLUME ["/var/www/html"]

ENTRYPOINT  service apache2 start && \
            tail -f /var/log/apache2/access.log
```

PHP+Apacheで動いている普通のコンテナ。これを、ビルドして起動する。

```bash:ap1/buildstart.sh
docker build -t 74th/ap1 .
docker run -d \
    -v `pwd`/html:/var/www/html \
    --name ap1 \
    74th/ap1
```

APコンテナのポイント

* `EXPOSE`でポート80を指定する。しかし`docker run`では、`-p 80:80`などと外部に出したりしない。
* ちゃんとコンテナ名`--name　ap1`を付け、nginxから参照できるようにする。
* `VOLUME`で、コンテンツをコンテナと共有する。

起動していることを確認する。

```
$docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                  NAMES
8f27081607b0        74th/ap1            "/bin/sh -c 'service   2 hours ago         Up 2 hours          80/tcp                 ap1
```

次に、これにnginxからアクセスできるようにする。
nginxのDockerfileはこちら。

```txt:frontnginx/Dockerfile
FROM debian:8.1
MAINTAINER 74th<site@j74th.com>

RUN apt-get update
RUN apt-get install -y nginx
COPY ./default /etc/nginx/site-enabled/default

EXPOSE 80

ENTRYPOINT  service nginx start && \
            tail -f /var/log/nginx/access.log
```

起動用のスクリプトは以下のとおり。

```bash:frontnginx/buildstart.sh
docker build -t 74th/frontnginx .
docker run -d \
    -p 80:80 \
    --link ap1:ap1 \
    --name frontnginx \
    74th/frontnginx
```

ここまでのポイントは、以下のとおり。

* `EXPOSE`で指定し、さらに`docker run -p 80:80`で、こちらは80番ポートを外部公開する。
* コンテナ間リンク`--link`をAPコンテナに設定して起動する。
* nginxの設定ファイル`default.conf`を、書き換えてコンテナの中に入れる。

さて、このnginxの設定を、以下のようにする。

```txt:default
server {
	listen 80 default_server;
	listen [::]:80 default_server;
    
    # ap1
	location / {
        proxy_pass http://ap1;
	}
}
```

実は、`--link`オプションで指定したエイリアスへは、/etc/hosts に設定が追加されるため、nginxのコンテナからは`http://ap1`でAPコンテナにアクセスできる。これだけでOKなのである。
なんとも簡単。

ポイント

* `--link`で設定したAPコンテナをホスト名として、nginxからプロキシさせる
c++ builder > TDateTime > 日付、時分秒の比較 (ミリ秒は無視)

```txt:動作確認
C++ Builder XE4
```

２つのTDateTime型変数を比較する際、ミリ秒は多少異なっても日付と時分秒は同じかどうかをチェックするには以下のようにする。

RecodeMilliSecond()を使って、ミリ秒を0に設定した上でCompareDateTime()している。

```cpp
#include <DateUtils.hpp>
...

static bool comp_dts(TDateTime dt1_, TDateTime dt2_)
{

	TValueRelationship res;
	int nop=1;

	dt1_ = RecodeMilliSecond(dt1_, 0);
	dt2_ = RecodeMilliSecond(dt2_, 0);

	res = CompareDateTime(dt1_, dt2_);
	switch (res) {
	case LessThanValue:
		nop=1;
		break;
	case EqualsValue:
		nop=1;
		break;
	case GreaterThanValue:
		nop=1;
		break;
	default:
		;
	}
}

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	TDateTime dt1, dt2;

	dt1 = StrToDateTime(L"2015/06/21 12:30:45");
	dt2 = StrToDateTime(L"2015/06/21 12:30:48");
	comp_dts(dt1, dt2);

	dt1 = StrToDateTime(L"2015/06/21 12:30:45.002");
	dt2 = StrToDateTime(L"2015/06/21 12:30:45.900");
	comp_dts(dt1, dt2);
}
//---------------------------------------------------------------------------
```
Rails4 attributeの代入をフックする


# Goal

* `new`, `create`, `update`などでattributesハッシュを渡したときに引数attributesに対して毎回特定のフィルタ処理をおこないたい
* 通常はモデルの仕様に合わせて呼び出し側でattributesを準備するべきだと思うが、準備すべき引数attributesがモデルのビジネスロジックに依存する場合、利便性のためにモデル側にパラメータ変換ロジックを持たせておきたい

# Code

`assign_attributes`をオーバーライドすればよい. `new`, `create`, `update`で渡された引数attributesは`assign_attributes`メソッドを通してモデルにセットされる.

```ruby:user.rb
class User < ActiveRecord::Base
  belongs_to :game

  def self.gender_role( role_name, gender_name )
    gender_roles = {
      acting: {
        male: :actor,
        female: :actress,
      },
      waiting: {
        male: :waiter,
        female: :waitress,
      }
    }
    return nil unless gender_roles[role_name]
    gender_roles[role_name][gender_name]
  end

  def assign_attributes(attributes)
    gender_local = gender
    gender_local = attributes[:gender] if attributes[:gender]
    attributes[:role] = User.gender_role(attributes[:role], gender_local)
    super attributes
  end
end
```

```ruby
user = User.new( role: :acting, gender: :male )
user.role # :actor

user = User.new( role: :acting, gender: :female )
user.role # : actress

user = User.create( gender: :male )
user.update( role: :waiting )
user.role # :waiter
```

# Caution

引数つきで`new`したときは毎回実行されるので、重い処理を実行するときは注意.
個別のattributeに直接代入するときは当然`assign_attributes`はよばれない.

# Environment

```
$ bundle exec rails -v
Rails 4.1.9
```
header() 関数を使ったメソッドを PHPUnit でテストする方法

header() 関数はその実行前に何らかの標準出力がされていると「`Cannot modify header information`」というエラーを吐いてしまいます。
PHPUnit はテスト中のメッセージを標準出力に逐一吐き出すため、そのままでは header() 関数を用いたメソッドのテストができません。


現象
----
たとえば下記のようなテストケースはエラーで止まります。

```php
class Api {
    public function output($data, $response_code = 200) {
        http_response_code($response_code);
        header('Content-Type: application/json'); // この行の前に PHPUnit が標準出力にテスト進捗を逐次出力するせいで、エラーになる
        $output = json_encode($data);
        
        echo $output;
        return $output;
    }
}

class ApiTest extends \PHPUnit_Framework_TestCase {
    /*
     * @covers Api::output
     */
    public function testOutput() {
        $data = ['foo' => 'bar'];
        $response_code = 200;

        ob_start();

        $actual = $this->Api->output($data, $response_code);
        $output = ob_get_contents();
        $expected = json_encode($data);

        $this->assertEquals($expected, $actual);
        $this->assertEquals($output, $actual);
        $this->assertEquals(http_response_code(), $response_code);

        ob_clean();
    }
}
```

上のテストを実行すると、以下のようなエラーを吐きます。

```
Cannot modify header information - headers already sent by (output started at C:\xampp\php\pear\PHPUnit\Util\Printer.php:172)
```


対策
----
PHPUnit の `@runInSeparateProcess` アノテーションを利用することで、テストケースだけを別プロセスで実行することができます。
つまり、header() 関数を使うテストだけは標準出力が真っさらなプロセスでテストできるので、エラーを吐きません。

```php
    /**
     * @covers Api::output
     * @runInSeparateProcess
     */
    public function testOutput() {
        // ...
    }
```

```bash
PHPUnit 3.7.8 by Sebastian Bergmann.

.

Time: 3 seconds, Memory: 2.75Mb

OK (1 test, 3 assertions)
```

header() 関数を使ったメソッドのテストをする際には覚えておきたいテクニックです。


参考
----
* [付録B アノテーション](http://www.phpunit.de/manual/3.7/ja/appendixes.annotations.html#appendixes.annotations.runInSeparateProcess)
* [PHP: header - Manual](http://www.php.net/manual/ja/function.header.php)
* [unit testing - Test PHP headers with PHPunit - Stack Overflow](http://stackoverflow.com/questions/9745080/test-php-headers-with-phpunit)
Sketchup で Google Earth の地形データをインポートする手順

Google Earth の 3D の地形データを Sketchup にインポートするチュートリアルです。


手順
----
### 場所のインポート
"ファイル > ジオロケーション > 場所を追加" をクリック。

![su_tutorial_001.png](https://qiita-image-store.s3.amazonaws.com/0/8267/468f5726-4787-3cdf-9283-14693fdd9cd9.png)

Google Maps が開くので、地名を検索する。

"地域を選択" をクリック。

矩形の範囲を設定し、"グラブ" をクリック。

![su_tutorial_002.png](https://qiita-image-store.s3.amazonaws.com/0/8267/0a893612-ac60-84cd-5e2d-1421e56bf2f8.png)


これで地形データが Sketchup にインポートされます。

![su_tutorial_003.jpg](https://qiita-image-store.s3.amazonaws.com/0/8267/0daf9b56-7e31-18a7-380c-6e8c1de04ef5.jpeg)


### 3D モデルを表示する
この時点では 2D の画像しかありませんが、3D のデータも非表示のレイヤーで取り込まれています。
表示するには次の手順に従います。

1. "ウィンドウ > レイヤ" をクリックして、レイヤパネルを開く。
1. "Google Earth Terrain" の "可視" チェックボックスをクリック。

![su_tutorial_004.png](https://qiita-image-store.s3.amazonaws.com/0/8267/47b48bb7-574d-21a6-7df1-2032021a1b38.png)


これで 3D のデータが取り込まれました。

### 編集可能にする
さらにこの時点ではエンティティにロックがかかっているため、編集できません。
編集したい場合はエンティティを選択し、"エンティティ情報" パネルの "ロック" チェックボックスを外します。

![su_tutorial_005.png](https://qiita-image-store.s3.amazonaws.com/0/8267/e5ef7cc6-51d8-afc9-c4f0-0bfa0150c0cf.png)

これでエンティティが編集可能になります。

![su_tutorial_006.png](https://qiita-image-store.s3.amazonaws.com/0/8267/c3a0ee0f-5262-41b0-674b-56e904b09bc8.png)


表面の 2D 画像を消したければ、エンティティを選択して "サーフェス" をデフォルトにすれば OK。


参考
----
[How do I import terrain from Google Earth? - Google プロダクト フォーラム](https://productforums.google.com/forum/#!topic/sketchup/Crl5SFcyRo0)
bundle install が遅ければ source を変えよう

Rails 4 アプリを作ろうとして `rails new` コマンドを叩いたら、`bundle install` のフェーズが永遠に終わらず老人になりそうでした。

どうやら gem リポジトリの [http://rubygems.org](http://rubygems.org) のレスポンスが遅すぎるようです。

そこで、Rails アプリの作成時は `bundler install` を省略し、Gemfile をいじってもっと早いリポジトリを参照するように変更したら、無事インストールできました。


具体的な手順
----------
```bash
$ rails new mojamoja --skip-bundle
$ cd mojamoja
$ vim Gemfile
```

`Gemfile` の1行目を以下のように変更する。

```rb
# source 'http://rubygems.org'
source "http://bundler-api.herokuapp.com"
```

これでインストールできるようになります。

```bash
$ bundle install
```


RHEL/CentOS 6.x 特有のバグ
------------------------------------------
RHEL/CentOS 6.x を使っている場合、ネットワークの解決が異常に遅くなることがあります。`/etc/resolve.conf` に以下の1行を追加すると解決するようです。

```
options single-request-reopen
```


参考
----
- [Ruby - bundlerが遅い(Error Bundler::HTTPError)のを解決 - Qiita [キータ]](http://qiita.com/quattro_4/items/fcc2ff8b04c43229a2fb)
- [Vagrant+VirtualBox（CentOS6）で「gem install rails」がすっごい遅い時の対処法 | IDEA*IDEA](http://www.ideaxidea.com/archives/2013/08/resolv.html)
WEBページのレスポンスが遅くなった時に、サーバ台数を増やす

# やってみたこと
WEBサーバのレスポンスが遅くなったときに、EC2インスタンスが自動で追加されたらいいなーという事でやってみました！
ELB配下にWEBサーバを配置します。
監視サーバでは、curlでELBに接続しレスポンスタイムをCloudWatchにPUTします。※カスタムメトリクスを使います。
レスポンスが遅くなったら、AutoScalingを発動しELB配下にWEBサーバを追加します。

![image](https://qiita-image-store.s3.amazonaws.com/0/70673/189b238a-5dd8-f683-874c-6aad4c379361.png)

# 監視サーバスクリプト
cronにて定期実行します。

```
#!/bin/bash

### 変数
# ELBのURL 
URL="http://***"

### 処理部
# ELBにアクセスした際にかかった時間を取得する
gettime=`curl -kL ${URL} -o /dev/null -w "%{time_total}" 2> /dev/null`

# メトリックデータをPUTする
aws cloudwatch put-metric-data \
--metric-name "***" \
--namespace "***" \
--dimensions "***=***" \
--value ${gettime} \
--unit "Seconds"
```
# AutoScaling
AutoScalingでは、ELBを指定する事ができます。
AutoScaling発動時に、指定したELB配下にアタッチされるようになります。
![image](https://qiita-image-store.s3.amazonaws.com/0/70673/90e0eec3-353c-e7e2-e776-273e04eee723.png)

# CloudWatch（アラーム）
アラームを作成し、遅延が発生した際にサーバ台数を増やします。
アラームでは、ActionとしてAutoScalingPolicyを指定できます。
![image](https://qiita-image-store.s3.amazonaws.com/0/70673/b9eb4935-e0e8-aead-236b-b3b6fc8a4cab.png)

# 試験スクリプト
PHPで指定した時間スリープするようにしました。
CloudWatchのカスタムメトリクス画面にて、3秒間のレスポンスタイムになった事を確認しました。
```<?php
sleep(3);                                                                               
echo "hello";
?> 
```
![image](https://qiita-image-store.s3.amazonaws.com/0/70673/b673b6f5-04fb-dd9f-1232-8102ea331bbe.png)

# 試験
CloudWatchアラームと試験スクリプトのsleep時間を調整します。
AutoSalingが発動し、ELB配下に組み込まれたら成功です。

# 課題
コンテンツ同期が大変かも？
AMIを最新化するか、AutoSaling発動時にGitからコンテンツを取得するような仕組みが必要そうです。
サーバを減らす処理のトリガーが迷いどころです。今回は、AutoScalingPolicyを手動実行する想定にしました。
grunt watch が遅い時の改善方法

Grunt を使うからには [grunt-contrib-watch](https://github.com/gruntjs/grunt-contrib-watch#optionsnospawn) でファイルの変更を監視して自動ビルドしたいのですが、どうも遅い。

```bash
$ grunt watch

Running "watch" task
Waiting...OK
>> File "src/sass/screen.scss" changed.

Running "compass:dist" (compass) task
overwrite app/css/screen.css (0.333s)
Compilation took 0.342s

Running "cssmin:add_banner" (cssmin) task
File app/css/screen.min.css created.

Running "cssmin:minify" (cssmin) task
File app/css/app.min.css created.
File app/css/screen.min.css created.

Done, without errors.
Completed in 12.602s at Sat Oct 19 2013 16:26:32 GMT+0000 (UTC) - Waiting...
```

タスクの実行自体は1秒もかかっていないのに、全体では12秒ほどかかっていました。

Gruntfile の設定を見直すことで改善できたので、そのやり方をメモしておきます。


<!--more-->


`grunt watch` のボトルネックは、ファイルの変更を検知後にタスクプロセスを子プロセスとしてスポーンさせる部分にあるようです。
したがって、子プロセスとしてタスクを起動するオプションを無効にすることで回避できます。

以下のように、Gruntfile.js 内で `spawn: false` を指定してやれば OK です。

```js
module.exports = function(grunt) {
  grunt.initConfig({
    // ...
    watch: {
      options: {
        spawn: false
      },
      css: {
        files: ['src/sass/*.scss'],
        tasks: ['compass', 'cssmin']
      }
    }
  });
  // ...
```

これで大幅にスピードが改善されました。

```bash
$ grunt watch

Running "watch" task
Waiting...OK
>> File "src/sass/screen.scss" changed.


Running "compass:dist" (compass) task
identical app/css/screen.css (0.319s)
Compilation took 0.328s

Running "cssmin:add_banner" (cssmin) task
File app/css/screen.min.css created.

Running "cssmin:minify" (cssmin) task
File app/css/app.min.css created.
File app/css/screen.min.css created.

Running "watch" task
Completed in 0.712s at Sat Oct 19 2013 16:27:58 GMT+0000 (UTC) - Waiting...
OK
>> File "src/sass/screen.scss" changed.
```

12秒が0.7秒に。イェーイ！


参考
----
- [Why Watch is so slow compared to Regarde · Issue #69 · gruntjs/grunt-contrib-watch](https://github.com/gruntjs/grunt-contrib-watch/issues/69)
- [gruntjs/grunt-contrib-watch#optionsnospawn](https://github.com/gruntjs/grunt-contrib-watch#optionsnospawn)
Google Chromeでjsにブレイクポイントを貼ると変数の中身が確認しやすい

## サンプルコード

```html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    </head>

    <body>
        <button id='sample'>SAMPLE</button>

        <script type="text/javascript" src="sample.js"></script>
    </body>
</html>
```

```js
$(function(){
    $('#sample').on('click', function(){
      var hoge = 'hoge';
      var test = 'テストだよー';
      var get_text = $('#sample').text();
      var long_text = 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん';
      console.log(hoge);
      console.log(test);
      console.log(get_text);
      console.log(long_text);
      alert('ここにブレイクポイントを貼って値を確認してみてください');
    });
});
```

## やり方

* `Google Chrome`のデベロッパーモードを起動
* `Sources`タブに移動
* `sample.js`を選択
* `alert`文のところにブレイクポイントを設置（行数の書いてある場所をクリック）
* その状態で`sample`ボタンをクリック

![スクリーンショット 2015-06-21 16.34.46.png](https://qiita-image-store.s3.amazonaws.com/0/67471/726dd281-5410-8d22-1723-56f30711b36b.png)

そうすると変数のすぐ脇に、その変数には現在なんの値が入っているかが表示されます。
デベロッパーモード中に右の方の枠の`scope`内に変数は表示されているんですが、コード上で変数の中身が全て表示されているのでかなり見やすいし確認しやすいですね。
ただ`long_text`のように変数内の文字列等が長いものになると表示し切れないことがあるようです。
これを知ったのが割と最近だったので最近のアップデートで表示されるようになった…？
ちょっと情報は追っていないので分かりませんが、便利になったことに違いはありませんね:smile:
PHPMD はヒステリックすぎるので無視しよう

[PHPMD (PHP Mess Detector)](http://phpmd.org/) は、PHP のコードを静的解析して、潜在的なバグや無意味なブロックを発見してくれるツールです。
が、しばしば問題ないブロックにもケチをつけてきます。

たとえばこんなコード。

```php
public function setUp() {
    // 警告: Avoid using static access to class 'parent' in method 'setUp'.
    parent::setUp();

    $this->Account = ClassRegistry::init('Account');
}
```

親クラスの setUp() メソッドを呼んだけで、「静的アクセスするな」と怒られます。じゃあどうやってオーバーライドすればいいんだよ、と思います。メンバ定数にアクセスしようと `self::` を使っても出ます。オブジェクト指向を否定してんのか。

`@SuppressWarnings` アノテーションをクラスの PHPDoc に書くことでこの警告は出なくなりますが、本当に間違った静的アクセスを行っていても無視されるようになってしまいます。困ったもんです。

ほかにも、if-else を使うと下のような警告を出します。

```php
public function step() {
    if ($this->find('count') < 1) {
        $this->foo();
    } else {
        // 警告: The method step uses an else expression. Else is never necessary and you can simplify the code to work without else.
        $this->bar();
    }
```

「else なんて必要ねえよ。else の必要ない書き方しろよ。」と言ってきます。言いたいことはわかりますが、リファクタリングした結果最もメンテナンス性が高くなるなら、if-else 構文を使っても全然問題ないはずです。else を使うだけで警告レベル High で糾弾するのはいかがなものでしょうか。


まとめ
------
PHPMD はヒステリーなので、レポート結果をあまり深刻に受け取らないようにしましょう。


参考
----
- [PHPMD - PHP Mess Detector](http://phpmd.org/)
- [php - PHPMD avoid static access to parent - Stack Overflow](http://stackoverflow.com/questions/18604179/phpmd-avoid-static-access-to-parent)
McAfee MySQL Audit Plugin の負荷はどれくらい？

[McAfee MySQL Audit Plugin を使うと簡単に監査ログが取れるようになる](http://qiita.com/1000k/items/14022083de30ed0c9d65) という記事で Audit の取得方法を紹介しました。が、一般的に Audit 処理は大きな負荷がかかります。

Audit プラグインを有効にすることで性能劣化はどれくらい発生するのか、検証してみました。


Audit プラグインの設定値
------------------------
MySQL CLI から Audit プラグイン関連の設定値を確認します。以下の通り、ほぼインストールしたままの状態です。

```
mysql> SHOW VARIABLES LIKE 'audit_%';
+---------------------------------+----------------------------+
| Variable_name                   | Value                      |
+---------------------------------+----------------------------+
| audit_checksum                  |                            |
| audit_delay_cmds                |                            |
| audit_delay_ms                  | 0                          |
| audit_json_file                 | OFF                        | <- Audit 有効時は ON にする
| audit_json_file_flush           | OFF                        |
| audit_json_file_sync            | 0                          |
| audit_json_log_file             | mysql-audit.json           |
| audit_json_socket               | OFF                        |
| audit_json_socket_name          | /tmp/mysql-audit.json.sock |
| audit_offsets                   |                            |
| audit_offsets_by_version        | ON                         |
| audit_record_cmds               |                            |
| audit_record_objs               |                            |
| audit_uninstall_plugin          | OFF                        |
| audit_validate_checksum         | ON                         |
| audit_validate_offsets_extended | ON                         |
| audit_whitelist_users           |                            |
+---------------------------------+----------------------------+
```


ベンチマークの条件
------------------
mysqlslap を使えば簡単にベンチマークが取れます。詳しい使い方は [mysqlslap で MySQL の負荷テストをする方法 - Qiita](http://qiita.com/1000k/items/8fe32ed2720c97e3c81f) をご覧ください。

```
mysqlslap \
  --no-defaults \
  --concurrency=100 \
  --iterations=5 \
  --number-int-cols=2 \
  --number-char-cols=3 \
  --engine=innodb \
  --auto-generate-sql \
  --auto-generate-sql-add-autoincrement \
  --auto-generate-sql-load-type=key \
  --auto-generate-sql-write-number=1000 \
  --number-of-queries=100000 \
  --host=localhost \
  --port=3306 \
  --user=root
```


結果
----
**10%～20% 程度の性能劣化** が見られました。カツカツのシステムで使う場合は注意が必要かもしれません。


Audit 無効時:

```
Running for engine innodb
Average number of seconds to run all queries: 15.935 seconds
Minimum number of seconds to run all queries: 15.487 seconds
Maximum number of seconds to run all queries: 16.717 seconds
Number of clients running queries: 100
Average number of queries per client: 1000
```

Audit 有効時:

```
Running for engine innodb
Average number of seconds to run all queries: 19.083 seconds
Minimum number of seconds to run all queries: 18.763 seconds
Maximum number of seconds to run all queries: 19.902 seconds
Number of clients running queries: 100
Average number of queries per client: 1000
```
mysqlslap で MySQL の負荷テストをする方法

mysqlslap は MySQL の負荷テストに使えるツールです。MySQL >=  5.1.4 からはデフォルトで提供されています。

テスト中は `mysqlslap` という DB を自動で作って、そこにクエリを投げまくります。

以下に基本的な使い方をメモしておきます。


<!--more-->


使い方
------
`mysqlslap -?` で詳しいヘルプが見られます。典型的な例は下記。

```bash
mysqlslap \
  --no-defaults \
  --concurrency=50 \
  --iterations=1 \
  --number-int-cols=2 \
  --number-char-cols=3 \
  --engine=innodb \
  --auto-generate-sql \
  --auto-generate-sql-add-autoincrement \
  --auto-generate-sql-load-type=key \
  --auto-generate-sql-write-number=1000 \
  --number-of-queries=100000 \
  --host=localhost \
  --port=3306 \
  --user=root \
  --csv=/tmp/bench_result.csv
```

| パラメータ | 意味 |
|------------|------|
|no-defaults|my.cnf に書かれたデフォルト値を無視する。このオプションは先頭に付ける必要がある|
|concurrency|同時に接続してくるクライアントの数|
|iterations|テストの試行回数|
|number-int-cols|テストテーブルに作る INT 型カラムの数|
|number-char-cols|テストテーブルに作る VARCHAR 型カラムの数|
|engine|使用する DB エンジン|
|auto-generate-sql|テストで使用する SQL 文を自動で生成する|
|auto-generate-sql-add-autoincrement|自動で作ったテーブルに AUTO_INCREMENT カラムを追加する|
|auto-generate-sql-load-type|クエリのタイプ。`[mixed|update|write|key|read]`から選ぶ。デフォルトは `mixed`|
|auto-generate-sql-write-number|スレッド毎の INSERT 文の発行数。デフォルトは 100|
|number-of-queries|各クライアントが投げるクエリの上限数。正確にこの値にはならない|
|host|ホスト|
|port|ポート番号|
|user|ベンチマークを実行するユーザー。DB 作成権限が無いユーザーを指定するとテストできないので注意！|
|csv|結果を CSV 形式で取得したい時は、ここに出力先のパスを書く|

結果は以下のように出力されます。

```
Benchmark
        Running for engine innodb
        Average number of seconds to run all queries: 16.086 seconds
        Minimum number of seconds to run all queries: 16.086 seconds
        Maximum number of seconds to run all queries: 16.086 seconds
        Number of clients running queries: 50
        Average number of queries per client: 2000
```


参考
----
- [MySQL :: MySQL 5.1 リファレンスマニュアル :: 7.15 mysqlslap — クライアント負荷エミュレーション](http://dev.mysql.com/doc/refman/5.1/ja/mysqlslap.html)
- [MySQL標準 負荷測定ツール mysqlslap - 祈れ、そして働け ～ Ora et labora](http://d.hatena.ne.jp/tetsuyai/20110209/1297253834)
Vagrant 1.6.x にアップデートしたら動かなくなった

Windows 環境で Docker が使いたくて Vagrant を 1.5.1 から 1.6.3 にアップグレードしたら、`vagrant up` するたびにエラーが出るようになってしましました。

```bash
$ vagrant up

Bringing machine 'myapp' up with 'virtualbox' provider...
==> myapp: Box 'myapp' could not be found. Attempting to find and
install...
    myapp: Box Provider: virtualbox
    myapp: Box Version: >= 0
==> myapp: Adding box 'myapp' (v0) for provider: virtualbox
    myapp: Downloading: file://C:/static/boxes/CentOS-6.3-x86_64-v2013010
1.box
    myapp: Progress: 8% (Rate: 201M/s, Estimated time remaining: 0:00:02)
    myapp: Progress: 53% (Rate: 203M/s, Estimated time remaining: 0:00:01
    myapp: Progress: 56% (Rate: 108M/s, Estimated time remaining: 0:00:01
    myapp: Progress: 76% (Rate: 103M/s, Estimated time remaining: 0:00:01
    myapp: Progress: 89% (Rate: 91.7M/s, Estimated time remaining: --:--:
    myapp: Progress: 100% (Rate: 85.8M/s, Estimated time remaining: --:--
    myapp:
The box failed to unpackage properly. Please verify that the box
file you're trying to add is not corrupted and try again. The
output from attempting to unpackage (if any):
```

GitHub の issue レポートにワークアラウンドが見つかりました。

[The executable 'bsdtar' Vagrant is trying to run was not found in the %PATH% variable · Issue #3674 · mitchellh/vagrant](https://github.com/mitchellh/vagrant/issues/3674)

これによると、古いバージョンが入った Windows に 1.6.x をインストールすると、bsdtar (Vagrant Box を解凍するツール？) がなぜかインストールされないそうです。実際に `C:\HashiCorp\Vagrant\embedded\gnuwin32\bin` を見てみたところ、`bsdtar.exe` は見つからず、`libarchive.dll` というファイル1つしかありませんでした。

そんなわけで以下の手順を行ったところ、無事起動するようになりました。

 1. 古い Vagrant をアンインストールする。
 1. `c:\HashiCorp\` を削除する。
 1. 再度インストーラーで Vagrant 1.6.3 をインストールする。

なおスレッドの書き込みによると、コントロールパネルの「プログラムと機能」から「修復」を選んでも直るらしいです。(未検証)
Chef Solo ではなく Chef Client Local Mode を使おう

2014/06/24 に Opscode 公式ブログで [From Solo to Zero: Migrating to Chef Client Local Mode](http://www.getchef.com/blog/2014/06/24/from-solo-to-zero-migrating-to-chef-client-local-mode/) という記事が公開されました。記事を要約すると「Chef Solo はオワコンだから Chef Client Local Mode を使え」ということのようです。


Chef Client Local Mode (旧 Chef Zero) って？
----------------
Chef Client Local Mode (旧 Chef Zero) は Chef Solo の全ての機能を備えており、Chef Server に移行する際にも楽です。Chef Client 11.8.0 から採用されました。実行するには `chef-client` に `--local-mode` または `-z` オプションを付けます。

Local Mode ではローカルのファイルシステムから揮発性の Chef Server を作り、
Server-Client 構成と同じオペレーションが行われます。つまり Chef Server が無ければできなかった高度な機能を、サーバーレスで気軽に行うことができます。

Chef Server のフル機能を、Chef Solo 同様の気軽さで使えるのが、Chef Client Local Mode と言っていいでしょう。


Chef Solo から Chef Client Local mode に移行するべき理由
------------------------------------------------------
1\. Local Mode なら Server-Client で使える全ての機能 -- environments, roles, (encrypted) data bags -- が使える。ノードやレシピの検索機能も使える。

2\. 特別なツールや knife プラグインは必要無い。

3\. レシピ実行環境が Solo か Server かの分岐を書く必要が無くなる。例えば以下のようなコード。

```rb
if Chef::Config[:solo]
  # do something
else
  # do something else
end
```

4\. `chef_zero` を Test Kitchen の provisioner に使う際、 "fixture node objects" をテストデータとして使える。

5\. 後に Chef Server 構成を使いたくなった時にすんなり移行できる。

今すぐ Chef Solo をお払い箱にする必要はありませんが、公式に deprecated 扱いされているので、今後は Solo よりも Local Mode を使うことをお薦めします。これから Chef を始める人は、chef-apply か local mode を使うといいでしょう。


Vagrant で使う時はどうする？
----------------------------
Vagrant 1.7.0 より、Chef Client Local mode が使えるようになりました。単純に provisioner に `chef_zero` を指定するだけで動作します。

[Chef Zero - Provisioning - Vagrant Documentation](https://docs.vagrantup.com/v2/provisioning/chef_zero.html)

```rb
Vagrant.configure("2") do |config|
  config.vm.provision "chef_zero" do |chef|
    # Specify the local paths where Chef data is stored
    chef.cookbooks_path = "cookbooks"
    chef.roles_path = "roles"
    chef.nodes_path = "nodes"

    # Add a recipe
    chef.add_recipe "apache"

    # Or maybe a role
    chef.add_role "web"
  end
end
```


参考
----
- [From Solo to Zero: Migrating to Chef Client Local Mode | Chef Blog](http://www.getchef.com/blog/2014/06/24/from-solo-to-zero-migrating-to-chef-client-local-mode/)
- [2014年のChefとInfrastructure as code](http://www.slideshare.net/YukihikoSawanobori/chef-2014)
- [chef-client (executable) — Chef Docs # Run in Local Mode](http://docs.opscode.com/ctl_chef_client.html#run-in-local-mode)
- [chef-solo (executable) — Chef Docs](http://docs.opscode.com/ctl_chef_solo.html)
  - 一番上に warning で「`--local-mode` を検討しなよ」と書いてある。
Sublime Text 2/3 で CakePHP2 の CodeSniffer ルールを適用する

Sublime Text 3 のエディタ上で PHP CodeSniffer を使い、コーディング規約をチェックする方法です。[sublime-phpcs](http://benmatselby.github.io/sublime-phpcs/) プラグインを導入することで、コーディング規約違反のある行がエディタ上に表示されるようになります。

なお、プラグインの公式ページでは phpmd も一緒に導入していますが、[PHPMD はヒステリックすぎて個人的にお勧めしない](http://blog.1000k.net/2013/11/26/phpmd-%e3%81%ae%e9%a0%ad%e3%81%8c%e3%81%8b%e3%81%aa%e3%82%8a-messy/) ので省略します。

<!--more-->

チュートリアル
----
### CodeSniffer をインストールする
```
pear install PHP_CodeSniffer
```

### CakePHP のルールセットをインストールする
```
pear channel-discover pear.cakephp.org
pear install cakephp/CakePHP_CodeSniffer
```

CodeSniffer のルールセットに追加されているか以下のコマンドで確認。

```
$ phpcs -i
The installed coding standards are CakePHP, MySource, PEAR, PHPCS, PSR1, PSR2, Squiz and Zend
(CakePHP が含まれていれば OK)
```

### Sublime Text 3 に CodeSniffer プラグインをインストールする
"Package Control: Install Package" で `Phpcs` をインストールするだけ。

(Package Control 自体のインストール方法は [Installation - Package Control](https://packagecontrol.io/installation) を参照)

### Sublime Text の設定
"Preferences > Package Settings > PHP Code Sniffer > Settings - User" を開き、以下のキーを設定する必要があります。

- phpcs_php_path
- phpcs_executable_path
- php_cs_fixer_executable_path

記入例:

```json
{
    "phpcs_php_path": "C:\xampp\php\phpcs",
    "phpcs_executable_path": "C:\xampp\php\phpcs.bat",
    "phpcs_additional_args": {
        "--standard": "CakePHP"
    },
    "php_cs_fixer_executable_path": "C:Users{ユーザー名}AppDataRoamingComposervendorbin"
}
```

### (Windows のみ) phpcs.py を修正する
Windows では、このまま phpcs が実行しても何も結果が表示されません。
(`Ctrl + @` でコンソールを開くと `[Windows Error]` と出て途中で止まっている)

以下の手順でプラグインのコードを修正してください。

1. "Preferences > Browse Packages..." でパッケージディレクトリを開く。
1. "Phpcs > phpcs.py" を開く。
1. 169行目を以下のように修正 (パラメータに `shell=True` を追加) する。

```
# proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, startupinfo=info, cwd=home)
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, startupinfo=info, cwd=home, shell=True)
```

### プラグインを実行する
PHP ファイルを開いたタブで `Ctrl + P > PHP Code Sniffer: Sniff This File` とタイプすれば、コーディング規約違反を検知してくれます。

これでコーディングルール違反でチームメイトにディスられるリスクを回避できるようになりました。


オプション
---------
### 保存時に Sniff されるのを止める
プラグインインストール後のデフォルトだと、保存するたびに規約違反がサジェストされます。
鬱陶しい場合は "Preferences > Package Settings > PHP Code Sniffer > Settings - User" に下記を追加することでオフにできます。

```json
{
  "phpcs_execute_on_save": false
}
```


参考
----
- [sublime-phpcs](http://benmatselby.github.io/sublime-phpcs/)
- [php - Custom ruleset for phpcs using PHPStorm - Stack Overflow](http://stackoverflow.com/questions/10585274/custom-ruleset-for-phpcs-using-phpstorm)
- [cakephp/cakephp-codesniffer · GitHub](https://github.com/cakephp/cakephp-codesniffer)
- [fabpot/PHP-CS-Fixer · GitHub](https://github.com/fabpot/PHP-CS-Fixer)
- [sublime-phpcsでPSR-2準拠のコーディング - だいたいよくわからないブログ( ´_ゝ`)](http://matsu-chara.hatenablog.com/entry/2013/12/27/125026)
tmuxはじめました

とあるきっかけで開発効率強化ウィークに入りました。まずはターミナルをもっと効率的にすべく、tmux を習得することにしました。


tumxとは？
----------
- ターミナルマルチプレクサ (端末多重化ソフトウェア, 仮想端末マネージャー) のひとつ
  - ほかには GNU screen が有名
- 読み方は "ティーマックス"

### できること
- 1つの端末で複数の仮想端末を起動できる
- 仮想端末の画面を自由に分割・統合できる
- マウスを使わずキーボードだけでコピペできる
- デタッチ(切り離し)とアタッチ(接続)により、ネットワークが切れても同じセッションを再開できる
- ステータスバーなどでターミナルの情報をリッチにできる
  - 現在時刻、Wi-Fi接続強度、バッテリー残量なども表示できる
- 設定ファイルで高度にカスタマイズできる

### tmuxの構成
tmuxはサーバー/クライアント構成を取る。

- tmuxサーバー(セッション)
  - tmux起動時に生成される
  - セッションを管理するプロセス
- tmuxクライアント(pty; 仮想端末)
  - tmuxセッションへ接続(アタッチ)しているプロセス(pty)

### 画面の内包関係
`セッション > ウィンドウ > ペイン`

- セッション: ウィンドウの集まり。
- ウィンドウ: ペインを管理する領域。タブのイメージ。
- ペイン: ウィンドウを分割した領域。


インストール
------------
yum ユーザーは EPEL リポジトリからインストールが可能。

```
sudo yum install -y tmux
```


チュートリアル
--------------
### 起動

`tmux` または `tmux new-session` で新規セッションを起動すると、新しい仮想端末が開く。

### ペインの操作

`C-b %` でペインを分割し、`C-b n` で次のウィンドウに移動します。
`C-b ?` でヘルプが開くので、片方のペインにヘルプを表示した状態で、もう片方でいろいろ実験してみると理解が進みます。

### デタッチ

仮想端末上で `C-b d` で、端末がセッションからデタッチされます。
デタッチ状態ではセッションは残っているので、再度 `tmux attach -t セッション番号` と入力すれば、最後の画面から再開できます。


基本操作
--------
### セッションの操作

| operation | command |
|-----------|---------|
| セッションの作成 | `tmux` or `tmux new-session` |
| セッションの確認 | `tmux list-sessions` |
| 接続されているクライアントの確認 | `tmux list-client` |
| セッションのアタッチ | `tmux attach -t セッション番号` or `tmux a` (`-d` を指定すると、そのセッションに接続しているほかのクライアントはデタッチされる) |
| セッションの削除 | `tmux kill-session [-t セッション番号]` (引数を指定しなければ直近のセッションが削除される)|
| 全セッションの削除 | `tmux kill-server` |

### ウィンドウの操作

| operation | command |
|-----------|---------|
| ヘルプ表示 | `C-b ?` (閉じるには `q`) |
| ウィンドウ作成 | `C-b c` |
| ウィンドウ削除 | `C-b &` (ステータスバーに確認が出るので `y` で削除) |
| ウィンドウ名変更 | `C-b ,` |
| ウィンドウ一覧表示/移動 | `C-b w` (カーソルキーで選択、[Enter] で表示)|
| 前のウィンドウに移動 | `C-b p` |
| 次のウィンドウに移動 | `C-b n` |
| 最後に操作したウィンドウへ移動 | `C-b l` |
| 指定したウィンドウへ移動 | `C-b ウィンドウ番号` |
| デタッチ | `C-b d` |

### ペインの操作

| operation | command |
|-----------|---------|
| ペイン番号表示 | `C-b q` or `C-b :display-panes` |
| 指定したペインへ移動 | `C-b q ペイン番号` (インジケーターが表示されている間に番号を入力する) |
| 最後に操作したペインへ移動 | `C-b ;` |
| ペイン分割 (水平方向) | `C-b "` |
| ペイン分割 (垂直方向) | `C-b %` |
| ペイン分割解除 | `C-b !` |
| ペイン強制終了 | `C-b x` (ステータスバーに確認が出るので `y` で削除) |
| ペイン間移動 | `C-b o` |
| ペイン入れ替え | `C-b {` |


カスタマイズ
------------
`~/.tmux.conf` にカスタマイズ設定を書き込むことができます。
yum でインストールした場合は `/usr/share/doc/tmux-1.6/examples/` 配下にサンプルファイルがあります。vimmer は [vim-keys.conf](https://github.com/jordansissel/tmux/blob/master/trunk/examples/vim-keys.conf) を設定するとペイン操作が楽になるかもしれません。


参考
----
- [OpenBSD manual pages](http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/tmux.1?query=tmux&sec=1)
  - 公式マニュアル。英語。
- [tmuxを使い始めたので基本的な機能の使い方とかを整理してみた - 完熟トマト](http://kanjuku-tomato.blogspot.jp/2014/02/tmux.html)
  - 概念図やスクリーンショット満載でわかりやすいです。
- [tmux基本のコマンド — nato's memo 1.0 documentation](http://room6933.com/mymemo/tmux/tmux-basic.html)
- [Vim - ターミナルマルチプレクサ tmux をカスタマイズする - Qiita](http://qiita.com/b4b4r07/items/01359e8a3066d1c37edc)
  - 使えるカスタマイズの例。zsh と連携して、ログイン時にいきなり tmux セッションにアタッチする方法など。