GCS上のファイルを結合する

Google Cloud Storage (以下GCS) 上のファイルを結合して、新しいファイルを作成する [複合オブジェクト](https://cloud.google.com/storage/docs/composite-objects) を紹介します。

# gsutil compose

GCS上のファイルの結合を簡単にできるのが `gsutil compose` commandです。
例えば、以下の3つのファイルを結合して、 `compose.txt` を作成する場合は1commandで達成できます。

* gs://cpb100demo1-input/1.txt
* gs://cpb100demo1-input/2.txt
* gs://cpb100demo1-input/3.txt

```
gsutil compose gs://cpb100demo1-input/1.txt gs://cpb100demo1-input/2.txt gs://cpb100demo1-input/3.txt gs://cpb100demo1-input/compose.txt

Composing gs://cpb100demo1-input/compose.txt from 2 component object(s).
```

`X.txt` はまんまXが1文字だけ書いてあるファイルなので、 `1.txt` , `2.txt` , `3.txt` を結合させた `compose.txt` は `123` と書いてあるファイルになります。

```
gsutil cat gs://cpb100demo1-input/compose.txt
1
2
3
```

一度の `gsutil compose` で指定できるファイルの数は32個までなので、33個以上をファイルを結合したい場合、 `gsutil compose` を複数回実行してやります。

# Component Count

複合オブジェクトは、結合できる数は1024以内という制限があります。
指定した複合オブジェクトがいくつのファイルを内包しているのかは、オブジェクトのmeta情報としてComponent Countを参照すれば分かります。
上で作成した `compose.txt` は `1.txt` , `2.txt` , `3.txt` の3つのファイルを結合しているので、Component Countは3になります。

```
gsutil ls -L gs://cpb100demo1-input/compose.txt

gs://cpb100demo1-input/compose.txt:
    ...
    Component-Count:        3
    ...
```

Component Countは結合すると増えていきます。
`compose.txt` に `4.txt` を結合して、`composeV2.txt` を作成した場合、Component Countは4となります。

```
gsutil compose gs://cpb100demo1-input/compose.txt gs://cpb100demo1-input/4.txt gs://cpb100demo1-input/composeV2.txt

Composing gs://cpb100demo1-input/composeV2.txt from 2 component object(s).

gsutil ls -L gs://cpb100demo1-input/composeV2.txt
gs://cpb100demo1-input/composeV2.txt:
    ...
    Component-Count:        4
    ...
```

更に `compose.txt` と `composeV2.txt` を結合して、 `composeV3.txt` を作成した場合、Component Countは7となります。

```
gsutil compose gs://cpb100demo1-input/compose.txt gs://cpb100demo1-input/composeV2.txt gs://cpb100demo1-input/composeV3.txt
Composing gs://cpb100demo1-input/composeV3.txt from 2 component object(s).

gsutil ls -L gs://cpb100demo1-input/composeV3.txt
gs://cpb100demo1-input/composeV3.txt:
    ...
    Component-Count:        7
    ...
```

これはGCSの後ろ側にいるColossusがうまいことやってるんじゃないかと思います。
Colossusは分散ファイルシステムなので、元々物理的に複数に別れているファイルを1つのファイルとして扱うことができるので、compose時も物理データを結合しているわけではなく、Meta情報のみ作っているのではないかと思います。

![gsutil compose.png](https://qiita-image-store.s3.amazonaws.com/0/15640/9ace6df3-c4e5-6057-435a-ab30d9432582.png)


Component Countは一回ファイルをUploadし直すとクリアされるので、1024に近付いてきたら、一回DownloadしてUploadしなおすとクリアできます。
また、Component Countが1の時は、Meta情報のComponent Countが省略されます。

```
gsutil cp gs://cpb100demo1-input/composeV3.txt .
gsutil cp composeV3.txt gs://cpb100demo1-input/composeV3new.txt
gsutil ls -L gs://cpb100demo1-input/composeV3new.txt

// 直接Uploadしたので、ComponentCountが1になって、Meta情報から省略された。
gs://cpb100demo1-input/composeV3new.txt:
    Creation time:          Sat, 03 Dec 2016 09:03:09 GMT
    Update time:            Sat, 03 Dec 2016 09:03:09 GMT
    Storage class:          STANDARD
    Content-Length:         14
    Content-Type:           text/plain
    Hash (crc32c):          XYmy3A==
    Hash (md5):             Flb7WCw+G520MsWa1noN5g==
    ETag:                   CPjn4pbV19ACEAE=
    Generation:             1480755789739000
    Metageneration:         1
```

# おしまい

複合オブジェクトは頻繁に使うことはないですが、分割Uploadした後に合体させたり、すでにGCSにUploadされているファイルを結合したりするのに便利なので、覚えておくと何かいいことあるかも！