OmniAICreator/Qiita-1.07M huggingface dataset:
IE11でSVGで指定したサイズからはみ出した要素が表示されてしまう。


[svg.js](http://svgjs.com) を試してみようと次のような簡単なサンプルを書いてみた。

```html:test.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<title>SVG TEST</title>
</head>
<body>
    <h1>SVG TEST</h1>
    <div id="drawing"></div>
    <!-- SCRIPTS -->
    <script src="svg.min.js"></script>
    <script>
        window.onload = function() {
            var draw = SVG('drawing').size(100, 100);
            draw.circle(100).attr({"fill":"red"}).move(50,50);
            draw.rect(100, 100).attr({"fill":"none", "stroke": "black"});
        }
    </script>
</body>
</html>
```
これをchromeで表示すると、
![スクリーンショット 2016-07-30 15.28.42.png](https://qiita-image-store.s3.amazonaws.com/0/31482/4bd75cc8-66b4-c537-3639-624e29ef794e.png "スクリーンショット 2016-07-30 15.28.42.png")
このように表示されるが、IE11だと次のようになる。
![スクリーンショット 2016-07-30 15.28.53.png](https://qiita-image-store.s3.amazonaws.com/0/31482/48ed88b4-90df-de75-9e3f-f8fd29a5c70e.png "スクリーンショット 2016-07-30 15.28.53.png")

どうも、IEではデフォルトのoverflow属性が"visible"になっているもよう。 
以下のように明示的にoverflow属性に"hidden"を指定してやれば、IEでもchromeと同様の表示になった。

```javascript
var draw = SVG('drawing').size(100, 100).attr({"overflow":"hidden"});
```
めでたし、めでたし。
aliexpress 電子部品 2016

aliexpressで電子部品を買った時にどれくらいで届いたかの記録です。

送料無料で、2週間ぐらいで届く店が良いです。

特に記載が無い限り、送料無料で注文しています。
でも、１個だと無料だけど、２個目から送料がかかる場合が多いので、購入の仕方は工夫が必要です。

# good

## DYKB Store
* http://www.aliexpress.com/store/2132223
* order : 2016-07-24
* deliver : 2016-08-01

## WeMos Electronic
* http://www.aliexpress.com/store/1331105
* order : 2016-06-26
* deliver : 2016-07-06

## KELI Electronics Technology
* http://www.aliexpress.com/store/623118
* order  : 2016-07-09
* delver : 2016-07-17

## aliship
* http://www.aliexpress.com/store/1543206
* order : 2016-06-27
* deliver : 2016-07-05
* EMSで送ってみた場合の実績です。

## GOLD MORALS INDUSTRY COMPANY
* http://www.aliexpress.com/store/518673
* order : 2016-06-26
* deliver : 2016-07-05

# normal

## Best & Fastest & Lowest For you 
* http://www.aliexpress.com/store/1495338
* order : 2016-07-09
* deliver : 
* 発送は早かったけど、配送業者起因で中国国内で止まっている。

# bad

## All good free shipping 
* http://www.aliexpress.com/store/1916536
* order : 2016-06-26
* 一ヶ月たっても届かない。　トラックもできないし、Open Disputeするかなぁ。
querySelectorAll 等で取得した NodeList の先頭だけ削除

配列の先頭を削除する場合は ```shift()``` を使えば良いのですが
配列みたいに使える NodeList(querySelectorAll などで取得)
では ```shift()``` が使えなくて悲しい。  

特に NodeList に拘りはないので、泥臭くforで先頭だけ消して配列に。
if 使ってコード増えるのも面倒くさいので若干手抜き。

```js
var hoge = document.querySelectorAll("h1");
var newHoge = new Array;

for(var i=1 ; i < hoge.length; i++){
  newHoge.push(hoge[i]);
}
```
i=0 でなくて i=1 で始めて先頭飛ばした。
他にいい方法ないだろうか。
ローカルの git リポジトリを Bitbucket に追加する手順

# ローカルの git リポジトリを Bitbucket に追加する手順

半年くらい明けるときれいに忘れてしまっている私向けの備忘録として残す。
2016-07-30 に Windows 環境で実施した手順です。

本トピックの情報は、検証なく公開しています、利用者の責任において使用ください。

## 前提

- ローカル Windows に SourceTree + git 管理のリポジトリがあり、それを SSH 経由で接続する。
- SourceTree がインストール済み
- 少し前に作った Bitbucket アカウントは Attrasian アカウントに移行されるので、本手順の実行前に指示にしたがって移行しておく必要がある。
- Bitbucket に作成したリポジトリには SSH 公開鍵を登録しておく。 SSH 登録は、おまけを参照。

## 手順

1. Bitbucket にログインして、リポジトリを作成する。
2. 上部メニュー [リポジトリ] > [リポジトリの作成] をクリックして、Bitbucket リポジトリを作成する。
3. SourceTree のリポジトリを表示して、ツールバーの [設定] ボタンをクリックする。
4. リポジトリ設定ダイアログの [リモートリポジトリのパス] の [追加] ボタンをクリックする。
5. [リモート名] に `origin` もしくは [デフォルトリモート] をチェック状態にする。
6. リモートの詳細設定ダイアログでの [URL/パス] に、次の URL を指定する。  
```
ssh://git@bitbucket.org/bitbucketに登録したユーザ名/作成したリポジトリ名.git
```
7. [ユーザ名] は、、Bitbucket に登録したユーザ名を指定して、[OK] ボタンを クリックする。
8. SourceTree ツールバーの [プッシュ] ボタンをクリックする。


## おまけ: SSH 登録の方法も忘れてた。

- ゴールは、「私用の公開鍵、秘密鍵を作成して、公開鍵を Bitbucket、秘密鍵を Pageent に登録する」こと。

- PuTTY がインストール済みの前提。

### Bitbucket サイト

1. Bitbucket にログインし、画面右上のアバター > [アカウントの管理] をクリックする。
1. アカウント設定画面で、左メニューから [SSH キー] をクリックする。
1. SSH キー画面で [鍵を追加] ボタンをクリックし、SSH 鍵を追加ダイアログを開いておく。

### Windows - PuTTY Key Generator

1. PuTTY Key Generator (puttygen.exe) を開く。
1. [Parameters] > [Type of key to generate:] を `SSH-2 RSA` に変更、もしくは確認。
1. [Actions] > [Generate] ボタンをクリックし、上部の [Key] フレームの中でプログレスバーが消えるまでマウスをぐるぐる。
1. [Key] フレームの [Public key for pasting into OpenSSH authorized_keys file:] に `ssh-rsa` で始まる文字列が出力される。これが公開鍵。
1. この公開鍵文字列は、**スクロールさせて最後まで** コピーする。
1. Bitbucket サイトの最後の手順で開いたダイアログの [Key] に貼りつける。 **注意点** を参照のこと。
1. [Save private key] ボタンをクリックして、秘密鍵を適当なフォルダに保存する。拡張子は、`ppk` にしておくと便利。
1. Windows 通知領域の [Pageant (PuTTY Authentication Agent)] を右クリックし、[View Keys] をクリックする。
1. Pageant Key List ダイアログの [Add Key] ボタンをクリックし、開いたダイアログで、先に保存した秘密鍵を指定する。

### 注意点

- PuTTY Key Generator には [Save public key] ボタンで出力されたファイルの内容を Bitbuket サイトに貼りつけても、Bitbuket は正しいキーだと認識してくれない。
LabVIEW で IRKit (NatureRemo)


# LabVIEWでIRKit (NatureRemo)

IRKit(学習機能付リモコン)を使って、ＴＶや扇風機などのリモコン操作、やってみました。
WiFi経由でhttpクライアント関数で読み取ったデータを送信するだけなので、LabVIEWからも簡単にできました。

学習リモコンとして使うならiPhone/Androidアプリをダウンロードすればいいだけ、なのですが、温度センサーなどを組み合わせてちょっとした自動化にも使えそう、ということでLabVIEWで作ってみました。

# 初期設定はiPhone/Androidアプリで

残念ながら、初期設定には、iPhone/Androidアプリが必須です。WiFi環境も必要です。
それとIRKitにはバッテリーがないので、使うときはUSB給電が必要。

# IRKitでリモコン操作

IRKitとの通信は httpGet/httpPostなので、LabVIEWのhttpクライアント関数だけでできます。

## 手順

操作したいリモコンの赤外線信号をIRKit経由で読み取って、読み取った赤外線信号のデータをhttpPostすれば、IRKitから赤外線で対象の家電にリモコンの信号が送信される、という仕組みです。

## IRKitのIPアドレスの取得
http通信するのにIRKitのIPアドレスが必要ですが、それを調べるのが一番の難関かもしれません。
DHCPのみでIPアドレスを固定できないので、IRKitを電源On/OffするたびにIPアドレスが変わる可能性があります。
IRKitの公式サイトでは Bonjour で調べる方法が紹介されていましたが、Windowsには標準には入っていません。
コマンドプロンプトから、IRKitのデバイス名に".local"をつけてpingするとIPアドレスが表示されるようです。

こんな感じ
`> ping <IRKit名>.local`


## リモコン信号の取得

IRKitに向けてリモコンボタンを押した後、2,3秒のタイムラグをおいてLED点滅した後、httpGetすると、JSON形式文字列データでリモコン信号のデータが受信できます。
一度しか読み取れないので、もし、失敗したら、もう一度、リモコンボタンを押すところからやり直します。

VIスニペット
![IRKit_Messages_GET_vi.png](https://qiita-image-store.s3.amazonaws.com/0/43526/15fd084b-54d7-f0f6-0397-da2748b7f0b8.png)


## リモコン信号の送信

取得したリモコン信号データ(JSON形式文字列)をhttpPostする

VIスニペット
![IRKit_Messages_POST_vi.png](https://qiita-image-store.s3.amazonaws.com/0/43526/ff5dbb30-a84f-6208-0817-4e05d49b886a.png)


# アプリケーション作ってみた

簡単なアプリケーションにしてみました。githubにソース公開します。

[LvIRKit github](https://github.com/alucky4416/LvIRKIT)

画面イメージ
![LvIRKit_Panel.png](https://qiita-image-store.s3.amazonaws.com/0/43526/9dfd6f69-05a4-b105-0edd-c1863967d0b7.png)

LabVIEW 2014で作成。Toolkitやドライバは特に必要ありません。


# 感想
~~IRKitはAmazonで7～8千円で手に入る。~~ 電子工作しなくても手近な家電を操作できるようになるので便利。
温度センサーと組み合わせれば、気温にあわせて扇風機のOn/Offを自動化とか手軽に実現できそう。

欠点、というか不便なところもある。
IRKitというか赤外線リモコンだと、機器の状態が取得できない。
扇風機にしてもＴＶにしても電源ボタンを押すという操作はできても、実際にOnなのかOffなのかわからない。
目の前にあれば人間が判定できるが、それでも反応が遅いとつい連打してしまって点いたり消えたり繰り返して気持ち悪いことがある。
あとは、スマフォのアプリだとスマフォごとに学習操作が必要なので、データを簡単に共有できる方法があるといいなと思う。

# Tips
IRKit公式サイトでは curl を使って解説していますが、Windowsには標準では入ってません。
"Git for Windows"にcurlコマンドが含まれていますので、もし、Gitを使っていて、"Git for Windows"をインストールしているなら、Git bashから curlコマンドが使えます。
-> 最近のWindows10にはcurlも入っています。

# IRKitの入手
IRKit自体はもう発売終了しているようで、入手は難しくなっているようですが、
IRKitベースの(?)「 Nature Remo(https://nature.global/jp/top )」という製品が発売されているようです。ローカルなネットワークで利用するAPIも公開されているようなので、できれば、そのうち入手して対応できれば、と思っています。（いつになるやら）  
-> NatureRemo miniで試してみたが、ローカルapiで通信成功(200 OK)するが、リモコン信号が送信されない。miniだからなのか、natureremoではローカルAPIは無効になっているのかは不明。NatureRemoをスマホアプリから操作するには問題ないし、とても便利なんだが。
-> 2021/1/31 NatureRemo mini2を購入してリトライ、今度は問題なく動作した。前回miniで動かなかった原因はなんだったのか。

# 参考
- [IRKit(公式)](http://getirkit.com/)
- [Qiita記事「IRKitを使ってターミナルで家電を操作する」](http://qiita.com/kazuqqfp/items/079cdbd1e1997dedc512)
- [Nature Remo](https://nature.global/jp/top)
システムコールの呼び出し方を調べた

詳解Linuxカーネルの10章に関連するシステムコールを呼び出す部分のコードを読んだ。


## カーネルバージョン

v4.1.13

## システムコールの入り口

次の呼び出し方がある。

* int 0x80：割り込みベクタにエントリポイントを入れておく
* SYSENTER：専用レジスタにエントリポイントを入れておく
* SYSCALL：本にはのっていなかったが、ある？[MSR_LSTARを参照するらしい。](http://softwaretechnique.jp/Linux/SystemCall/sc_01.html)

## どうやって呼び分けるのか

必ずリンクされているlinux-vdsoなるものに含まれる？
__kernel_vsyscallはもう実体が存在しないみたい。違うようだ。

~~~
% ldd /bin/ls
        linux-vdso.so.1 =>  (0x00007ffec3d5a000)
~~~

参考になりそうなページを見つけたので、後で読む→[System calls in the Linux kernel. Part 3.](https://0xax.gitbooks.io/linux-insides/content/SysCall/syscall-3.html)

## システムコールの実行

どの呼び出し方でも処理は同じで、raxにシステムコール番号を入れて、system_call関数を呼び出す。
`entry_64.S`をみた。システムコールの呼び出しはこの部分。番号が`NR_syscall_max`よりも大きい場合は実行せずに-ENOSYSで返る。

~~~c
system_call_fastpath:
#if __SYSCALL_MASK == ~0
	cmpq $__NR_syscall_max,%rax
#else
	andl $__SYSCALL_MASK,%eax
	cmpl $__NR_syscall_max,%eax
#endif
	ja	1f	/* return -ENOSYS (already in pt_regs->ax) */
	movq %r10,%rcx
	call *sys_call_table(,%rax,8)
	movq %rax,RAX(%rsp)
1:
~~~

`sys_call_table`のリストは`./arch/x86/include/generated/asm/syscalls_64.h`にある。
これはコンパイル中に生成されているらしい。

~~~
cmd_arch/x86/syscalls/../include/generated/asm/syscalls_64.h := /bin/bash './arch/x86/syscalls/syscalltbl.sh' arch/x86/syscalls/syscall_64.tbl arch/x86/syscalls/../include/generated/asm/syscalls_64.h
~~~

それを読み込むのがここ。`sys_ni_syscall`は初期値（コンパイラのバグ対策とコメントにはある）で、実際はincludeしたファイルの中身が入っている。

~~~c
asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
	/*
	 * Smells like a compiler bug -- it doesn't work
	 * when the & below is removed.
	 */
	[0 ... __NR_syscall_max] = &sys_ni_syscall,
#include <asm/syscalls_64.h>
};
~~~

syscalls_64.hの抜粋

~~~c
__SYSCALL_COMMON(0, sys_read, sys_read)
__SYSCALL_COMMON(1, sys_write, sys_write)
__SYSCALL_COMMON(2, sys_open, sys_open)
__SYSCALL_COMMON(3, sys_close, sys_close)
__SYSCALL_COMMON(4, sys_newstat, sys_newstat)
__SYSCALL_COMMON(5, sys_newfstat, sys_newfstat)
__SYSCALL_COMMON(6, sys_newlstat, sys_newlstat)
__SYSCALL_COMMON(7, sys_poll, sys_poll)
__SYSCALL_COMMON(8, sys_lseek, sys_lseek)
__SYSCALL_COMMON(9, sys_mmap, sys_mmap)
__SYSCALL_COMMON(10, sys_mprotect, sys_mprotect)
__SYSCALL_COMMON(11, sys_munmap, sys_munmap)
__SYSCALL_COMMON(12, sys_brk, sys_brk)
__SYSCALL_64(13, sys_rt_sigaction, sys_rt_sigaction)
__SYSCALL_COMMON(14, sys_rt_sigprocmask, sys_rt_sigprocmask)
__SYSCALL_64(15, stub_rt_sigreturn, stub_rt_sigreturn)
__SYSCALL_64(16, sys_ioctl, sys_ioctl)
__SYSCALL_COMMON(17, sys_pread64, sys_pread64)
~~~


マクロはこんな感じ、なのでシステムコール番号に関数ポインタが入った配列になっている。

~~~c
#define __SYSCALL_64(nr, sym, compat) [nr] = sym,
~~~

なので、このcallではその関数ポインタをよぶ。
補足：アセンブリの括弧のルールをいつも忘れる・・→[X86アセンブラ/GASでの文法](https://ja.wikibooks.org/wiki/X86%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%A9/GAS%E3%81%A7%E3%81%AE%E6%96%87%E6%B3%95)
`sys_call_table`のアドレスにシステムコール番号(rax)*ポインタのサイズ(8)を足したアドレスが関数ポインタになる。

~~~
	call *sys_call_table(,%rax,8)
~~~
セマフォの実装について調べた

詳解Linuxカーネルの5章カーネルの同期処理に関連する、セマフォについて調べた。

## カーネルバージョン

v4.4

## セマフォとは

ロックが取れない場合に、休止状態で実行を待たせる機能。スピンロックよりはCPUを有効活用出来るパターンもあるんだろうと思う。
いろいろ調べた後にに気づいたが、この機構はほとんど使われていない・・・古い機能なのかな？

## 構造体

解放と取得の関数はスピンロックで保護されている。いろんな関数がラップしているが`__up()`や`__down_common()`が操作する関数の本体になる。
`wait_list`には`struct semaphore_waiter`が繋がっていて、`task_struct`が辿れるようになっている。

~~~c
/* Please don't access any members of this structure directly */
struct semaphore {
	raw_spinlock_t		lock;
	unsigned int		count;
	struct list_head	wait_list;
};
~~~

## 初期化論理

nは同時に取れるセマフォの数、`DEFINE_SEMAPHORE`マクロでラップされていて、その場合nは1になる。

~~~c
#define __SEMAPHORE_INITIALIZER(name, n)				\
{									\
	.lock		= __RAW_SPIN_LOCK_UNLOCKED((name).lock),	\
	.count		= n,						\
	.wait_list	= LIST_HEAD_INIT((name).wait_list),		\
}
~~~

## セマフォの解放

`__up()`ではwait_listにつながって待っている最初のプロセスを起床させるだけで、特に難しいことはない。
countはゼロになるまではデクリメントするだけで良い。ここはスピンロックをとっているからアトミック操作になっている。

~~~c
/**
 * up - release the semaphore
 * @sem: the semaphore to release
 *
 * Release the semaphore.  Unlike mutexes, up() may be called from any
 * context and even by tasks which have never called down().
 */
void up(struct semaphore *sem)
{
	unsigned long flags;

	raw_spin_lock_irqsave(&sem->lock, flags);
	if (likely(list_empty(&sem->wait_list)))
		sem->count++;
	else
		__up(sem);
	raw_spin_unlock_irqrestore(&sem->lock, flags);
}
EXPORT_SYMBOL(up);
~~~


## セマフォの取得

`down()`はdeprecatedで、`down_interruptible()`か、`down_killable()`を使えとなっている。それぞれの違いはなんのシグナルに反応するかで、全部のシグナルか、SIGKILLだけかを選べる。

結局のところ、どの関数も`__down_common()`の内部で、次のforループで自分がupされるまでまつ。timeoutか指定のシグナルを受け取った場合は、ロックを取らずに返る。
スピンロックは`schedule_timeout()`の前で解除しているので、スピンロックをとりっぱなしにはならない。

~~~c
	for (;;) {
		if (signal_pending_state(state, task))
			goto interrupted;
		if (unlikely(timeout <= 0))
			goto timed_out;
		__set_task_state(task, state);
		raw_spin_unlock_irq(&sem->lock);
		timeout = schedule_timeout(timeout);
		raw_spin_lock_irq(&sem->lock);
		if (waiter.up)
			return 0;
	}
~~~
システム間通信 パイプの実装について調べた



Linuxのパイプの実装について調べた。

## カーネルバージョン

v4.5.0

## パイプ、名前付きパイプとは

VFSのオペレーションで扱うことが出来る、メモリ上の一時ファイルみたいなもの。
pipefsに作られる場合は普通のパイプで、ファイルシステム上に次のoperationを持って作られた場合、名前付きパイプと呼ぶ。要するにinodeがどこから辿れるか、という違いだけで内部の実装はおなじ。

~~~c
const struct file_operations pipefifo_fops = {
	.open		= fifo_open,
	.llseek		= no_llseek,
	.read_iter	= pipe_read,
	.write_iter	= pipe_write,
	.poll		= pipe_poll,
	.unlocked_ioctl	= pipe_ioctl,
	.release	= pipe_release,
	.fasync		= pipe_fasync,
};
~~~

パイプの作成はpipeシステムコールの延長の、`__do_pipe_flags()`によって行われる。
inode番号は、`get_next_ino()`によって確保される。CONFIG_SMPの場合、CPUごとにプールを作ったりしているが、要するにシステム全体でインクリメントしていく数を順番に割り当てているだけである。オーバーフローすると重複するが、パイプはfdでやり取りされるだけなので、問題ないのだろう。

~~~c
unsigned int get_next_ino(void)
{
	unsigned int *p = &get_cpu_var(last_ino);
	unsigned int res = *p;

#ifdef CONFIG_SMP
	if (unlikely((res & (LAST_INO_BATCH-1)) == 0)) {
		static atomic_t shared_last_ino;
		int next = atomic_add_return(LAST_INO_BATCH, &shared_last_ino);

		res = next - LAST_INO_BATCH;
	}
#endif

	res++;
	/* get_next_ino should not provide a 0 inode number */
	if (unlikely(!res))
		res++;
	*p = res;
	put_cpu_var(last_ino);
	return res;
}
EXPORT_SYMBOL(get_next_ino);
~~~

ちなみに、パイプのファイル名を参照すると、`pipe:[inode番号]`のような表示になる。

~~~
juntaki@lab% sleep 100 | cat &
[2] 1822 1823
juntaki@lab% ls -la /proc/1822/fd
total 0
dr-x------ 2 juntaki juntaki  0  4月 10 15:09 .
dr-xr-xr-x 9 juntaki juntaki  0  4月 10 15:09 ..
lrwx------ 1 juntaki juntaki 64  4月 10 15:09 0 -> /dev/pts/3
l-wx------ 1 juntaki juntaki 64  4月 10 15:09 1 -> pipe:[10810]
lrwx------ 1 juntaki juntaki 64  4月 10 15:09 2 -> /dev/pts/3
~~~

pipefsは外部から参照されないので、パス名は不要なためである。
`pipefs_dname()`で生成している。

~~~c
static char *pipefs_dname(struct dentry *dentry, char *buffer, int buflen)
{
	return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]",
				d_inode(dentry)->i_ino);
}
~~~

## パイプバッファ

パイプを書き込んでから別のプロセスが受け取るまでの間、データを置いておくのがパイプバッファである。
`pipe_inode_info`の`struct pipe_buffer *bufs`からポイントされる場所にある。サイズは`alloc_pipe_info()`で初期化され、サイズは`PIPE_DEF_BUFFERS * 4KB = 64KB`となる。

~~~c
struct pipe_buffer {
	struct page *page;
	unsigned int offset, len;
	const struct pipe_buf_operations *ops;
	unsigned int flags;
	unsigned long private;
};
~~~

~~~c
#define PIPE_DEF_BUFFERS	16
~~~
Linuxのロック共通関数とspinlock

詳解Linuxカーネルの5章カーネルの同期処理に関連する、Linuxのロックについて調べた。
ロックは共通関数が多そうなので、それらの仕組みから調べてみる。

## カーネルバージョン

v4.4

## lock_acquire

lockdep.hに実装されているマクロから、`lock_acquire()`はspinlock, rwlock(読み書き用spinlock), シークエンスロック, mutex, 読み書き用semaphoreで利用されているらしい。
これは[lockdep-design](https://www.kernel.org/doc/Documentation/locking/lockdep-design.txt)のカーネルドキュメントにもあるように、ロックが正しいことを検証するためのデバッグのための関数である。

~~~c
#define lock_acquire_exclusive(l, s, t, n, i)		lock_acquire(l, s, t, 0, 1, n, i)
#define lock_acquire_shared(l, s, t, n, i)		lock_acquire(l, s, t, 1, 1, n, i)
#define lock_acquire_shared_recursive(l, s, t, n, i)	lock_acquire(l, s, t, 2, 1, n, i)
~~~

## LOCK_CONTENDEDマクロ

`lock_acquire()`のあとに呼ばれているマクロで、(少なくとも)スピンロックと読み書き用セマフォで使われているようだ。
`try()`は取得できないとエラー終了するロック取得関数、`lock()`は何らかの方法でロック取得を待つという違いがあると思われる。つまりlockdepのポリシーに従うと、次のロック取得のフローがある。（参考：[LKML](https://lkml.org/lkml/2010/3/2/143)）

~~~
ロック競合がある場合
lock_acquire() -> *(try)()[失敗] -> lock_contended() -> *(lock)() -> lock_acquired()
ロック競合がない場合
lock_acquire() -> *(try)() -> lock_acquired()
~~~

ソースコードは次のようになっている。つまり、上位から関数ポインタとして渡されるlockがそれぞれのロックの違いが一番現れるところかな。

~~~c
extern void lock_contended(struct lockdep_map *lock, unsigned long ip);
extern void lock_acquired(struct lockdep_map *lock, unsigned long ip);

#define LOCK_CONTENDED(_lock, try, lock)			\
do {								\
	if (!try(_lock)) {					\
		lock_contended(&(_lock)->dep_map, _RET_IP_);	\
		lock(_lock);					\
	}							\
	lock_acquired(&(_lock)->dep_map, _RET_IP_);			\
} while (0)
~~~

## spinlockの実装

lockは`arch_spin_lock()`を渡す。下記はx86のコードである。スピンロックなので、`for(;;)`で待つところがメインの処理だろうと思う。
ループを抜ける条件は`__tickets_equal(inc.head, inc.tail)`で、`自分の番号tail == lock.head`となった時に、ロックが取れたことになる。

~~~c
static __always_inline void arch_spin_lock(arch_spinlock_t *lock)
{
	register struct __raw_tickets inc = { .tail = TICKET_LOCK_INC };

	inc = xadd(&lock->tickets, inc);　ここでtailに加算、戻り値は元の値
	if (likely(inc.head == inc.tail))
		goto out;

	for (;;) {
		unsigned count = SPIN_THRESHOLD;

		do {
			inc.head = READ_ONCE(lock->tickets.head);
			if (__tickets_equal(inc.head, inc.tail))　元のtailと、今のheadが一致
				goto clear_slowpath;
			cpu_relax();
		} while (--count);
		__ticket_lock_spinning(lock, inc.tail);
	}
clear_slowpath:
	__ticket_check_and_clear_slowpath(lock, inc.head);
out:
	barrier();	/* make sure nothing creeps before the lock is taken */
}
~~~
カーネルのシグナル配信についてさらに調べた

前回に引き続きLinuxのシグナルの配信について調べた。

## カーネルバージョン

v4.5.0

## シグナルの配信

シグナルの配信はシステムコール(= "Interrupt came from user space"かな？)から、ユーザモードに戻るときに呼ばれる`prepare_exit_to_usermode`で実行される。
ここで、プログラムカウンタ(ip)にシグナルハンドラのエントリポイントにセットして`restore_regs_and_iret`を呼び出すことでハンドラが実行される。

~~~
  /* Interrupt came from user space */
GLOBAL(retint_user)
  mov %rsp,%rdi
  call  prepare_exit_to_usermode
  TRACE_IRQS_IRETQ
  SWAPGS
  jmp restore_regs_and_iret
~~~

`prepare_exit_to_usermode`を見ていくと、`do_signal()`,`handle_signal()`によって、対象のプロセスに保留されているシグナルのうち、ハンドラが設定されているものが呼び出される。
`handle_signal()`ではまず、ユーザモードのスタックを作成する。このとき、シグナルハンドラからの戻り番地を`sigreturn()`を呼び出すコードにセットする。

ユーザモードスタックにセットするのは次の`rt_sigframe`構造体である。`pretcode`が戻り番地になる。

~~~
struct rt_sigframe {
  char __user *pretcode;
  struct ucontext uc;
  struct siginfo info;
  /* fp state follows here */
};
~~~

x86_64では、pretcodeにvdso`vdso_image_32.sym___kernel_sigreturn`がセットされるわけではなく、`ka.sa.sa_restorer`が`frame->pretcode`にセットされているようだ。
restorerは`sigaction()`の引数の`act`のメンバとしてアプリケーションからセットされる(man 2 sigaction 参照)が、ユーザが好きにセットするものではないのでlibcなどで決められている可能性があるかも。

~~~
/* Set up to return from userspace.  If provided, use a stub
   already in userspace.  */
/* x86-64 should always use SA_RESTORER. */
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
  put_user_ex(ksig->ka.sa.sa_restorer, &frame->pretcode);

...

  regs->sp = (unsigned long)frame;
~~~

また、シグナルハンドラのエントリポイントをipにセットすることで、ユーザモードに戻った時にシグナルハンドラが実行されるようにしている。

~~~
  regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
~~~

本来の呼び出し元のユーザモードのコンテキストは、同じくユーザモードスタック内に保存され,dxレジスタでポイントされる。
これらは呼び出された`sigreturn()`によって回復されるはず。

~~~
/* Create the ucontext.  */
if (cpu_has_xsave)
  put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
else
  put_user_ex(0, &frame->uc.uc_flags);
put_user_ex(0, &frame->uc.uc_link);
save_altstack_ex(&frame->uc.uc_stack, regs->sp);

...

  regs->dx = (unsigned long)&frame->uc;
~~~

## まとめ

シグナルの配信は生成と違い、アーキテクチャ依存のコードとなっていて比較的複雑だった。
シグナルハンドラからの復帰をカーネルがフックするために、POSIXに規定されていないsigreturn()なるシステムコールを使っていることがわかった。
カーネルのシグナル生成と配信の実装を読んだ


Linuxのシグナルの実装について調べた。

## カーネルバージョン

v4.5.0

## シグナルの仕組み

普通のシグナルと、リアルタイムシグナルの２種類がある。
普通のシグナルは同じ種類のシグナルを２回送っても１度しか配信されないことがあるが、リアルタイムシグナルはキューにつながって必ず生成した回数分届く（メモリが足りていれば）

シグナルは生成と配信という２段階を踏んで届く。
生成はシグナル発信側プロセスが受信側のプロセスの`task_struct->pending`に対して保留中のキューをつなげる操作のことで、
配信は受信側のプロセスの`schedule()`の延長でdo_signalを呼び出す操作のことである。

条件分岐が複雑になるので、以下は普通のシグナルの場合だけをみる。

## シグナル生成

`__send_signal()`で生成される。

普通のシグナルがすでに保留されているかどうかは`legacy_queue()`で確認する。
引数のsignalsが現在保留されているシグナルのビットマップである。

~~~
static inline int legacy_queue(struct sigpending *signals, int sig)
{
	return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
}
~~~

まだ保留されていない場合、次の処理でシグナルがキューに繋がれその情報をinfoに格納する。
`SI_USER`はシグナルの送信者がユーザプロセスの場合、SI_KERNELはカーネルから。
キューに繋げられたら、sigaddset()で保留済みのビットを立てる。

~~~
	q = __sigqueue_alloc(sig, t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE,
		override_rlimit);
	if (q) {
		list_add_tail(&q->list, &pending->list);
		switch ((unsigned long) info) {
		case (unsigned long) SEND_SIG_NOINFO:
			q->info.si_signo = sig;
			q->info.si_errno = 0;
			q->info.si_code = SI_USER;
			q->info.si_pid = task_tgid_nr_ns(current,
							task_active_pid_ns(t));
			q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
			break;
		case (unsigned long) SEND_SIG_PRIV:
			q->info.si_signo = sig;
			q->info.si_errno = 0;
			q->info.si_code = SI_KERNEL;
			q->info.si_pid = 0;
			q->info.si_uid = 0;
			break;
		default:
			copy_siginfo(&q->info, info);
			if (from_ancestor_ns)
				q->info.si_pid = 0;
			break;
		}

		userns_fixup_signal_uid(&q->info, t);

	} else if (!is_si_special(info)) {

...

out_set:
	signalfd_notify(t, sig);
	sigaddset(&pending->signal, sig);
	complete_signal(sig, t, group);
ret:
	trace_signal_generate(sig, info, t, group, result);
	return ret;
~~~

## シグナルの配信

システムコールからユーザモードに戻るとき、`do_signal()`が呼び出され`get_signal()`で保留中のシグナルハンドラを処理する。ハンドラが設定されている場合は、`handle_signal()`で実行される。ユーザモードへ戻るときのレジスタ情報などを差し替えるのだろうと思う。詳細は次回記事参照。

~~~
void do_signal(struct pt_regs *regs)
{
	struct ksignal ksig;

	if (get_signal(&ksig)) {
		/* Whee! Actually deliver the signal.  */
		handle_signal(&ksig, regs);
		return;
	}

...
~~~


## プロセスごとのシグナルの状態と設定の確認
各プロセスごとのシグナルの保留状態、ブロックなどの設定は`/proc/[pid]/status`から確認できる。
SigPndからSigCgtはシグナル番号のビットマップになっている。
例えばSigIgnは２進数にすると、100000000000001000000000000なので、13と27のシグナルがブロックされている。

~~~
juntaki@lab% cat /proc/1342/status
Name:   emacs
State:  S (sleeping)
Tgid:   1342
Ngid:   0

...

Threads:        2 #スレッド数
SigQ:   1/15922 #キューの長さと上限
SigPnd: 0000000000000000 保留中：task->pending.signal
ShdPnd: 0000000000000000 task->signal->shared_pending.signal
SigBlk: 0000000000000000 ブロックのマスク：task->blocked
SigIgn: 0000000004001000 ハンドラがSIG_IGN：task->sighand->action->sa.sa_handler
SigCgt: 00000001db816eff シグナルハンドラが指定されている

...
~~~


## まとめ

シグナルは生成と配信の２段階で実現されている。
生成は比較的簡単な構造体の操作だけだが、配信はプロセス切り替えなどのアーキテクチャ依存の部分があるため、やや複雑だった。
次回は配信の箇所をもう少し読みたい。
Let's encryptでnginxのBASIC認証つきSSLリバースプロキシ

開発用サーバーをEC2に移行したが、開発中のWebアプリを動かしてブラウザから見に行きたい。
一時的にせよ全世界に公開はマズイ感じがするので、BASIC認証ができるようにnginxでSSLリバースプロキシを組んだ。

## Let's encryptの使いかた

サーバも何も入れてないところからのスタートの場合、[Standalone](http://letsencrypt.readthedocs.org/en/latest/using.html#standalone)が簡単のようだ。

~~~sh
git clone https://github.com/letsencrypt/letsencrypt
~~~

`--help`で依存パッケージをとってきたり、新バージョンを探し始めるので、注意。
443しかポート開けてなかったので、次のコマンドを実行した。質問に答えていくとキーが生成されている。すごい。

オプションはHow-to系のサイトを見てもよくわからないので（仕様が変わった？）、これも鵜呑みにせずにそのときの公式ドキュメントかhelpを見るのがよさそう。

~~~sh
./letsencrypt-auto certonly --standalone --standalone-supported-challenges tls-sni-01
~~~

## 追記：証明書の更新

Standaloneで証明書を更新しようとすると、Webサーバを止めないといけない、というのが欠点らしい。
cronなどで適当なタイミングで次のコマンドを起動するようにする。数秒くらい止まっても良いならコマンド実行時だけnginxを止めておけばよい。
止めたくない場合はwebrootプラグインを使えば良い、とのこと。

~~~sh
./letsencrypt-auto renew
~~~


## nginxの設定

ubuntuのお作法に従うとnginx.confはあんまり編集してはダメなのかな・・？
基本的な設定は[ここ](http://webos-goodies.jp/archives/ssl_proxy_using_nginx.html)を参考にした。

## セキュリティ

SSLv3など古い機能がデフォルトで有効になっていたので蓋をする。基本的に自分しか見ないので、古いブラウザのサポートは気にせず高セキュリティ設定にした。
`ssl_protocols`がちょっと冗長な感じもするが、意図した設定にはなっているみたいなので、細かいことは気にしない。

参考：[Webサーバー nginx における SSL証明書設定の安全性向上 ～SSL Server Test で A+ 判定を目指して～](https://www.saintsouth.net/blog/safety-of-ssl-certificate-setting-improvements-in-web-server-nginx-to-get-rankaplus-from-ssl-server-test/)

## .htpasswdファイルの生成

ubuntuだと、apache2-utilsにコマンドが入っている。

~~~bash
htpasswd -c .htpasswd username
~~~

## 設定ファイル

`/etc/nginx/sites-available/example`, `/etc/nginx/sites-enabled/example`

~~~nginx
server {
	listen 443;
	listen [::]:443;
	server_name example.juntaki.com;

	ssl on;
	ssl_certificate /etc/letsencrypt/live/example.juntaki.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/example.juntaki.com/privkey.pem;

	ssl_session_timeout 5m;

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers 'ECDH !aNULL !eNULL !SSLv2 !SSLv3';

	ssl_prefer_server_ciphers on;
	add_header Strict-Transport-Security "max-age=15768000; includeSubdomains";

	auth_basic "Restricted";
	auth_basic_user_file /etc/nginx/.htpasswd;
	location / {
		deny all;
	}
	location /8080/ {
		proxy_pass http://localhost:8080/;
		proxy_redirect default;
	}
}
~~~

`/etc/nginx/conf.d/reverse_proxy.conf`

~~~nginx
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
~~~

## まとめ

Let's encryptであっという間にSSLのキーがもらえる。
SSLでBASIC認証を使うことで、安全に開発用のプレビューができそう。
tcpdumpで理解するTCPのコネクション拒否 (connection refused)

## TCPのコネクション拒否 (connection refused)

TCPでデータを転送する場合、データの転送を行う前にコネクションを確立する必要があります。
TCPのコネクション拒否は、TCPクライアントがコネクション確立要求に対して、コネクションを拒否する要求が返った場合に発生します。

TCPのコネクションについての詳細は以下のエントリを参照してください。

[tcpdumpで理解するTCPのコネクション](http://qiita.com/keikmobile/items/93cf6dc5b95019c6a442)


上記のコネクション確立要求に対して、コネクションを拒否する要求が返る振る舞いをtcpdumpコマンドで実際に確認して行きます。

## tcpdumpで理解するTCPのコネクション拒否 (connection refused)

#### 使用するネットワークコマンド

本エントリでは、以下のLinuxコマンドを使用します。

* tcpdump
 * ネットワーク上のパケットを出力するために使用します。
* nc,telnet
 * tcpサーバー/クライアントとして使用します。
* netstat
 * コネクションの状態を確認するために使用します。

上記コマンドがインストールされていない場合、以下のコマンドでインストールします。

```
$ sudo yum -y install tcpdump nc telnet net-tools
```

### 1. コネクション確立の拒否

一番単純にコネクション確立の拒否を確認する方法はListenしていないportにコネクション確立要求を発行することです。
ここでは、12345portにコネクション確立要求を発行します。

```
$ telnet 127.0.0.1 12345
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
$ 
```

即時にTCPのコネクション拒否(Connection refused)が発生します。
これで、TCPのコネクション拒否をtcpdumpで確認する準備ができました。

### 2. tcpdumpでのコネクション拒否を目視する。

tcpdumpコマンドでlocal interfaceのport12345を指定して実行します。

```
$ sudo tcpdump -i lo -nnn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
```

1.の手順と同様にtelnetコマンドを実行します。

```
$ telnet 127.0.0.1 12345
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
$ 
```

tcpdumpの出力を確認します。

```
12:43:40.125255 IP 127.0.0.1.60642 > 127.0.0.1.12345: Flags [S], seq <seq num> ...
12:43:40.125277 IP 127.0.0.1.12345 > 127.0.0.1.60642: Flags [R.], seq 0, ...
```

上記のtcpdumpの出力フォーマットは以下の通りです。

```
timestamp src > dst: flags data-seqno
```
* timestamp: タイムスタンプ
* src: 送信元IP.ポート
* dst: 送信先IP.ポート
* flags: フラグ S (SYN), R(RST), ‘.’ (no flags)
* data-seqno: シーケンス番号(上記はSYNパケットのみなので初期シーケンス番号) 

上記のパケットキャプチャは、TCPクラアントがコネクション確立要求(SYN)を送信したが、対象のportがListenしていないため、コネクション拒否(RST)が返ったことを示します。

以下はシーケンスの概要です。

![tcp_rst.png](https://qiita-image-store.s3.amazonaws.com/0/22861/a030546f-31c2-6461-2150-7a278eb63d2f.png)

## おまけ: straceコマンドでTCPのコネクション拒否(Connection refused)を確認する

straceコマンドにtelnetコマンドを渡してListenしていないportにコネクション確立要求を送信します。以下のようにconnectシステムコールにECONNREFUSED(Connection refused)が返っていることが確認できます。

```
[vagrant@centos601 ~]$ strace -Ttt -e trace=network telnet 127.0.0.1 12345
Trying 127.0.0.1...
00:31:31.345795 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 <0.000021>
00:31:31.345912 setsockopt(3, SOL_IP, IP_TOS, [16], 4) = 0 <0.000013>
00:31:31.345956 connect(3, {sa_family=AF_INET, sin_port=htons(12345), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ECONNREFUSED (Connection refused) <0.000057>
telnet: connect to address 127.0.0.1: Connection refused
00:31:31.346192 +++ exited with 1 +++
$
$ man 2 connect
...
       ECONNREFUSED
              No-one listening on the remote address.
...
$
$
$ grep ECONNREFUSED /usr/include/asm-generic/errno.h 
#define ECONNREFUSED    111     /* Connection refused */
$ 
```
EspressoでRecyclerViewの中身を比較


# EspressoでRecyclerViewの中身を比較

Espressoに標準で用意されていないので、自分でmatherを作る必要があります

* RecyclerViewに用意されているfind系のメソッドにはこのようなものがあります
 - `findChildViewUnder(float x, float y)`
 - `findContainingItemView(View view)`
 - `findContainingViewHolder(View view)`
 - `findViewHolderForAdapterPosition(int position)`
 - `findViewHolderForItemId(long id)`
 - `findViewHolderForLayoutPosition(int position)`
 - `findViewHolderForPosition(int position)`

今回はRecyclerViewの `findViewHolderForAdapterPosition(int position)`を使用します
適宜 使いやすいメソッドを使用して下さい 

## ViewHolder

```kotlin
class MyViewHolder(v: View) : RecyclerView.ViewHolder(v) {
            var title: TextView           
            ...
}
```

## matcherのメソッドを作成

``` kotlin
  fun hasText(position: Int, text: String) = object : TypeSafeMatcher<View>() {
        var innerText: String? = null

        override fun describeTo(description: Description) {
            description.appendText(String.format(text + "is not equal to %s.", text))
        }

        override fun matchesSafely(view: View): Boolean {
            if (view !is RecyclerView) return false

            val holder = view.findViewHolderForAdapterPosition(position) as MyViewHolder
            innerText = holder.title.text.toString()
            return holder.description.text == text
        }
    }
```

## 使用側

```kotlin
@Test
fun testRecyclerView() {
    val position = 0
    val text = "hoge"
    onView(withId(R.id.recyclerView)).check(matches(hasText(position, text)))
}
```
Reactと最近のWebアプリの開発について調べた

最近のWebアプリの開発について情報収集してみて、Reactが流行っている、に辿り着くまでの結果をまとめた。
それぞれの技術はまだチュートリアルを触った程度なので、若干誤解があるかもしれない。

## モジュール管理、ビルドツール、CommonJS、ES2015

学習コストが高い割に、細かい技術は長続きしなさそう。
npmとwebpackを使えば、一番環境構築にコストをかけずに済みそうだ。
javascriptの書き方はES2015に準拠するようにしておくと、RubyやPythonのようなLLの使用感に近くなっているように思えるので少しハードルは下がるか。

このあたりのことがまとまっている記事としては:
[旧石器時代のJavaScriptを書いてる各位に告ぐ、現代的なJavaScript超入門 Section1 ～すぐにでも現代っぽく出来るワンポイントまとめ～](http://qiita.com/gaogao_9/items/ec2b867d6941173fd0b1)
かなり新し目の記事で、現在進行形で続きが書かれている。
しかし、ES2015だとしても、サーバーサイドのブラウザと関係ないところはNode.jsじゃなくて、そもそも他の言語のほうが向いているような気がする。

### 参考

1年前くらいの記事。かなり混沌としている。
上記に落ち着くまでの歴史を見ておくには良さそう。

* [Front-end with Node.js Tools](https://speakerdeck.com/ahomu/front-end-with-node-dot-js-tools)
* [npm とか bower とか一体何なんだよ！Javascript 界隈の文脈を理解しよう](http://qiita.com/megane42/items/2ab6ffd866c3f2fda066)
* [JavaScriptのモジュール管理(CommonJSとかAMDとかBrowserifyとかwebpack)](https://tsuchikazu.net/javascript-module/)
* [JavaScriptでのモジュールロード方式とパッケージ管理についての勉強メモ](http://hblog.glamenv-septzen.info/entry/2015/03/23/001618)

## ReactとWebアプリ

なんとか.jsのフレームワークが乱立していたが、今はReactが流行っているらしい。

Webアプリを簡単に言うと、ブラウザ環境で動くクライアントアプリをサーバから送りつけて、サーバと通信させるものということになる。そのクライアントアプリの目的は、画面を通してWebの先にあるデータをいい感じに操作すること。
いまブラウザ環境で動く言語は(基本的には)javascriptだけで、画面に出すにはDOM APIを通してHTMLな画面を作る必要がある。

画面更新の難しさは、サーバから都度HTMLを送りつければ画面更新は簡単だがインタラクティブではない。逆に頑張って変えたい要素だけ書き換えると、フレームワークが難しくなっていく。
Reactでは仮想DOMという、DOMの反映前のjavascriptから扱いやすい状態を作り、ブラウザ上で更新差分を計算することで、簡単な更新とインタラクティブな操作を実現している。

* [なぜ仮想DOMという概念が俺達の魂を震えさせるのか](http://qiita.com/mizchi/items/4d25bc26def1719d52e6)
* [仮想DOMで魂が震えてから一年、仮想DOMとFluxの今](http://qiita.com/mizchi/items/82f205e16e78424df71b)
* [10年のツケを支払ったフロント界隈におけるJavaScript開発環境（2016年4月現在）。](http://d.hatena.ne.jp/tomoya/20160403/1459665374)

HTMLやCSSがコンポーネントとして隠蔽できている点も使いやすい。
例えば：

* [React-Bootstrap](https://react-bootstrap.github.io/)
* [Material-UI](http://www.material-ui.com)

ところで、Reactが流行っている理由を考えると、ブラウザという環境がかなり限界に近いのではないかという気がしてくる。
ブラウザのDOMを介した画面更新も、その生成元となるHTMLやCSSも隠蔽して、使いやすくしている。
そのときに、フロントエンドのソースコードがトランスパイルしないと動かないなら、もうHTMLやjavascriptが生成される必要性はないんじゃないだろうか。
例えば、適当なバイナリを送りつけて、それがブラウザで動けば上に書いたようなWebアプリの目的は果たせるはず。（WebAssemblyはそういう流れで出てきたのかもしれないけど、それはまた今度調べる）

この辺をちゃんと理解するには、ブラウザのこともちょっとは詳しくなったほうがいいか。

[Design Documents - The Chromium Projects:](https://www.chromium.org/developers/design-documents)
syncシステムコールのしくみ

syncシステムコールの仕組みを調べた。

## カーネルバージョン

v4.7-rc

## syncシステムコール

システムコールの呼び出し元はこんな感じなので、補助関数の分け方はあまり変わっていなさそうだ。

~~~c
/*
 * Sync everything. We start by waking flusher threads so that most of
 * writeback runs on all devices in parallel. Then we sync all inodes reliably
 * which effectively also waits for all flusher threads to finish doing
 * writeback. At this point all data is on disk so metadata should be stable
 * and we tell filesystems to sync their metadata via ->sync_fs() calls.
 * Finally, we writeout all block devices because some filesystems (e.g. ext2)
 * just write metadata (such as inodes or bitmaps) to block device page cache
 * and do not sync it on their own in ->sync_fs().
 */
SYSCALL_DEFINE0(sync)
{
	int nowait = 0, wait = 1;1

	wakeup_flusher_threads(0, WB_REASON_SYNC);
	iterate_supers(sync_inodes_one_sb, NULL);
	iterate_supers(sync_fs_one_sb, &nowait);
	iterate_supers(sync_fs_one_sb, &wait);
	iterate_bdevs(fdatawrite_one_bdev, NULL);
	iterate_bdevs(fdatawait_one_bdev, NULL);
	if (unlikely(laptop_mode))
		laptop_sync_completion();
	return 0;
}
~~~

## flusherスレッド

`fs-writeback.c`にある`wb_*`の関数で非同期でライトバックを行うためのスレッドである。もう`pdflush`ではなくて、`writeback`というそのまんまの名前のワークキューになっている。全部のブロックデバイスの`bdi_writeback`に対して、ダーティーを吐き出すワークキューを積む。
これで、すべてのブロックデバイスに対して、ページキャッシュがディスクまで書かれる。

この辺はcgroup_writebackというのが関連していて、構造が複雑になっているようだ。メモリのリソースを分割した時のために、ブロックデバイスごとに複数のwriteback用スレッドが存在している？

* [2015-LCJ-cgroup-writeback.pdf](http://events.linuxfoundation.org/sites/events/files/slides/2015-LCJ-cgroup-writeback.pdf)

## iterate_supers

すべての`super_blocks`のアイテムに対して第一引数の関数を実行する。`super_blocks`へは`sget()`で追加されている、`sget()`はフィアルシステムからマウント時に呼ばれる。
削除は`__put_super()`で、おそらくアンマウント時に呼ばれる。

## sync_inode_one_sb

第一引数の`super_block`に含まれるinodeから、`__filemap_fdatawait_range()`にmappingを渡してdirtyなファイルを書き出す。

## sync_fs_one_sb

各ファイルシステムのスーパーブロックに対する`sync_fs`オペレーションを呼び出す。

## iterate_bdevs

`blockdev_superblock`なるリストに対して、第一引数の関数を実行する。`iterate_supers`のブロックデバイスバージョン。

## fdata*_one_dev

`__filemap_fdatawrite_range()`で、メモリマップされているファイルをライトバックする。これはブロックデバイスのinodeのマッピングなので、バッファキャッシュということになる。


## まとめ

syncの動作を見ることで、どんなページキャッシュが作られるかイメージがつきやすい。writebackのスレッドがやっている書き出しと、inode,blockデバイスごとに走査して書き出す内容の違いがあまり調べられていない。もう一段キャッシュがある？

cgroupに関連して新たな仕組みが作られている。cgroupのような新し目の話題は書籍には無いので、どこかのタイミングでまとめて調査してみたい。
bioをブロックのrequest_queueにつなげる その２

Linuxのブロック層について調べた。bioをrequest_queueにくっつけて、ブロックドライバがキューを処理する部分を見た。

## カーネルバージョン

v4.4.0

## bio構造体に書いてあること

`submit_bio()`に入った時点でのbioはこんな感じ。ログか何かを書こうとしているところ。
まだリクエストキューに繋がっていないので、`bi_next`は空だったり使っていない部分もある。

`bi_iter`の`bi_sector`と`bi_size`は、それぞれ対象とするブロックデバイスのセクタ番号と、そこからのサイズ。
`bi_rw`がこのIOの読み書きの種別を表していて、何もセットされていない場合はReadで、それ以外はWriteになる。このフラグは`submit_bio()`の中でセットされるため、この時点では必ず0になっている。

~~~
>>> p/x *bio
$6 = {
bi_next = 0x0,
bi_bdev = 0xffff8802334d09c0,
bi_flags = 0x50002100,
bi_error = 0x0,
bi_rw = 0x0,
bi_iter = {
bi_sector = 0x930170,
bi_size = 0x1000,
bi_idx = 0x0,
bi_bvec_done = 0x0
},
bi_phys_segments = 0x0,
bi_seg_front_size = 0x0,
bi_seg_back_size = 0x0,
__bi_remaining = {
counter = 0x1
},
bi_end_io = 0xffffffff8127e2d0,
bi_private = 0xffff8802335f2240,
bi_ioc = 0x0,
bi_css = 0x0,
{
bi_integrity = 0x0
},
bi_vcnt = 0x1,
bi_max_vecs = 0x100,
__bi_cnt = {
counter = 0x2
},
bi_io_vec = 0xffff88023579b000,
bi_pool = 0xffff880236377980,
bi_inline_vecs = 0xffff8800bb82d188
}
~~~

`bi_io_vec`がIO要求に対応するメモリ上の領域になっている。

~~~
>>> p/x *bio->bi_io_vec
$13 = {
bv_page = 0xffffea0008c5c840,
bv_len = 0x1000,
bv_offset = 0x0
}
~~~

## blk_queue_bio()は何をするか

概要しか見れなかった。

* `elv_merge()`で既存のリクエストとマージできるかをチェックして、マージをする。マージできたら抜ける。ここでrequest_queueに紐付いたelevatorを呼んでいる。
* `get_request()`で新しいリクエストを初期化、そこにbioを詰める。
* `__blk_run_queue()`でブロックデバイスにキューの処理を依頼する。
ファイルロック flockの実装 その2

詳解Linuxカーネルの12章VFSに関連するコードを読んだ。

## カーネルバージョン

v4.1.13

## flockとは

manに書いてある。

* ファイル(inode)に対してロックをかける、引数はファイルディスクリプタ。
* 排他、共有のロック設定、解除ができる。
* 勧告ロックである。追記：強制ロックも出来るかも？

## プロセスはどうやって判別するのか

file_lock構造体の`fl_file`にfile構造体へのポインタが入っているので、それが同一か否かで判定する。
file構造体はopenごとに生成されるので、forkした場合は子プロセスで同じロックを参照することができる。

~~~c
struct file_lock {
	struct file_lock *fl_next;	/* singly linked list for this inode  */
	struct list_head fl_list;	/* link into file_lock_context */
	struct hlist_node fl_link;	/* node in global lists */
	struct list_head fl_block;	/* circular list of blocked processes */
	fl_owner_t fl_owner;
	unsigned int fl_flags;
	unsigned char fl_type;
	unsigned int fl_pid;
	int fl_link_cpu;		/* what cpu's list is this on? */
	struct pid *fl_nspid;
	wait_queue_head_t fl_wait;
	struct file *fl_file;
	loff_t fl_start;
	loff_t fl_end;

	struct fasync_struct *	fl_fasync; /* for lease break notifications */
	/* for lease breaks: */
	unsigned long fl_break_time;
	unsigned long fl_downgrade_time;

	const struct file_lock_operations *fl_ops;	/* Callbacks for filesystems */
	const struct lock_manager_operations *fl_lmops;	/* Callbacks for lockmanagers */
	union {
		struct nfs_lock_info	nfs_fl;
		struct nfs4_lock_info	nfs4_fl;
		struct {
			struct list_head link;	/* link in AFS vnode's pending_locks list */
			int state;		/* state of grant or error if -ve */
		} afs;
	} fl_u;
};
~~~

## 仕組み

同じfl_file（つまり、同一プロセスの同一fdのファイル）ですでにロックが存在する場合、いままでのロックを消す（正確には、disposeに繋いで`out:`セクションでまとめて削除している）、ということをしている。
完全に同じロックがかかっていた場合、何もせずにそのまま関数を抜ける。

~~~c
	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
		if (request->fl_file != fl->fl_file)
			continue;
		if (request->fl_type == fl->fl_type)
			goto out;
		found = true;
		locks_delete_lock_ctx(fl, &dispose);
		break;
	}
~~~

ロックの操作がアンロックだった場合はそのまま関数を抜ける。前のロックは上のブロックで消されている。

~~~c
	if (request->fl_type == F_UNLCK) {
		if ((request->fl_flags & FL_EXISTS) && !found)
			error = -ENOENT;
		goto out;
	}
~~~

次に、ロックの衝突を探す。`flock_locks_conflict()`は、自分以外からのロックのうち排他ロック(`F_WRLOCK`)がある場合、もしくは自分が`F_WRLOCK`で他のロックがあった場合は衝突になる。
`MAND_LOCK`もチェックしているが・・flockで強制ロックも出来るのかな？ここはまだよくわからない。

~~~c
find_conflict:
	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
		if (!flock_locks_conflict(request, fl))
			continue;
		error = -EAGAIN;
		if (!(request->fl_flags & FL_SLEEP))
			goto out;
		error = FILE_LOCK_DEFERRED;
		locks_insert_block(fl, request);
		goto out;
	}
~~~

衝突がなければ、ロックを取得する。
関数内では`flc_lock`のスピンロックをとっているため処理の競合はない。noblockの指定をしない場合の待ち処理はさらに上位の関数で書かれているようだ。

~~~c
	locks_copy_lock(new_fl, request);
	locks_insert_lock_ctx(new_fl, &ctx->flc_flock);
	new_fl = NULL;
	error = 0;
~~~

## 参考

[Linux におけるファイルの排他制御](http://kamae-norihiro.blogspot.jp/2011/01/file-lock-in-linux.html)
Pacmanの使い方

Pacmanの使い方
============================
# この記事について
パッケージマネージャpacmanの使い方を紹介します。
[こちらのサイト](https://wiki.manjaro.org/index.php?title=Pacman_Overview)を翻訳した内容となっています。
pacmanはArch系のLinuxディストリビュージョンで使用されるパッケージマネージャです。
yum、aptにならぶメジャーなパッケージマネージャとして有名です。

# ミラーの最適化
初期状態のPacmanはかなり遅いです。
これは、参照しているミラーが地理的に遠くのサーバになっているからです。
そこで、参照するミラーを変更する必要が出てきます。
ミラーの最適化を自動的に実行するには以下のコマンドを使用します。

```sh
sudo pacman -g
```
これによりパッケージのダウンロードをするミラーの優先順位を最適化し、ダウンロードが速くなります。

# レポジトリとの同期
レポジトリとの同期には-Syyオプションを使います。これはaptでいう```apt-get update```に相当します。


```sh
sudo pacman -Syy
```

同時にソフトウェアのアップグレードを実行するには

```sh
sudo pacman -Syyu
```
を実行します。

# レポジトリのソフトウェアの検索
レポジトリのソフトウェアの検索には```-Ss```オプションを使います。

```sh
pacman -Ss [検索したいソフトウェアパッケージ名]
```

# ローカルのソフトウェアの検索
ローカルにインストールされたソフトウェアの検索には-Qsオプションを使います。

```sh
pacman -Qs [検索したいソフトウェアパッケージ名]
```
より詳細を知りたい場合は-Qiオプションを使います。

```sh
pacman -Qi [検索したいソフトウェアパッケージ名]
```
更に詳細を表示したい場合はiを増やします。

```sh
pacman -Qii [検索したいソフトウェアパッケージ名]
```
ローカルにインストールされたソフトウェアをすべて羅列するには-Qlオプションを使います。

```sh
pacman -Ql
```

# 依存関係の表示
パッケージの依存関係を表示するにはpactreeコマンドを使います。

```
pactree [調べたいパッケージ名]
```

# 孤児パッケージの表示
どのパッケージからも依存されていないパッケージを孤児パッケージ（勝手に命名。原文ではOrphans）といいます。孤児パッケージの表示には

```sh
pacman -Qdt
```
孤児パッケージをすべて削除するには以下のコマンドを使います。

```sh
sudo pacman -Rs $(pacman -Qdtq)
```

# パッケージのインストール
パッケージをインストールするときは-Sオプションを使います。

```sh
sudo pacman -S [パッケージ名]
```
パッケージをインストールせず、ダウンロードだけするときは

```sh
sudo pacman -Sw [パッケージ名]
```
を使います。
ローカルにあるパッケージからインストールする-Uオプションを使います。

```sh
sudo pacman -U [パッケージのパス][パッケージ名]
```
URLを使えばネットにあるパッケージをインストールできます。

```sh
pacman -U http://www.examplepackage/repo/examplepkg.tar.xz
```

# パッケージの削除
パッケージの削除には-Rオプションを使います。

```sh
sudo pacman -R [パッケージ名]
```
依存するパッケージを同時に削除するには

```sh
sudo pacman -Rs [パッケージ名]
```
を使います。
パッケージを削除する際にpacmanは念のためにバックアップファイルを作成します。それらを削除するには

```sh
sudo pacman -Rns
```
を使います。

# キャッシュの削除
pacmanはパッケージをインストールする際一時的にパッケージをキャッシュします。
このキャッシュをクリーンアップするには

```sh
sudo pacman -Sc
```
を使います。完全に削除するには

```sh
sudo pacman -Scc
```
を使います。

# アップグレードの例外を追加
アップグレード対象からパッケージを除外するには、/etc/pacman.confのなかにある。
```
IgnorePkg=[パッケージ名]
```
にパッケージ名を追加します。

# 小ネタ
## さらなる高速化
pacmanに組み込まれたダウンローダではなく他のダウンローダを使うことによってpacmanを高速化できます。ここではaria2を使ったpacmanの高速化を紹介します。
まずaria2をインストールします。

```sh
sudo pacman -S aria2
```
それから、/etc/pacman.confを書き換えてaria2を使用するようにします。
[options]セクションの下記の行を変更します。

```sh
XferCommand = /usr/bin/aria2c --allow-overwrite=true --continue=true --file-allocation=none --log-level=error --max-tries=2 --max-connection-per-server=2 --max-file-not-found=5 --min-split-size=5M --no-conf --remote-time=true --summary-interval=60 --timeout=5 --dir=/ --out %o %u
```

## pacmanのプログレスバーをpacmanにする
/etc/pacman.confの#Misc optionsセクションに下記の行を追加します。

```
# Misc options
#UseSyslog
#UseDelta
#TotalDownload
CheckSpace
#VerbosePkgLists
ILoveCandy
```
DB  import コマンド 目的別まとめ


 DB2 importコマンドの利用目的別にオプションの使い分けメモ。
 以下、import.csv を sampleテーブルに登録する例

## 文字コード指定
modified by codepage=xxxxで指定

```import from import.csv of del of del modified by codepage=1208 insert into sample
```
codepage=1208はUTF-8


## 改行付データ
modified by delprioritycharを利用。
字区切りの優先順位を変えてくれる。
デフォルト優先順位は、(1) レコード区切り文字、(2) 区切り文字、(3) 列区切り文字。
この修飾子を使用すると、区切り文字の優先順位が (1) 区切り文字、(2) レコード区切り文字、(3) 列区切り文字にとなる 

```import from import.csv of del of del modified by delprioritychar insert into sample 
```

## デフォルト値を利用
列のデフォルト値を設定する場合のオプション。
modified by usedefaultsを利用する。

```import from import.csv of del of del modified by usedefaults insert into sample 
```

## identity列のimport
 フィールドでidentity列を利用している場合※、Importファイルの内容に整合性がないとエラーになります。
※ddl ex. field1 int generated by default as identity

そんな時は、modified by identityignoreを指定すると、Importファイルの内容を無視して、 ID値を生成してくれます。

```import from import.csv of del of del modified by identityignore insert into sample 
```



## コミット単位を指定する
アクティブログフルには要注意。

```import from import.csv of del of del commitcount xxxxx modified by xxxx insert into sample 
```
/optに入れたhomebrewでmecabが起動しない場合はsourceから入れよう

homebrewを/opt以下など/usr/local以外に入れている場合に、下記のようなエラーが出る。

```shell-session
$ mecab
param.cpp(69) [ifs] no such file or directory: /usr/local/etc/mecabrc
```

これはmecabrcの場所をデフォルトでは読み込んでくれないためで、いろいろ調べた結果bottleでバイナリ落としてきた時に、mecabrcの場所が`/usr/local/etc/mecabrc`でコンパイルされたものが入っているのが原因だった。
`mecab-config --sysconfdir`しても/opt/homebrewとかが返ってきたのでハマってしまった。

そういう時は素直にsourceから入れれば良い。

```shell-session
$ brew install --build-from-source mecab
```

めでたしめでたし
Electron1.3.xの最小構成

```package.json
{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "electron index.js"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron-packager": "^7.3.0",
    "electron-prebuilt": "^1.3.1"
  }
}
```
```index.js
const {app, BrowserWindow} = require('electron');

let win;

function createWindow() {
  win = new BrowserWindow({width: 800, height: 600});
  win.loadURL(`file://${__dirname}/index.html`);
  win.on('closed', () => { win = null; });
}

app.on('ready', createWindow);
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});
```
```index.html
<!doctype html>
<html>
  <body>
    <h1>my-electron-app</h1>
  </body>
</html>
```
以上のファイルをプロジェクトのルートディレクトリに作成し、`$ npm install `と`$ npm run start`で起動します。お疲れ様でした。
電子工作 > MSC-MOD20 > SDモジュール 使用開始からI2C通信まで

```txt:動作環境
ESP8266 (気圧計で使用したユニバーサル基板: I2Cを4.7kでプルアップ)
SDモジュール: MSC-MOD20
```

気圧計 (以下のものをベースにI2Cを4.7kプルアップしている)。
http://qiita.com/7of9/items/09272fcfb56bd479c679


## 背景

MSC-MOD20というSDカードモジュールを使ってみる。
[MSC-MOD20の取説]( http://www.microtechnica.tv/support/manual/msc-mod20_man.pdf 
)

取説には2.2kでプルアップと記載があるが、今回は4.7kプルアップとしている。

MSC-MOD20の価格は4500円。
http://www.microtechnica-shop.jp/shopdetail/000000000026/

ESP8266の場合は、microSDスロット(600円)さえあればmicroSDに保存できる。
http://qiita.com/7of9/items/280758359f3d2c0c7fe8

MSC-MOD20をESP8266で試す目的は、MSC-MOD20の癖を把握すること。変な癖がないか把握し、あれば対応を検討する。
将来的には把握した情報をもとに、別のマイコンで使う。
その前準備として、実装が簡単なESP8266を使った。

## 実装

MSC-MOD20のパッケージ。RTC用の水晶振動子があり基板上に実装する。水晶振動子を使わないという場合もある。取説参照。
こちらでは水晶振動子を実装して使用した。

![quuta.png](https://qiita-image-store.s3.amazonaws.com/0/32870/1e7b9393-ef76-b539-37b8-eba469ef5acd.png)

## 配線

MSC-MOD20とESP8266の配線は以下とした。
I2Cでの使用としている。

| MSC-MOD20 | ESP8266 | 備考 |
|:-:|:-:|:-:|
| 1: UART TX | NC |   |
| 2: UART RX | NC | I2C BUSY / 今回未使用  |
| 3: I2C SCL | 5: I2C SCL | |
| 4: I2C SDA | 4: I2C SDA | |
| 5: MODE 1 | GND | I2C用 |
| 6: UART BUSY | NC | | 
| 7: NC | NC | |
| 8: MODE 2 | VCC | I2C用 |
| 9: RESET(負論理) | VCC | |
| 10: GND | GND | |
| 11: VCC | VCC | | 
| 12: WAKE | NC | 今回は未使用 |
| 13: Vbat | VCC | 外部RTC用バッテリーを接続してもいい |

## 配線状況

@hotchpotch さんが紹介されていた[スルーホール用テストワイヤー](http://qiita.com/hotchpotch/items/074c97c12291bcc59028)を使った。4500円するモジュールをテスト使用ではんだ付けすると、実使用時に苦労する。こういうツールは便利だ。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/f0645f5e-b136-b5a8-a139-d1fade3a7798.png)

全体の接続状況

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/0bd92ecb-c55b-25b7-f5e6-8b63bc3c0bc0.png)


## code v0.2

[朝飯前](http://qiita.com/7of9/items/1c40de42ab2647918140)の結果、以下のコードとなった。

```esp8266_160730_MSC-MOD20p1.ino
#include <Wire.h>

#define DEVICE_ADDRESS (0xA4 >> 1)

void setup() {
  Serial.begin(115200);
  Serial.println("");

  Wire.begin();
  Wire.setClock(100000L); // 100kHz
}

void loop() {
  helloWorld();
  delay(3000); // msec
}

void readData() {
  Wire.requestFrom(DEVICE_ADDRESS, /* length= */1);  
  char code = Wire.read();
  delayMicroseconds(30);

  Serial.println(code);
}

void helloWorld()
{
  Wire.beginTransmission(DEVICE_ADDRESS);
  Wire.write(0x0A);
  Wire.endTransmission(); 
  delayMicroseconds(30);

  for(int loop=0; loop<3; loop++) {
    readData();
  }
}
```


```txt:結果
GHI Electronics, LLC 
----------------------
 ALFAT SoC Processor 
!00
!00
!00
!00
!00
!00
!00
!00
!00
!00
!00
```

ほぼ読めたので、今後はSD読書きなどの詳細作業に移行する。
【Swift】RxSwiftのPlaygroundを読む⑧

RxSwiftのPlaygroundを読んでみるシリーズ今回は
エラー処理についてです。
([Error_Handling_Operators](https://github.com/ReactiveX/RxSwift/blob/master/Rx.playground/Pages/Error_Handling_Operators.xcplaygroundpage/Contents.swift))

# Error Handling Operators
今回はerrorを扱う処理についてです。
[【Swift】RxSwiftのPlaygroundを読む①](http://qiita.com/KentaKudo/items/d9ff7cdc639c24301456)でみたように、
Observableにerrorが流れてくると、もうそのObservableには何も流れてきません。

それでは困る！という場合や、
errorではなくcompleteとして処理したい場合などに以下のOperatorを使用します。

## catchErrorJustReturn
errorが流れてきたら、
errorを引数で渡した値のnextイベントに変換する。
その後completeを自動で流し、Observableを終了する。

```swift
let disposeBag = DisposeBag()
extension String: ErrorType {}

let catchErrorJustReturn = PublishSubject<String>()

catchErrorJustReturn
    .catchErrorJustReturn("🍑")
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

catchErrorJustReturn
    .onNext("🍎")

catchErrorJustReturn
    .onError("An error occurred.")
```

**結果**

```
Next(🍎)
Next(🍑)
Completed
```

## catchError
errorが流れてきたら、
errorを流す代わりに、
subscribe対象のObservableを、
引数で指定した別のObservableに変更する。

```swift
let disposeBag = DisposeBag()
extension String: ErrorType {}

let catchError = PublishSubject<String>()
let recover = BehaviorSubject(value: "🍊")

catchError
    .catchError { _ in recover }
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

catchError
    .onNext("🍐")
catchError
    .onError("An error occurred.") // このタイミングでrecoverをsubscribeし、BehaviorSubjectの挙動に従い🍊が流れる

recover
    .onNext("🍇")
```

**結果**

```
Next(🍐)
Next(🍊)
Next(🍇)
```

## retry
errorが流れてきたら、
errorを流す代わりに、
同じObservableをsubscribeし直す。
引数でsubscribeし直す回数を指定できる。
指定しない場合は無限にsubscribeし直す。

```swift
let disposeBag = DisposeBag()
extension String: ErrorType {}

var count = 0

let retry = Observable<String>.create { observer in
    
    if count < 5 {
        
        observer.onNext("🍑")
        observer.onError("An error occurred.")
        
        count += 1
    }
    else {
        
        observer.onCompleted()
    }
    
    return NopDisposable.instance
}

retry
    .retry()
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)
```

**結果**

```
Next(🍑)
Next(🍑)
Next(🍑)
Next(🍑)
Next(🍑)
Completed
```

# おわりに
エラー時の取り扱いは要件に直結する重要な部分なので、
しっかり理解したいです。

次回最後はデバッグ処理についてです。

# 参考
https://github.com/ReactiveX/RxSwift/tree/master/Rx.playground