ERBとCSVを使って簡単な自分用ドリルを作る
最近シェルの勉強をしたいんですが、以前SQLを勉強した時のように基本的なシェルを反復して書くのが一番では? と思って、ドリルのようなものが欲しくなりました。
そこで、CSVにお題とお題の答えを書き連ねたらアコーディオンで答えを出したり隠したりしてくれるHTMLを出すコードと、そのHTMLを見るアプリ*1を書いたのでポスト。
使い方は、
$ ruby generator/generator.rb input.csv > drill.html
を実行して drill.html
をブラウザで開く、です。アプリで見る場合はさらに
$ cp drill.html cp drill.html CSDriller/app/assets/drill.html
とした後、一緒についているAndroidプロジェクトをビルドしてください。
実際動かしてみると下記のような感じです。
参考
- http://d.hatena.ne.jp/littlebuddha/20081022/1224645199
- https://qiita.com/shizuma/items/7719172eb5e8c29a7d6e
- http://magazine.rubyist.net/?0017-BundledLibraries
- https://qiita.com/kozo002/items/bcf693738a37aa9ee917
特に上記記事のアコーディオンがよすぎて作りたくなったので多謝。
Cocos2d-x 2.2.6をMac OS Sierraで動くようにするまでのメモ
仕事でやってて面白かったので許可を取って公開。
環境
- Cocos2d-x 2.2.6
- Eclipse Oxygen.1a Release (4.7.1a)
- Android NDK, Revision 10e
- Android SDK & tools v24.0.3 のもの一式
- Android Studioとは別に用意
- Eclipseの環境設定で下図のように設定
メモ
プロジェクトの作成
python create_project.py -project MyGame -package com.MyCompany.AwesomeGame -language cpp
Eclipse インストーラからJavaのIDEをインストールして環境変数を設定
Help > Install New SoftWare
Work with
の欄にhttps://dl-ssl.google.com/android/eclipse
を入力
cocos2dxのプロジェクトをインポートとプロジェクト間の依存関係の設定
Import > Andorid > Existing Android Code Into Workspace
でcocos2d-x-2.2.6/cocos2dx
のplatform/andorid/java
をインポートCopy projects into workspace
にチェックしておく
Import > Andorid > Existing Android Code Into Workspace
でcocos2d-x-2.2.6/cocos2dx/ProjectName
をインポートCopy projects into workspace
にチェックしないProjectName
のAndroidManifest.xml 中のminSDKVersion
が小さすぎるので14くらいにあげておく
PackageManager
上でProjectName
の上を右クリックしてProperties > Android
を開き、Libraryのところで、libcocos2dxを指すよう設定するisLibrary
のチェックはしない(アプリプロジェクトにisLibraryのチェックをするとapkが生成されない)
アプリ側のプロジェクトのLinked Resourcesの修正
- プロジェクトのところで右クリックして
Properteis > Resources > Linked Resources
のLinked Resources
のタブを確認。Classes
,cocos2dx
,extensions
,scropting
の壊れているパスを修正
古めのNDKを用意してNDK_ROOTの環境変数を設定
- 古めのNDK(Android NDK, Revision 10e)を https://developer.android.com/ndk/downloads/older_releases.html からDL
Eclipse
のPreferences > Android > NDK
の項目の NDK LocationにDLしてきたNDKを配置したパスを書く
Preferences > Android > NDK
に設定したパスが Eclipse に見えてないことがあるのでC/C++ > Build > Environment
にもNDK_ROOT
として追加Bulid Project
した結果、build_native.sh
は走ってくれたが。。
トラブルシューティング
Could not find BuildTest.apk!
...
- https://stackoverflow.com/questions/4778113/android-eclipse-could-not-find-apk
- アプリケーションプロジェクトのプロパティに
isLibrary
のチェックが入ってないか
Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!
Failed to load /Users/woshidan/Library/Android/sdk/build-tools/26.0.2/lib/dx.jar
- https://stackoverflow.com/questions/5228453/android-adt-error-dx-jar-was-not-loaded-from-the-sdk-folder
Eclipse起動時に Failed to get the required ADT version number from the SDK
- Eclipseが想定しているADTのライブラリ構成のパスが古いせいで、ビルドツールの特定のライブラリが見つからないって言われてる(その2)
- Andorid SDKと一緒のディレクトリに入っているツールは
build-tools
以外は最新版しか保持できない。buildtools
以外のツールのバージョンが v26以上だと同様のメッセージが出るのでAndorid Studio用のSDKとは別のディレクトリにEclipse用の古いバージョンのSDKを入れ直してそちらを使う
エミュレータを起動しようとしたら[Start]が押せず詳細を確認したら Google Nexus 5X No longer exists as a device
Description Resource Path Location TypeThe container 'Android Dependencies' references non existing library'cocos2d-x-2.2.6/cocos2dx/platform/android/java/bin/libcocos2dx.jar' ...
- http://renkaze.seesaa.net/article/405756568.html
libcocos2xd
のプロジェクトでjar
を吐き出すパスが別のパスに設定されているlibcocos2dx
のプロジェクトで右クリックしてProperties > Java Build Path < Source
の下側のDefault output folder
をlibcocos2dx/bin/classes
に設定
java.lang.IllegalArgumentException: No configs match configSpec
というエラーでエミュレータで起動するとクラッシュする
- http://mapyo.hatenablog.com/entry/2013/08/27/Mac%E3%81%ABCocos2d-x%E3%81%AE%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E3%82%92%E4%BD%9C%E3%82%8B
- エミュレータ作成時の設定で
Emulation Options
のUse Host GPU
をチェック
Eclipse
でエミュレータを起動しようとしたら PANIC: Missing emulator engine program for 'arm' CPUS...
と出る
- Eclipse の ADT からエミュレータのシステムイメージが見えてないとかそういうことな気がする。
- Android Studioで使っている最新のAndroid SDK & Tools とは別にEclipse用の古いバージョンのSDKを入れ直したら解決した
Google Nexus 5X no longer exists as a device
とでて Nexus 5
のスキンのエミュレータがつけない
- Eclipse の ADT は対応しているバージョンより新しいAndroid SDKのスキンは存在しないものとして扱う、みたいな雰囲気
- Eclipse のデバイスマネージャから選択できるスキンのエミュレータを使う
まとめ
そろそろEclipseでAndroidを開発するのをやめたほうがいいのでは。
現場からは以上です。
ウェブオペレーション サイト運用管理の実践テクニックを読んだ
ウェブオペレーション ―サイト運用管理の実践テクニック (THEORY/IN/PRACTICE)
- 作者: John Allspaw,Jesse Robbins,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/05/14
- メディア: 大型本
- 購入: 10人 クリック: 923回
- この商品を含むブログ (50件) を見る
前職で研修に使われていた記憶があり、いい本なのかなーと思って読みました。 運用系の仕事をしているわけではないので、一ヶ月強かけてなんとか読みおおせた感じです。
各章はかなり生き生きとした文章で、場合によっては「これはもしかして飲み会の書き起こしではないだろうか」「これ開発者の前に出したらグーパンされても文句言えないのでは」と感じた章もいくつかあり、いんたーねっつの進歩を体感することができます。
なんとか読みおおせた印象としては
- ウェブサービスのサーバ構成について、それぞれのサーバの大まかなイメージが頭に描けるようになった
- 結構前の章でいいよって言われていることが次の章でそうでもないよって言われてたりして、道具を使ったり人の意見を採用する前に要件を確認するのは大事だな、と思えた
- もともとあまりシェルになじみのない人でなんでもLL言語+RDBMSで考えがちだったのですが、監視のシステムの実装例でawkなどが出てきたり、道具の得意分野に合わせていろんな道具を操ることについて考えさせられた
- Dynamoの論文の特徴が面白かった
- Consistent hash, read repair, hinted handoffが書いてあったよと紹介されていて、特に気になったのは read repair.
- 高可用性(リクエストがあったらいつでも応答できる)と応答速度/パフォーマンス(速くレスポンスが返ってくる)と一貫性(データに矛盾が生じない)が違う、相反しない、という例がくどくどと書かれていて身にしみた
- 分割耐性はまだ自信がない
- みんな結構データセンタや社内システムの外からファイアウォールでping弾かれてて面白かった
- サーバの監視システムについて、死活監視・リソース監視(Nagiosなど)・それらの結果の表示(Cacti, Muninなど)、みたいなソフトごとの得意領域があるんだなみたいなイメージが湧いた
- レスポンスの配信の節で、サーバとクライアントの間に一度に取得できるオブジェクト数の上限があるということを知らなかったため、デバッグコンソールを眺めてみたり
でした。
個人的に特に面白かったのは、6章、9章、12章、15章。
6章の学生時代のサイト運営経験から右往左往しながらシステムを運用していく様子に共感を覚え、9章の急増したトラフィックへの障害対応の文章を読んでリクエストがどのサーバに順に到達するかのイメージを描き、12章でこの人本当にMySQL好きなんだなという気持ちになり*1、15章で高分散型*2NoSQLの監視ソフトウェアの違いや比較的小さい規模で動かすものと大きい規模で動かすものの思想の違いに思いを馳せたり。。
運用経験のない人が一人で読むとどうなのかな、と思いつつ、ここで紹介されている技術は今の時代ではそれなりに枯れていたり廃れていたり流行っていたりするためインターネットにまとめられた記事を適宜参照しながら進めました。しかしまあ、早口でまくしたてるクセがある他部署の先輩の運用談義を聞かされている風味もあり、本開いてる間はなんだか忙しかったのでした...。
前述の文体が気になる点や2011年出版でやや古いところもあるので、この本のポジションに収まる新しい本とかあったらそちらも読んでみたいです。
現場からは以上です。
Athenaでクエリの実行結果を使い回すために最近投げたクエリとそのquery_execution_idを記録する
Amazon Athena
では
S3上にあるファイルをスキャンした量に応じた料金 + S3をスキャンするためにGETしたリクエスト数(+ファイル容量)
に応じて課金されます。
また、Athenaでは一回SQLを実行した時に query_execution_id
が発行され、同じ query_execution_id
を使って GetQueryResults
のAPIに複数回リクエストを送ると二回目以降は一回目の実行結果が再利用され、新しいクエリは実行されません*1。
このため、一度検索した結果が使い回せるのであれば、 query_execution_id
を控えておいて結果を再利用した方が良いです。
というわけで、雑に CSV
で直近で実行した クエリ
と query_execution_id
の対応を控えておいて、実行しようとしたクエリがすでに実行済みであれば教えてくれるスクリプトを書いたのでポスト。
gem にしようかと思ったけどそれほど大きくなかったのでひとまずこれで。
# athena_query_keeper.rb require "csv" class AthenaQueryKeeper def initialize(csv_path, keepe_count=20) @csv_path = csv_path @keepe_count = keepe_count @keeped_queries = [] begin CSV.foreach(@csv_path) do |row| @keeped_queries.push({ time: row[0], execution_id: row[1], query_string: row[2] }) end rescue Exception => ex puts ex puts "query keeped csv(path=#{csv_path}) was not found or format was broken." puts "new csv will be created." end end def keep(excution_id, query_string) if @keeped_queries.count >= @keepe_count @keeped_queries.slice!(0, @keeped_queries.count + 1 - @keepe_count) end @keeped_queries.push({ time: Time.now.to_i, execution_id: excution_id, query_string: query_string }) flush end def flush CSV.open(@csv_path, 'w') do |csv| @keeped_queries.each do |query| csv << [ query[:time], query[:execution_id], query[:query_string] ] end end end def keeped_execution_id_for(query_string) keeped_query = @keeped_queries.find { |query| query[:query_string] == query_string } if keeped_query.nil? puts "query: #{query_string.slice(0, 60)} ... has been not executed recently." "" else puts "query: \"#{query_string.slice(0, 60)} ... \" has been executed recently." puts "you should reuse that result unless the result update must be used." keeped_query[:execution_id] end end end
# test.rb require 'aws-sdk-athena' require "#{File.dirname(__FILE__)}/athena_query_keeper.rb" query_string = ARGV[0] client = Aws::Athena::Client.new begin query_execution_id = nil athena_query_keeper = AthenaQueryKeeper.new("./sample.csv", 20) keeped_query_id = athena_query_keeper.keeped_execution_id_for query_string if keeped_query_id.empty? start_query_response = client.start_query_execution({ query_string: query_string, query_execution_context: { database: "mydatabase", }, result_configuration: { output_location: "s3://example-woshidan-test/athena_query_result" }, }) sleep(3) query_execution_id = start_query_response.query_execution_id athena_query_keeper.keep(query_execution_id, query_string) else puts "reuse query result for id=#{keeped_query_id}." query_execution_id = keeped_query_id end puts "query_execution_id: #{query_execution_id}" get_query_response = client.get_query_results({ query_execution_id: query_execution_id }) get_query_response.inspect rescue Aws::Athena::Errors::InvalidRequestException => ex puts ex.inspect ensure puts "query request ended." end
$ ruby test.rb 'SELECT * FROM mydatabase."athena_logs_20171003_app" WHERE user_id = "tester" LIMIT 10;' query: SELECT * FROM mydatabase."athena_logs_20171003_app" WHERE us ... has been not executed recently. result_csv_file_key: 32e86285-e0c5-4329-973d-38bd039945e4 #<Aws::Athena::Errors::InvalidRequestException: Query did not finish successfully. Final query state: FAILED> query request ended. $ ruby test.rb 'SELECT * FROM mydatabase."athena_logs_20171003_app" WHERE user_id = "tester" LIMIT 10;' query: "SELECT * FROM mydatabase."athena_logs_20171003_app" WHERE us ... " has been executed recently. you should reuse that result unless the result update must be used. reuse query result for id=32e86285-e0c5-4329-973d-38bd039945e4 result_csv_file_key: 32e86285-e0c5-4329-973d-38bd039945e4 #<Aws::Athena::Errors::InvalidRequestException: Query did not finish successfully. Final query state: FAILED> query request ended.
参考
AWS CLIでAWS Athenaのクエリがデータベースが見つからないためになんども失敗する場合は結果出力先のS3のバケットのregionを確認する
俺の屍を越えていけ、的なメモ。
require 'aws-sdk-athena' client = Aws::Athena::Client.new begin start_response = client.start_query_execution({ query_string: "SELECT * FROM samples limit 10", query_execution_context: { database: "mydatabase", }, result_configuration: { output_location: "s3://sample-woshidan-test-tokyo/athena_query_result" }, }) sleep(5) result_response = client.get_query_results({ query_execution_id: start_response.query_execution_id }) rescue Aws::Athena::Errors::InvalidRequestException => ex puts ex.inspect ensure puts "Ensure" end
上記のコードで aws-sdk-athena
でAthena のクエリを飛ばそうとしたら
Query did not finish successfully. Final query state: FAILED (Aws::Athena::Errors::InvalidRequestException)
というエラーが出て失敗する。なんで失敗したのかさっぱりわからないので、CLIで実行し直すと、
$ aws athena start-query-execution \ > --query-string "SELECT * FROM mydatabase.samples limit 10;" \ > --result-configuration OutputLocation=s3://sample-woshidan-test/athena_query_result { "QueryExecutionId": "f8e45456-238a-44ba-955a-40f048e5c3b2" } $ aws athena get-query-execution --query-execution-id f8e45456-238a-44ba-955a-40f048e5c3b2 { "QueryExecution": { "Status": { "SubmissionDateTime": 1506675885.243, "State": "FAILED", "CompletionDateTime": 1506675885.387, "StateChangeReason": "com.facebook.presto.hive.DataCatalogException: Namespace mydatabase not found. Please check your query." }, "Query": "SELECT * FROM mydatabase.logs limit 10", "Statistics": { "DataScannedInBytes": 0, "EngineExecutionTimeInMillis": 53 }, "ResultConfiguration": { "OutputLocation": "s3://sample-woshidan-test/athena_query_result/f8e45456-238a-44ba-955a-40f048e5c3b2.csv" }, "QueryExecutionId": "f8e45456-238a-44ba-955a-40f048e5c3b2" } }
というメッセージが出て、どうも database
が見つからないらしい。
もしかして、 AWS のアカウントの region
を間違ったかな、とAWS CLIの設定で使う region を Athenaの管理画面で表示されている region に設定しなおしてみると
- region = ap-northeast-1 + region = us-east-2
The S3 location provided to save your query results is invalid. Please check your S3 location is correct and is in the same region and try again. If you continue to see the issue, contact customer support for further assistance.
戻すと
+ region = ap-northeast-1 - region = us-east-2
Query did not finish successfully. Final query state: FAILED (Aws::Athena::Errors::InvalidRequestException)
どっちに設定しても何かしらダメっぽい...
最終的に
自分がAthenaのクライアントとして選んだ aws-athena-client
はその実装でAWS CLIを利用しています。
そして、AWS CLIで設定値として使うregion は ~/.aws/config
で指定しているためか
- クエリを投げるAthenaのデータベースが
~/.aws/config
で指定したregionに存在すること - クエリ結果の出力先のS3のバケットが
~/.aws/config
で指定したregionに存在すること
の2点がAWS CLIでAthenaにクエリを投げるためには必要みたいです。そして最終的に結果出力先のS3のバケットのregionをAthenaのデータベースのregionに揃えてことなきを得ました。
AthenaのクエリでスキャンするS3のバケットのregionは、AWS CLIで使うIAMアカウントがアクセス権を持ってさえいればAthenaのデータベースのregionと違ってもクエリが実行できるのもあっていまいち原因がわからず焦りました。
もしかしたらAthena - S3 間だけでなく、複数のAWSのサービスが協調して動く場合、CLIが一個しかregionの値を持たない、みたいなことが原因で似たようなトラブルはあるかもなと思いつつ、現場からは以上です。
iOSにてzlibのdeflate()コマンドでファイルをgzip形式で圧縮する方法について
zlibについてコピペで使うのはいやだなと思ったのでちょっと調べてメモ。
比較的小さいファイルの圧縮を行うなど、圧縮前後のデータを全てメモリ上に展開できる場合は、 compress()
を使って一気に圧縮できますが、今回はストリームから少しずつデータを出し入れして圧縮していく deflate()
コマンドを利用する場合についてメモします。
zlibとは
まず、zlibが何かをこちらのページから引用します。
zlibとは、圧縮アルゴリズムの一種である Deflate のライブラリであり,C#, Haskell, Java, Perl, Python, Ruby など,主要なプログラミング言語では,軒並み使えるように整備されています.圧縮・伸長が高速なこともあり,ディスク領域の有効利用や通信量の削減を目的として,zlib は気軽に利用できます.
XCodeでのiOSの開発環境への導入について
XCodeでのiOSの開発環境下では、iOS SDKに一部APIが利用できる状態でzlib.hが含まれているため umcompress()
はリンクエラーで使えないようでしたが、compress()
については zlib.h
をimportすれば利用可能でした。
導入しようとしたプロジェクトによっては zlib.h
のimportだけでは
Undefined symbols for architecture x86_64: "_deflate", referenced from: +[GzipSample compress:] in Sunaba(GzipSample.o) "_deflateInit2_", referenced from: +[GzipSample compress:] in Sunaba(GzipSample.o) "_deflateEnd", referenced from: +[GzipSample compress:] in Sunaba(GzipSample.o) ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
のようなエラーメッセージでリンクに失敗することがあります。
その場合は、
libzを利用するアプリのプロジェクトのターゲットの設定で、 Build Phases > Link Binary With Libraries
から libz
と入力して出てきたものの中から利用するバージョンの libz
を追加してビルドしなおしてください *1 。
今回は圧縮の方法についてだけひとまずメモしようと思っているのでこれで進みますが、iOS添付でない zlib.h
の導入には以下が参考になりそうです。
https://gist.github.com/dulaccc/75f1f49f53e544cef549
zlibでファイルを圧縮する
z_stream構造体のオブジェクトを生成
zlibの基本的な使い方ですが、 z_stream
構造体のオブジェクトを生成して、 zalloc, zfree, opaque
のメンバを設定します。
z_stream stream; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.opaque = Z_NULL;
この時、設定する値はデフォルト値である Z_NULL
で基本的に問題ありません。gzip形式で圧縮する場合は、 delateInit2()
で stream の初期化処理を行います。
入力データの設定
z_stream
構造体の avail_in
, next_in
の設定をします。
stream.next_in = (Bytef *)[inputData bytes]; // 入力バッファへのポインタ stream.avail_in = (uint)[inputData length]; // 入力データの量
出力データの初期設定
自分の環境のzlibではデフォルト値でもよかったんですが、ライブラリなどにする場合、どのzlibとリンクされるか固定ではないので、 z_stream
構造体の avail_out
, total_out
の初期値の設定をしておきます。
stream.total_out = 0; // これまでの出力されたデータの合計長 stream.avail_out = 0; // 出力データのバッファ上の残量
ストリームの初期化
gzip圧縮の場合、ストリームの初期化は下記の deflateInit2()
コマンドで行います。
// int deflateInit2(z_stream *strm, // int level, .... 圧縮レベル(数値が小さいほど圧縮時間が小さく、大きいほど圧縮後のサイズが小さい) // デフォルト Z_DEFAULT_COMPRESSION(=6) // 圧縮速度最高 Z_BEST_SPEED(=1) // 圧縮率最高 Z_BEST_COMPRESSION(=9) // 圧縮無効 Z_NO_COMPRESSION(=0) // int method, .... 圧縮方法 zlib-1.2.6 で指定できるのは Z_DEFLATED のみ // int windowBits, ウィンドウ・サイズ gzip 形式では 31 を指定する必要あり // int memLevel, .. メモリの消費量を指定 大きくても特に嬉しいことはない. デフォルト8 // int strategy); . 圧縮の方式を指定。デフォルトは Z_DEFAULT_STRATEGY deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY)
これによって、出力バッファの合計長 stream.total_out
や、出力データのバッファ上の残量 stream.avail_out
などの出力関連のパラメータが設定されます。
圧縮したデータをstreamに出力する
int result = deflate(&stream, Z_FINISH); // 戻り値の意味 // Z_OK ... まだ出力できる範囲が残っているのでもう一回deflate()が呼び出せる // Z_STREAM_END ... もう出力できる範囲がない // Z_BUF_ERROR ... 入力データ、出力バッファの一時的な不足 // Z_STREAM_ERROR ... next_in, next_outがNULLの時や内部状態が破壊された
deflate
を実行するたびに stream.next_out
で指定されたポインタのバッファへ圧縮結果が書き込まれます。
この出力先のポインタは書き込むたびに書き込んだ分ずらす必要があります。
stream.next_out = (uint8_t *)[data mutableBytes] + stream.total_out; // ... 出力先のバッファのポインタの位置をこれまで書き込んだ分 stream.total_out だけずらして設定 // [NSMutableData mutableBytes] はNSMutableDataで管理している生のバイト列へのポインタを返してくれる
また、出力を書き込むたびにバッファ残量の値が減少するので、不足するようであれば書き込み先のバイト列の長さを伸ばしたり、次に書き込む前に出力バッファ残量が不足しないよう設定し直してやる必要があります。
if (stream.total_out >= [data length])
{
data.length += ChunkSize;
}
stream.avail_out = (uInt)([data length] - stream.total_out);
圧縮処理に使ったメモリの解放
最後に後始末のため deflateEnd(&stream)
を呼び出して、使ったメモリを開放します。
deflateEnd(&stream);
最終的に書いたみたコード
以上を踏まえつつ、
のコードを参考にして書くとこういうコードになりました。
#import <Foundation/Foundation.h> #import <zlib.h> static const NSUInteger CHUNK_SIZE = 1000; // バイト列を伸ばす処理を確認するために小さめにしている static const int GZIP_WINDOW_BITS = 31; static const int DEFAULT_MEMORY_USAGE = 8; + (NSData *)compress:(NSData *)sourceData { if ([sourceData length]) { z_stream stream; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.opaque = Z_NULL; stream.avail_in = (uint)[sourceData length]; stream.next_in = (Bytef *)[sourceData bytes]; stream.total_out = 0; stream.avail_out = 0; if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, GZIP_WINDOW_BITS, DEFAULT_MEMORY_USAGE, Z_DEFAULT_STRATEGY) == Z_OK) { NSMutableData *data = [NSMutableData dataWithLength:CHUNK_SIZE]; int result = 0; while (result == Z_OK) { if (stream.total_out >= [data length]) { data.length += CHUNK_SIZE; } stream.next_out = (uint8_t *)[data mutableBytes] + stream.total_out; stream.avail_out = (uInt)([data length] - stream.total_out); result = deflate(&stream, Z_FINISH); } deflateEnd(&stream); if (result != Z_STREAM_END) { return nil; } data.length = stream.total_out; return data; } } return nil; } @end
参考
- http://s-yata.jp/docs/zlib/
- https://discussions.apple.com/thread/1494368?start=0&tstart=0
- https://gist.github.com/dulaccc/75f1f49f53e544cef549
- https://oku.edu.mie-u.ac.jp/~okumura/compression/zlib.html
- https://developer.apple.com/documentation/foundation/nsmutabledata?language=objc
- http://d.hatena.ne.jp/MoonMtLab/20141105/1415136219
- https://github.com/nicklockwood/GZIP
- https://stackoverflow.com/questions/18053546/undefined-symbols-for-architecture-i386-deflate-referenced-from-platcompres
どー考えてもライブラリのリンク関連についてまた勉強する必要がありますが、それはおかわり案件にします。現場からは以上です。
Heartbeatとブロックデバイスについて
短いですが、一応何かしら書くぞということで、本を読んでいたら「Heartbeatがスタンバイしたサーバを有効にする」「ブロックデバイスをレプリケーション」と出てきたのが意味がわからなかったのでメモ。
Heartbeat関連
- クラスタに関することでハートビートといえばHAクラスタを実現する上で利用される仕組み
- クラスタの種類
- ハートビート色々
- http://www.atmarkit.co.jp/ait/articles/0711/13/news139_2.html の記事では
- Heartbeat …
オープンソースソフトウェア「Heartbeat」全体
- heartbeat …
上記のHeartbeatで提供されるプログラム、もしくはそれを起動したときのプロセス
- ハートビート …
HAクラスタを構成するPCが相互に状態監視をする際のネットワーク構成、およびその通信を指すものとします
- 数ページしか調べてない時点で上記とちょっと違う定義が出て来ていて、一番上の行にあるのがそれ。要注意単語。
- Heartbeat …
- http://www.atmarkit.co.jp/ait/articles/0711/13/news139_2.html の記事では
- ハートビートの通信をどう行うか
Linux系OSのブロックデバイスとキャラクタデバイス
- Linux系OSでは、デバイスはコンピュータに接続された周辺機器のことをデバイスと呼び、
/dev
以下に作成されるデバイスファイルが周辺機器のハードウェアへのインタフェースとなっている - ブロックデバイスとは、ある一定の量(通常512~2048バイト)の読み書きをランダムアクセスで行えるデバイスで、ディスク装置全般が該当する
- キャラクタデバイスはデータの入出力をバイト(1文字)単位で扱うデバイスで、データの読み出しや書き込みがシーケンシャルアクセスとなる
- 一度読み書きしたデータを後戻りして再び読み書きすることはできない
- キーボードやマウスなどが該当する
参考
- Heartbeat関連
- http://www.atmarkit.co.jp/ait/articles/0711/13/news139.html
- http://itpro.nikkeibp.co.jp/article/COLUMN/20090224/325384
- https://h50146.www5.hpe.com/products/software/oe/hpux/developer/column/sg_text_02/
- https://qiita.com/growsic/items/fead30272a5fa374ac7b
- https://reboot.makeall.net/2010/11/25/about-heatbeat/
- ブロックデバイスとキャラクタデバイス関連
ウェブオペレーションまとめ用に読み直してるんですが、真面目に読むと11章や12章がとても重くて少しいやですね。わかんないものはわかんないで仕方ないですが。
*1:ここのwebアプリケーションサーバをEC2で調達したりする話を聞いたことが多いので、なんとなくクラスタ=クラウド感がありました