不動産と株の投資日記

日々の大家業の備忘録

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

お名前.com の不正請求??

お名前.com の請求ログを見てたら、与信失敗だらけです、、、orz

別に残高がない訳じゃなくて、登録しているカードの有効期限が切れているだけなんですが、、、


で、10/01 に4309円も請求があります。なんだろう??

onamae.png

明細を見ると、.com の1年更新費用らしいです、、、

onamae2.png

うーん、994円の請求は正しいはずなんで、10/01 の請求だけ変です、、、


もしかして、更新引き落としの日だけ値上げしてるとかないですよね??

与信なくてよかった、こわすぎ。自動更新切っておこう、、、
スポンサーサイト

linux からお名前.com の DDNS 自動設定

11/末で、ddo.jp の無料ドメインが終了してしまいました、、、
あ、もちろん、広告を貼って10回/月のアクセスがあれば、無料で使えるらしいんですが、
ssh でしかアクセスしてないので、そういうわけにもいかず、、、

仕方ないので、お名前.com で真面目にドメイン買いました。

いろいろ格闘してたんですが、どうも、linux 上から DDNS を自動更新するのは大変そうです。

対応方法としては、ネットで3つ見つかったんですが、
・公式ツール => Windows しか対応していない。
・DiCE => linux 版が 32bit 版しかないし、最新の OpenSSL に対応してない。
・ddclient => MyDNS.jp のネームサーバーを経由して、設定しないといけない。

うーん、どれもいまいちです、、、
みんな困ってないの???

自前で作った方が楽かな。(誰か止めて、、、)

動作的には、ブラウザをエミュレートして、

現在の IPアドレス取得 => 変更があったかチェク =>
お名前.com にログイン => 現在の設定をエクスポート => 設定を書き換えて POST => 確認

するだけですよね、、、

起動は、cron あたりで、1日1回くらい動かせば、CPU負荷もないし。

昔からデーモンプロセス作るの嫌いなんですよね、、、
24時間、異常終了もメモリのフラグメント化もリークもなしで動かすのとか、
普通のプログラムを作るのの10倍疲れる、、、


来週末あたり作るかな、、、

linux版 chrome のタイトルバー文字化け

久しぶりに linux をアップデートしたら、chrome のタイトルバーが文字化けしたので、
解決方法の覚書です。


$ su -
# cd /etc/fonts/conf.d/
# mv 65-droid-sans-fonts.conf 65-droid-sans-fonts.conf.bak
# fc-cache -s -f -v /usr/share/fonts/truetype/droid/
/usr/share/fonts/truetype/droid: caching, new cache contents: 23 fonts, 0 dirs
/usr/share/fonts/truetype/droid: caching, new cache contents: 23 fonts, 0 dirs
/var/cache/fontconfig: cleaning cache directory
/.cache/fontconfig: not cleaning non-existent cache directory
fc-cache: succeeded
# mv 65-droid-sans-fonts.conf.bak 65-droid-sans-fonts.conf


で、直りました。

参照元: Ubuntu フォーラム

[Redmine] uninitialized constant Arel::Relation

久しぶりに redmine にログインしようとしたら

uninitialized constant Arel::Relation (NameError)

のエラーになっていたので、修正のメモです。

原因は、OS アップデート時に ruby が 2.1 になったのが原因らしい。


# diff /usr/lib/ruby/vendor_ruby/active_record/relation/predicate_builder.rb /var/lib/gems/2.1.0/gems/activerecord-3.2.17/lib/active_record/relation/predicate_builder.rb
47c47
< when Range, Arel::Relation
---
> when Range #, Arel::Relation


Arel::Relation が未初期化ということなので関連するところをコメントアウトしました。

redmine だけならいいけど、他から使うときやばいかな、、、


とりあえず、動くようになりました。

追記:

まだ wiki でエラーがでてる、、、
trunk の redmine は、ruby2.1 に対応してるみたいなんで、次のリリースまで待つかな。

追記2:

Arel を 3.0.x にダウングレードしたら直りました。

CA CERT Error

OS のアップデートしたら、SSL のエラーで https 通信ができなくなったので、復旧作業の覚書です。

現象:
エラーメッセージは、認証に失敗。
Peer certificate cannot be authenticated with given CA certificates


strace したら、SSL の公開キーのファイルがないらしい。
    :
stat("/etc/ssl/certs/c692a373.0", 0x7fffd6521d50) = -1 ENOENT
:


原因:
ca-certificates が提供するファイルが少なくなったらしい。

ca-certificates (20140223) unstable; urgency=medium

Debian will no longer ship cacert.org certificates.

Update mozilla/certdata.txt to version 1.97.


対策:
必要な公開キーを取ってきてリンク張りました。
公開キーを作成
# cat /usr/share/ca-certificates/mozilla/GTE_CyberTrust_Global_Root.crt
-----BEGIN CERTIFICATE-----
MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgw
FgYDVQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRy
dXN0IFNvbHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3Qg
R2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1
MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYD
VQQLEx5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMT
GkdURSBDeWJlclRydXN0IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUA
A4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9pTAipTHBsiQl8i4
ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6XALn
ZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8F
LztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh3
46B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq
81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0PlZPvy5TYnh+d
XIVtx6quTx8itc2VrbqnzPmrC3p/
-----END CERTIFICATE-----

リンクを張る
# cd /etc/ssl/cert
# ln -s /usr/share/ca-certificates/mozilla/GTE_CyberTrust_Global_Root.crt GTE_CyberTrust_Global_Root.pem

ショートカット作成
# c_rehash



とりあえず、通信できるようになりました、、、

SSDって

今週から、株の呼値が小さくなって、DBサイズの増え方が半端ないんですが、

SSD って、容量の 98%くらい使用した状態で読み書きしてると、すぐ(寿命で?)書き込みエラーになるんですよね、、、

残り2%っていっても、300GBx2%=6GB も余ってるのに、、、

もちろん、圧縮とかディスク掃除すると、使えるように復帰するんですが。

3年くらい前の安物の SSDだからかな、、、



DBアクセスを高速化しようと思ってSSD使ってたんですが、SSDに巨大データを放置しておくのは危険ですね、、、

リアルタイム処理に必要なものだけ置いて、容量スカスカの状態で使うようにしないと。



高速なRAIDディスクアレイがほしい、、、

DBサーバー設定覚書

JIRA 用に mysql を設定しました。

postgresql と mysql の両方を立ち上げるのが嫌だったんで、mysql を使用します。

バージョンは、
JIRA:1.6.5
mysql:5.5
です。

DB名: jiradb
ユーザー名: jirauser

1. データーベースを作成し、ユーザーに権限を与える。
# mysql -u root -p
mysql> CREATE DATABASE jiradb CHARACTER SET utf8 COLLATE utf8_bin;
mysql> GRANT ALL PRIVILEGES ON *.* TO jirauser@localhost IDENTIFIED BY 'パスワード';
mysql> flush privileges;
mysql> show grants for jirauser@localhost;


2. mysql 用 JDBC をインストールする。(debian.jar はいらないかも)
# apt-get install libmysql-java
# cp /usr/share/maven-repo/mysql/mysql-connector-java/5.1.28/mysql-connector-java-5.1.28.jar /opt/atlassian/jira/lib/
# cp /usr/share/maven-repo/mysql/mysql-connector-java/debian/mysql-connector-java-debian.jar /opt/atlassian/jira/lib/


JIRAから、接続できるのを確認しました。

メールサーバー設定覚書

サーバーが壊れたときに設定が吹っ飛んでいたんで、再設定しました。
その覚書です。

gmail 経由で、メールできるようにしてます。

1. exim4 を再設定する
# dpkg-reconfigure exim4-config
- メール設定の一般的なタイプ
->スマートホストでメール送信: SMTP または fetchmail で受信する
- システムメール名
->localhost
- 入力側 SMTP 接続をリスンする IP アドレス
->127.0.0.1 # IPv6 は消す
- メールを受け取るその他の宛先
-> 削除
- メールをリレーするマシン
-> 削除
- 送出スマートホストのIPアドレスまたはホスト名
->smtp.gmail.com::587
- 送出するメールでローカルメール名を隠しますか
->いいえ
- DNS クエリの数を最小限に留めますか (ダイヤルオンデマンド)
->いいえ
- ローカルメールの配送方式
->/var/mail内のmbox形式
- 設定を小さなファイルに分割しますか
->いいえ


2. SMTP認証の設定
# vi /etc/exim4/passwd.client
*.google.com:user@gmail.com:pass # support.google.com への認証
smtp.gmail.com:user@gmail.com:pass

# update-exim4.conf
# /etc/init.d/exim4 restart


3. テスト
$ mail -s test user@gmail.com
test
.
CC:


とりあえず、最低限の設定完了。

ITS どうしよう

バージョン管理が設定できたので、次はITS(問題追跡システム)です。

候補としては、
・Bugzilla (by perl) [無償]
・trac (by python) [無償]
・redmine (by ruby) [無償]
・JIRA (by java) [有償]
あたりなんですが、

仕事では、bugzilla + cvs と trac + svn を使ってました。
今更、bugzilla はないとして、trac は、もっさりしてて、よくエラーになるイメージなんですよね、、、

redmine は、不動産のトラブル管理に使おう、と設定してみたものの、
ソフト開発に特化しすぎてて断念したんですが、trac と似たりよったりなイメージです。

世間では、JIRAの評判がいいみたいなんで、ちょっと試してみようかな。
java 製なんで、ruby や python のバージョンがあがって、突然動かなくなる心配がないのもいいな。


値段も、10ユーザーまでなら、1,000円の激安。
いろいろオプションつけても5,000円くらい。今日買った本より安いな。


11人超えると60万円以上かかるけど、当分、10人以上で開発する気もないし、いい気がする。


こんな本質と関係ないところで、時間と労力をかけたくないしね。


あ、GHEもあるけど、ちょっと高いな。

git 設定覚書

git の設定覚書です。

1. git ユーザーを作成する
root@main# adduser -uid 1200 --gid 33 git    # group id 33 は、 www-data
root@main# sudo su - git
git@main$ vi ~/.bashrc # umask を 002 に設定(--shared したらいらないかも。)
root@main# vipw # git のシェルを git-shell に変更(ログインできなくなる)

2. 共有リポジトリを作成
git@main$ mkdir sandbox.git
git@main$ cd sandbox.git
git@main$ git init --bare --shared

3. git の各種設定(メイン/サブの各サーバーで実行)
# ユーザー情報を設定
user@main$ git config --global user.name "XXX"
user@main$ git config --global user.email "xxx@gmai.com"
# 端末色設定
user@main$ git config --global color.ui true
user@main$ git config --global color.branch true
user@main$ git config --global color.diff true
user@main$ git config --global color.interactive true
user@main$ git config --global color.status true
# CRLF 変換設定
user@main$ git config --global core.autocrlf input
# ツール設定
user@main$ git config --global core.pager "less -R"
user@main$ git config --global core.editor "vim -X"
user@main$ git config --global merge.tool tkdiff
# alias 設定
user@main$ git config --global alias.co checkout
user@main$ git config --global alias.ci "commit -a"
user@main$ git config --global alias.st status
user@main$ git config --global alias.br branch

4. 既存ソースを登録
user@main$ cp -a src backup               # 念の為バックアップ
user@main$ cd src
user@main$ git init
user@main$ git add *
user@main$ git commit
user@main$ git remote add origin ssh://git@main/home/git/sandbox.git
user@main$ git push origin master

5. 遠隔地にあるサブサーバーで確認
user@sub$ git clone ssh://git@main/home/git/sandbox.git
user@sub$ cd sandbox/src
user@sub$ make

一通り動きました。


って、正月から何してんだろう、、、

git 使ってみました。

ちょっと、来年から東証の呼値が変わるということで、
システムを大変更する前に、バージョン管理を導入しようと思って、VCS を調べてたんですが、
最近は、git が流行りならしいです。

これって、「Subversionは史上最も無意味なプロジェクト」ってこき下ろしてた Linus さんが作っちゃったバージョン管理システムなんですが、、、

Subversion で CVS を作り直すときに掲げてた、
・ディレクトリの移動をきちんと管理する。
・リポジトリをすっきりさせる
っていうのが、デグレードしてません??
Subversion を全否定っすか?Linus さん?

分散リポジトリっていう、開発者が好き勝手出来るシステムは魅惑的なんですけど、障害対応がちょっと不安です。


オープンソースのこういう誰かが作り直して、一部は良くなって一部は悪くなって螺旋状に成長していくのってほんとに嫌いです。

作り直すんじゃなくて、ちゃんとコミュニケーションとって、改良しようよ。
説得するより作り直す方が、楽だし技術も上がるし楽しいのはわかるけど、、、

libcurl 7.34 で SSL接続失敗

libcurl を 7.34 に上げたら、昔 Qt で発生した特定のサイトでhttps接続に失敗する不具合が再発しました、、、orz

CURL の変更履歴を眺めてたら、以下のような記述が、、、

- [Gergely Nagy brought this change]

SSL: protocol version can be specified more precisely

CURL_SSLVERSION_TLSv1_0, CURL_SSLVERSION_TLSv1_1,
CURL_SSLVERSION_TLSv1_2 enum values are added to force exact TLS version
(CURL_SSLVERSION_TLSv1 means TLS 1.x)

OpenSSL:
Added support for the new enum values.
Bugfix: The original CURL_SSLVERSION_TLSv1 value enabled only TLS 1.0,
now it enables 1.0-1.2.


今まで、CURL_SSLVERSION_TLSv1 で指定していたのを、 CURL_SSLVERSION_TLSv1_0 で指定しないといけなくなったらしい。

修正したら、無事解決。

Bugfix って、、、今まで動いてたのは Bug のおかげで動いてたのか、、、

連結リストの非再帰ソート

連結リストのソートを高速化したくて、いろいろ探してたんですが、
std::list のソートが再帰せずにマージソートしていたんで、
参考にして、非再帰版マージソートを作ってみました。


template ... T *
sort(T *l)
{
(中略)

for ( ; l != NULL; l = next )
{ // リストの先頭を取り出す
next = l->next;
l->next = NULL;

// 順にマージしていく
for( counter = &tmp[0]; *counter != NULL; counter++ )
{
l = merge(l, *counter);
*counter = NULL;
}
*counter = l;

if (counter == fill)
++fill;
}

(中略)

for ( ; counter != fill; ++counter)
{
if ( *counter != NULL )
l = merge(l, *counter);
}

return l;
}


おー、できた。やればできる!!

ということで、早速、ワクワクしながら速度を計ってみると、再帰版に負けました、、、orz


原因を考えてみると、この処理って、全然平衡じゃないやん、、、
最後のマージの部分で、最悪 1:N のマージが発生してる、、、orz

仕方がないので、独自に改良して、再帰版と非再帰版を混在させるようにいいとこ取り、、、
なんとか、気休め程度に速くなりました、、、orz

1000万個のソート
改良版
user 0m4.340s
再帰版
user 0m4.408s
非再帰版
user 0m4.612s

2の乗数の8M個のソート
改良版
user 0m3.464s
再帰版
user 0m3.584s
非再帰版
user 0m3.512s


まぁ、1000万個もソートする前に、基数でバケットして並列化しろって話なんですけどね。

ソースコードいります?いらないよね。

gcc/g++4.8 最適化失敗

昔から高速化のために、連結リストの作成を下記のように作ってたんですが、

List *list_new()
{
List *head;
List *tail = (List *)&head;
for ( ... )
tail = tail-next = new List;
tail->next = NULL;
return head;
}

gcc/g++ 4.8 で -O2 で最適化してコンパイルすると、動かない、、、

List *tail = (List *)&head;

の部分が、type-alias を破壊してるのが原因っぽいです、、、orz


仕方がないので、ポインタのポインタを使って、こんな感じに修正です。

List *list_new()
{
List *head;
List **tail = &head;
for ( ... )
{
*tail = new List;
tail = &(*tail)->next;
}
*tail = NULL;
return head;
}

小細工していない分、すっきりした気がします。
速度は、そんなに違わないっぽい。

libcurl ベンチマーク

DB 処理を Qt から CURLに移行中、、、どんだけかかってんねえん、、、

以下、速度
Qt バージョン
real 1m38.397s
user 1m13.608s
sys 0m23.500s

CURL バージョン
real 1m26.322s
user 0m4.400s
sys 0m0.060s


CPU 時間が18倍速くなった。おー。
実時間が遅いのは、相手のサーバーのレスポンスが遅いし仕方ない。
多重化してもいいけど、他所様のサーバーなのでこのへんで。

やっぱ、QString をこねくり回してると遅いな。

libcurl SSL 通信でエラー

libcurl の ssl 通信で、Connection: keep-alive で通信してるときに、Server から timeout などで、Connecction: close がきても認識してくれずに、session id を再利用しようとしてエラーになるみたい。

なので対策は、

keep-alive を使用しない

struct curl_slist *chunk = curl_slist_append(NULL, "Connection: close");
r = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
r = curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);


Reply の Connection: close を認識して、SESSIONID_CACHE を off にする

if ( strstr(header, "Connection: close") != NLLL )
r = curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);
else
r = curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 1L);

libxml2 お試し その2

htmlDocPtr doc = htmlReadFile(htmlfile, charset, option);

のオプション値一覧

HTML_PARSE_NOWARNING: 警告メッセージなし
HTML_PARSE_NOERROR: エラーメッセージなし
HTML_PARSE_PEDANTIC: エラーチェックが厳しくなるっぽい
XML_PARSE_NOBLANKS: スペース文字を保持しない
HTML_PARSE_RECOVER: エラー時にすぐに終了しない
HTML_PARSE_COMPACT: (使用箇所が見当たらない、、、)
XML_PARSE_HUGE:
HTML_PARSE_NODEFDTD: DTD がない
HTML_PARSE_IGNORE_ENC: エンコーディングを無視する
HTML_PARSE_NOIMPLIED: 暗黙タグがない場合に補完しない

tracker 削除

なんかサーバーが重いと思ったら、tracker-store とかいうGNOME の新しいデスクトップ検索がメモリを食いまくってた。

トラッカーという検索ツールが GNOME デスクトップの一部になりました。最初のログイン後にデスクトップの検索データを作り、これが標準の検索ツールから利用可能となっています。これはまた、新しい GNOME ドキュメントツールが最近使ったドキュメントを管理する肝となっています。


即削除。

ついでに NetworkManager も削除。


こないだ、X がいきなり落ちたのも、こいつのせいかな、、、、ウィルスみたい、、、

XPointer 指定方法

XPointer 仕様書(原文)
XPointer 仕様書(日本語)

XPath 指定方法

w3c XPath 仕様書(原文)
w3c XPath 仕様書(日本語訳)

para: 子 para 要素
*: すべての子要素
text() すべてのテキストノード
@name: name 属性
@: すべての属性
para[1]: 1番目の子 para
para[last()]: 最後の子 para
*/para: 孫 para
/doc/chapter[5]/section[2]: doc の5番目の chapter の2番目の section
chapter//para: 子 chapter 要素の子孫 para 要素
//para: 同じ文書にあるすべての para 要素
//olist/item: 同じ文書にあるすべての item 要素のうち、親 olist をもつもの
.: カレントノード
.//para: 子孫 para 要素
..: 親ノード
../@lang: 親の lang 属性
para[@type="warning"]: 子 para のうち type 属性に warning という値をとるもの
para[@type="warning"][5:] 子 para で、type 属性に warning という値をとるもの
para[5][@type="warning"] 番目の子 para が type 属性に warning という値をとるもの
chapter[title="Introduction"]: 子 chapter で、文字列値が Introduction に等しい子 title を1個以上もつもの。
chapter[title]: 子 chapter で、子 title を1個以上もつもの
employee[@secretary and @assistant]: 子 employee で、secretary 属性と assistant 属性との両方をもつもの

uim-mozc キーバインド変更

サーバーが死んだのを機にそろそろ atok を卒業しようかと。
ていうより、atok が 32bit なので、何かと競合して面倒くさいのでやめたい。
でも、atok 以外のキーバインドはつらい。

ということで標準でインストールされている uim-mozc のキーバインドを変更する。

/usr/share/uim/mozc.scm から読み込まれている
/usr/share/uim/generic-key-custom.scm
/usr/share/uim/mozc-key-custom.scm
を変更すればいいらしい。もしくは、~/.uim

中身はschemeかな。

変換on 全角半角と、Shift+space
変換off 全角半角と、Shift+space
=> は、間違って日本語入力に入ってしまうので消す。 ひとつだけでも list 指定しないといけないっぽい。

うーん、ドキュメントないしギブアップ、、、


調べてると、UimPref というので GUI から設定できるらしい、、、orz
$ uim-pref-gtk


あんまり設定できないな、、、

libxml2 お試し その1

Qt を CURL に変更するついでに、htmlcxx でHTML解析していたのを、libxml2 に変更できないか試してみた。

とりあえず、入力して出力するだけのプログラムを作ってみた。

int
main(
int argc,
char *argv[])
{
if ( argc != 2 )
return 1;

htmlDocPtr doc = htmlReadFile(argv[1], "UTF-8", 0);
htmlDocDump(stdout, doc);

return 0;
}


・問題点

- 大量のエラーメッセージ、、、
test.html:263: element a: validity error : ID PAGETOP already defined
test.html:1102: HTML parser error : htmlParseEntityRef: expecting ';'

人のHTMLなんで、変えられないし、しゃあない、、、

- char-set を認識してしまう、、、
iconv で変換してから渡すと、libsml2 が混乱してしまう。

カンマ区切り数値の文字列変換

1,234,567 みたいなカンマ区切りの数値を文字列と相互変換したい。

1. 数値 -> 文字列

いつのまにか printf が対応していた、、、

setlocale(LC_ALL, "");
snprintf(buf, sizeof(buf), "%'d", val);


2. 文字列 -> 数値

scanf の対応に期待したけど、対応してないっぽぃので、自作。

double
strtod_ex(
char *str)
{
double val = 0;
for (char *endptr = str;; endptr++)
{
val += strtod(endptr, &endptr);
if ( *endptr != ',' )
break;
val *= 1000;// 1000倍
}
return val;
}


エラー処理してないので注意!!

gcc4.8 CPU オプション

はじめて gcc 4.8 を使ったので、最近の対応 CPU タイプを調べてみた。

-march=TYPE / -mtune=TYPE で指定可能

-march は、命令セットを使うように指示
-mtune は、指定CPU用に最適化するように指示


CPU名内容
core2MMX, SSE, SSE2, SSE3, SSSE3 対応
corei7 MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1,SSE4.2 対応
corei7-avxMMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AES,PCLMUL 対応
corei7-iMMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AES, PCLMUL, FSGSBASE, RDRND,F16C 対応


/proc/cpuinfo で確認してみたところ、
メインサーバーは、Core i7 980X、AVX に対応してないので、corei7
予備サーバーは、Core i3 2120、AVXに対応しているので、corei7-avx

-march=corei7 -mtune=corei7 を指定することになりそう。

文字コードの変換

取得したHTMLの文字コードを解析を簡単にするために統一する。

文字コードの変換には、iconv と nkf がある。nkf は、入力文字列を自動判定してくれるので便利だけど、ライブラリ化されてないので、プログラムの呼出しをしないといけない。(ソースを組み込めばいいんだけど、ライセンスとかメンテナンスとか、いろいろ問題が、、、)

まずは、charset が正しいことを期待して、iconv を使用する。charset が存在せず、言語が日本語の場合は、popen()でnkf を呼び出す。

iconv に渡す引数は、コマンドラインから確認できる。
$ iconv -l


使用方法は、こんな感じ。
iconv_t cd = iconv_open("UTF-8", "WINDOWS-31J");
iconv(cd, in_buf, in_size, out_buf, out_size);
iconv_close(cd)




simplify 処理

文字コードを変換するのに加えて、simplify 処理をすることで、文字解析を行いやすくする。
この処理では次のことを行う。
- 全角文字を半角文字に変換する。
 (E38080) => (20)
!(EFBC81) => !(21)
”(E2809D) => "(22)
#(EFBC83) => #(23)
$(EFBC84) => $(24)
%(EFBC85) => %(25)
&(EFBC86) => &(26)
’(E28099) => '(27)
((EFBC88) => ((28)
)(EFBC89) => )(29)
*(EFBC8A) => *(2A)
+(EFBC8B) => +(2B)
,(EFBC8C) => ,(2C)
-(EFBC8D) => -(2D)
.(EFBC8E) => .(2E)
/(EFBC8F) => /(2F)
0(EFBC90) => 0(30)
1(EFBC91) => 1(31)
2(EFBC92) => 2(32)
3(EFBC93) => 3(33)
4(EFBC94) => 4(34)
5(EFBC95) => 5(35)
6(EFBC96) => 6(36)
7(EFBC97) => 7(37)
8(EFBC98) => 8(38)
9(EFBC99) => 9(39)
:(EFBC9A) => :(3A)
;(EFBC9B) => ;(3B)
<(EFBC9C) => <(3C)
=(EFBC9D) => =(3D)
>(EFBC9E) => >(3E)
?(EFBC9F) => ?(3F)
@(EFBCA0) => @(40)
A(EFBCA1) => A(41)
B(EFBCA2) => B(42)
C(EFBCA3) => C(43)
D(EFBCA4) => D(44)
E(EFBCA5) => E(45)
F(EFBCA6) => F(46)
G(EFBCA7) => G(47)
H(EFBCA8) => H(48)
I(EFBCA9) => I(49)
J(EFBCAA) => J(4A)
K(EFBCAB) => K(4B)
L(EFBCAC) => L(4C)
M(EFBCAD) => M(4D)
N(EFBCAE) => N(4E)
O(EFBCAF) => O(4F)
P(EFBCB0) => P(50)
Q(EFBCB1) => Q(51)
R(EFBCB2) => R(52)
S(EFBCB3) => S(53)
T(EFBCB4) => T(54)
U(EFBCB5) => U(55)
V(EFBCB6) => V(56)
W(EFBCB7) => W(57)
X(EFBCB8) => X(58)
Y(EFBCB9) => Y(59)
Z(EFBCBA) => Z(5A)
[(EFBCBB) => [(5B)
¥(EFBFA5) => \(5C)
](EFBCBD) => ](5D)
^(EFBCBE) => ^(5E)
_(EFBCBF) => _(5F)
‘(E28098) => `(60)
a(EFBD81) => a(61)
b(EFBD82) => b(62)
c(EFBD83) => c(63)
d(EFBD84) => d(64)
e(EFBD85) => e(65)
f(EFBD86) => f(66)
g(EFBD87) => g(67)
h(EFBD88) => h(68)
i(EFBD89) => i(69)
j(EFBD8A) => j(6A)
k(EFBD8B) => k(6B)
l(EFBD8C) => l(6C)
m(EFBD8D) => m(6D)
n(EFBD8E) => n(6E)
o(EFBD8F) => o(6F)
p(EFBD90) => p(70)
q(EFBD91) => q(71)
r(EFBD92) => r(72)
s(EFBD93) => s(73)
t(EFBD94) => t(74)
u(EFBD95) => u(75)
v(EFBD96) => v(76)
w(EFBD97) => w(77)
x(EFBD98) => x(78)
y(EFBD99) => y(79)
z(EFBD9A) => z(7A)
{(EFBD9B) => {(7B)
|(EFBD9C) => |(7C)
}(EFBD9D) => }(7D)
~(EFBD9E) => ~(7E)

- 半角カタカナは全角カタカナに変換する。
ァ(EFBDA7) => ァ(E382A1)
ア(EFBDB1) => ア(E382A2)
ィ(EFBDA8) => ィ(E382A3)
イ(EFBDB2) => イ(E382A4)
ゥ(EFBDA9) => ゥ(E382A5)
ウ(EFBDB3) => ウ(E382A6)
ェ(EFBDAA) => ェ(E382A7)
エ(EFBDB4) => エ(E382A8)
ォ(EFBDAB) => ォ(E382A9)
オ(EFBDB5) => オ(E382AA)
カ(EFBDB6) => カ(E382AB)
キ(EFBDB7) => キ(E382AD)
ク(EFBDB8) => ク(E382AF)
ケ(EFBDB9) => ケ(E382B1)
コ(EFBDBA) => コ(E382B3)
ガ(EFBDB6EFBE9E) => ガ(E382AC)
ギ(EFBDB7EFBE9E) => ギ(E382AE)
グ(EFBDB8EFBE9E) => グ(E382B0)
ゲ(EFBDB9EFBE9E) => ゲ(E382B2)
ゴ(EFBDBAEFBE9E) => ゴ(E382B4)
サ(EFBDBB) => サ(E382B5)
シ(EFBDBC) => シ(E382B7)
ス(EFBDBD) => ス(E382B9)
セ(EFBDBE) => セ(E382BB)
ソ(EFBDBF) => ソ(E382BD)
ザ(EFBDBBEFBE9E) => ザ(E382B6)
ジ(EFBDBCEFBE9E) => ジ(E382B8)
ズ(EFBDBDEFBE9E) => ズ(E382BA)
ゼ(EFBDBEEFBE9E) => ゼ(E382BC)
ゾ(EFBDBFEFBE9E) => ゾ(E382BE)
タ(EFBE80) => タ(E382BF)
チ(EFBE81) => チ(E38381)
ツ(EFBE82) => ツ(E38384)
テ(EFBE83) => テ(E38386)
ト(EFBE84) => ト(E38388)
ダ(EFBE80EFBE9E) => ダ(E38380)
ヂ(EFBE81EFBE9E) => ヂ(E38382)
ヅ(EFBE82EFBE9E) => ヅ(E38385)
デ(EFBE83EFBE9E) => デ(E38387)
ド(EFBE84EFBE9E) => ド(E38389)
ナ(EFBE85) => ナ(E3838A)
ニ(EFBE86) => ニ(E3838B)
ヌ(EFBE87) => ヌ(E3838C)
ネ(EFBE88) => ネ(E3838D)
ノ(EFBE89) => ノ(E3838E)
ハ(EFBE8A) => ハ(E3838F)
ヒ(EFBE8B) => ヒ(E38392)
フ(EFBE8C) => フ(E38395)
ヘ(EFBE8D) => ヘ(E38398)
ホ(EFBE8E) => ホ(E3839B)
バ(EFBE8AEFBE9E) => バ(E38390)
ビ(EFBE8BEFBE9E) => ビ(E38393)
ブ(EFBE8CEFBE9E) => ブ(E38396)
ベ(EFBE8DEFBE9E) => ベ(E38399)
ボ(EFBE8EEFBE9E) => ボ(E3839C)
パ(EFBE8AEFBE9F) => パ(E38391)
ピ(EFBE8BEFBE9F) => ピ(E38394)
プ(EFBE8CEFBE9F) => プ(E38397)
ペ(EFBE8DEFBE9F) => ペ(E3839A)
ポ(EFBE8EEFBE9F) => ポ(E3839D)
マ(EFBE8F) => マ(E3839E)
ミ(EFBE90) => ミ(E3839F)
ム(EFBE91) => ム(E383A0)
メ(EFBE92) => メ(E383A1)
モ(EFBE93) => モ(E383A2)
ャ(EFBDAC) => ャ(E383A3)
ヤ(EFBE94) => ヤ(E383A4)
ュ(EFBDAD) => ュ(E383A5)
ユ(EFBE95) => ユ(E383A6)
ョ(EFBDAE) => ョ(E383A7)
ヨ(EFBE96) => ヨ(E383A8)
ラ(EFBE97) => ラ(E383A9)
リ(EFBE98) => リ(E383AA)
ル(EFBE99) => ル(E383AB)
レ(EFBE9A) => レ(E383AC)
ロ(EFBE9B) => ロ(E383AD)
ワ(EFBE9C) => ワ(E383AF)
ヲ(EFBDA6) => ヲ(E383B2)
ン(EFBE9D) => ン(E383B3)

- 連続するスペース文字は半角スペース1つに置き換える。
- 先頭と末尾のスペース文字は削除
- >< の間の先頭末尾のスペース文字も削除

libcurl の使い方 その2

Cookie の取り扱い

5つほど関係ありそうなオプションがある。
char *cookie = "sessionid=xxxx";
curl_easy_setopt(curl, CURLOPT_COOKIE, cookie);
COOKIEを key/value 文字列で設定する。1つしか設定できない?
"sessionid=xxx; user=admin" のようにすると複数設定できるけど、仕様外かも。

char *filename;
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, filename);
Cookie が保存されたファイルを指定する。
複数指定可。
ファイルの形式は、Set-Cookie: ラインが並んだもの。(Mozilla/Netscape形式)

char *jar;
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, jar);
Cookie が保存するファイルを指定する。
curl_easy_cleanup()時に保持している Cookie が出力される。

int session_restart;
curl_easy_setopt(curl, CURLOPT_COOKIESESSION, session_restart);
1を指定すると新しいCookie セッションを作成する。

char *set-cookie;
curl_easy_setopt(curl, CURLOPT_COOKIELIST, set-cookie);
Set-Cookie スタイルの文字列で、Cookie を登録する。


同じCURL を使用している限り、Cookie は自動的に登録されて、次回通信時に使用される。
複数のCURLで共有する場合は、CURLSH を使用する。
処理の流れは
//初期化
CURL curl = *curl_easy_init();
// 入力先を指定する
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/home/user/.xxx/cookiejar);
// 出力先を指定する
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "/home/user/.xxx/cookiejar);
for ( ... )
{
URL等設定
:
// 通信
curl_easy_perform(curl);
// HTML内の meta タグの Set-Cookie を登録する。
curl_easy_setopt(curl, CURLOPT_COOKIELINE, set-cookie);
}
// 後処理
curl_easy_cleanup(curl);

Cookie の確認方法
        struct curl_slist *cookies;
curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
struct curl_slist *c = cookies;
if ( c == NULL )
{
printf("(none)\n");
return;
}
for ( int i = 1;c != NULL; c = c->next, i++ )
printf("[%d]: %s\n", i, c->data);
curl_slist_free_all(cookies);

libcurl の使い方 その1

HTTP 通信を独自実装しようかと思ってたけど、cURL を使うと簡単そう。

このライブラリには、3種類の API がある。
- easy: 同期通信API
- multi: 複数通信API
- share: 共有通信API

ソースを取得して眺めてたけど、中規模程度のC言語ライブラリ。
Qt みたいな C++ と違って、ユーザー空間から独自拡張しやすいし、使いやすそう。

easy API の流れ
// 初期化
curl_global_init(CURL_GLOBAL_DEFAULT); // https を使用するなら必要
CURL *curl = curl_easy_init();
// 各種設定
curl_easy_setopt(curl, ...);
curl_easy_setopt(curl, ...);
curl_easy_setopt(curl, ...);
:
// 実行
curl_easy_perform(curl);
// 後処理
curl_easy_cleanup(curl);
curl_global_cleanup();

multi API の流れ
// 初期化
curl_global_init(CURL_GLOBAL_DEFAULT);
CURLM *cm = curl_multi_init}();
// 同時接続数設定
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, 10);
// 接続設定
for ( int i = 0; i < 10; i++ )
{
CURL *curl = curl_easy_init();
// 各種設定
curl_easy_setopt(curl, ...);
:
curl_multi_Add_handle(cm, curl);
}
// 実行
curl_multi_perform(curl);
// 後処理
curl_multi_cleanup(cm);
curl_global_cleanup();

share API の流れ
DNS/COOKIE/SSL が通信間で共有できるらしい。
// 初期化
curl_global_init(CURL_GLOBAL_DEFAULT);
CURLSH *csh = curl_share_init();
// DNS を共有
curl_share_setopt(csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
// COOKIE を共有
curl_share_setopt(csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
// SSL を共有
curl_share_setopt(csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
:
// 通信
CURL *curl = curl_easy_init();
:
// 共有
curl_easy_setopt(curl, CURLOPT_SHARE, csh);
:
//実行
curl_easy_perform();
curl_easy_cleanup(curl);
// 後処理
curl_share_cleanup(csh);
curl_global_cleanup();

1秒毎のリアルタイム処理

今までQt 任せだったタイマー処理を自前でやらないといけないので、1秒毎にWebサーバーから情報を取得する方法を考えてみた。

最初は、setitimer() を使って、シグナル処理しようかと思っていたが、このインターバルタイマーって、設定してからの時間になるから、9:00:00.00、9:00:01.00 と、毎1秒00 のときに処理をしたい場合、setitimer() を設定した時刻によって、誤差がでてしまう。これを10時間とか実行すると、誤差が拡大して、あんまりよろしくない。

なので、素直にloop/sleep を使用することを検討してみた。

test.c
int
main(
int argc,
char *argv[])
{
time_t prev = 0;
struct timeval now;
for ( ;; )
{
gettimeofday(&now, NULL);
if ( now.tv_sec == prev )
{
usleep(1000);
continue;
}

printf("time %d.%02d\n", (int)now.tv_sec, now.tv_usec/1000);
prev = now.tv_sec;
}
return 0;
}

実行結果
$ ./a.out 
time 1369500259.585
time 1369500260.00
time 1369500261.00
time 1369500262.00
time 1369500263.00
time 1369500264.00
time 1369500265.00
time 1369500266.00
time 1369500267.00
time 1369500268.00
time 1369500269.00
time 1369500270.00

top で計測していると、0.001sec 毎で、CPU1%、0.0001sec 毎で、CPU4.3%くらい消費する。
十分ですな。

空ファイルの作り方

ある大きさの空ファイルを作成してmmap時に SEGV がおきないようにファイルサイズの予約をしたいけど、一々書き込んでると時間がかかるなぁ、と思ってたら、昔の記憶を思い出した。

その予約サイズまで lseek して書き込めば、ディスクを使用しないけどファイルサイズだけを持つファイルを作成できるんだった。

test.c
#include 
#include
#include
#include
#include
#include
int
main(
int argc,
char *argv[])
{
if ( argc != 2 )
return 1;

int fd = open(argv[1], O_WRONLY|O_CREAT, 0666);
if ( fd < 0 )
return 1;

off_t off = lseek(fd, 4LL*1024*1024*1024, SEEK_SET);
if ( off < 0 )
return 1;

char buf[1] = {'\0'};
ssize_t wsize = write(fd, buf, sizeof(buf));
if ( wsize < 0 )
return 1;

close(fd);
return 0;
}


$ gcc test.c
$ df -h
ファイルシス サイズ 使用 残り 使用% マウント位置
rootfs 514G 385G 124G 76% /
$ ./a.out A
$ ls -lh A
-rw-rw-r-- 1 user user 4.1G 5月 25 23:13 A
$ df -h
ファイルシス サイズ 使用 残り 使用% マウント位置
rootfs 514G 385G 124G 76% /


ディスクも使用してないけど、できれば、ディスクサイズも予約してほしかった。
ディスクが溢れたときは、どうなるんだろ、、、

この挙動なんて言ったっけ、ホールだったかな。

Cookie のおさらい

RFC6525 日本語訳

Cookie は、Set-Cookie/Cookie の二つのヘッダによって制御される。

サーバー → クライアント Set-Cookieヘッダ
クライアント → サーバー Cookieヘッダ

Set-Cookie の構文は、
Set-Cookie: [名前=値]+[; Expires=期限][; Max-Age=期限][; Path=パス] [; Domain=ドメイン] [; [HttpOnly|Secure]]

Set-Cookie は、レスポンスヘッダ内に複数存在する可能性がある。
一つのSet-Cookie に複数の名前/値が存在する可能性がある。
属性の文字列を判定するときは大文字小文字を区別しない。

Expires: クッキーの有効期限
Max-Age: クッキーの期限切れまでの秒数(Expiresより優先)
Domain/Path: 対応するURI
HttpOnly/Secure: http/https のどちらかだけに適用

Cookie の構文は、
Cookie: 名前=値 [名前=値] ...

Cookie ヘッダを複数送信してはいけない。
サーバーは、受信した値の順序に依存してはいけない。
同じ名前の値を複数送信した場合の挙動は未定義。

Set-Cookie より単純。
Webアクセスするときに、対応する Cookie を探してきて付加するだけ。

日付の構文(重要じゃないけど、微妙に面倒臭い)
ex. 15-Nov-2013 23:12:40 GMT

cookie-date     = *delimiter date-token-list *delimiter
date-token-list = date-token *( 1*delimiter date-token )
date-token = 1*non-delimiter

delimiter = %x09 / %x20-2F / %x3B-40 / %x5B-60 / %x7B-7E
non-delimiter = %x00-08 / %x0A-1F / DIGIT / ":" / ALPHA / %x7F-FF
non-digit = %x00-2F / %x3A-FF

day-of-month = 1*2DIGIT ( non-digit *OCTET )
month = ( "jan" / "feb" / "mar" / "apr" /
"may" / "jun" / "jul" / "aug" /
"sep" / "oct" / "nov" / "dec" ) *OCTET
year = 2*4DIGIT ( non-digit *OCTET )
time = hms-time ( non-digit *OCTET )
hms-time = time-field ":" time-field ":" time-field
time-field = 1*2DIGIT

RFC 通りに Cライクな擬似コーディングすると、以下の感じ。
for ( date-token がある間 )
{
if ( !found-time && (date-token が time形式にマッチ) )
{
found-time = true;
hour-value, minute-value, second-value を解析
continue;
}
if ( !found-day-of-month && (date-token が day-of-month形式にマッチ) )
{
found-day-of-month = true;
day-of-month-value を解析
continue;
}
if ( !found-month && (date-token が month 形式にマッチ) )
{
found-month = true;
moht-value を解析
continue;
}
if ( !found-year && (date-token が year 形式にマッチ) )
{
found-year = true;
year-value を解析
continue;
}
}
if ( year-value >= 70 && year-value <= 99 )
year-value += 1900;
if ( year-value >= 0 && year-value <= 69 )
year-value += 2000;
if ( !found-day-of-month || !found-month || !found-year || !found-time )
goto ERROR;
if ( parsed-cookie-date が UTC に存在しない )
goto ERROR;
return parsed cookie-date;


Domain は、ホスト名のみで IPアドレスは不可。

Path の合致の条件は、
- path が同一である。
- path と前方一致で最後が /
- path と前方一致で一致しない部分の最初の文字が/

つまり、Path で示される下のディレクトリすべてに Set-Cookie は適用される。



とりあえずは、Cookie をディスク内に保存するつもりはないんで、日付は関係ないな、、、

 | HOME |  »

Calendar

« | 2017-10 | »
S M T W T F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -

Monthly

Categories

Recent Entries

Recent Comments

Recent Trackbacks

Appendix

ナマポ不動産

ナマポ不動産

株歴5年
大家歴4年
です。

株の手法は、酒田五法を自己流でアレンジした勘トレです、、、orz

2013 確定損益(含み損益込前月比)
 5月   +940,578
 6月 +1,103,401 (+648,940)
 7月   +496,406 (+337,406)
 8月   +227,368 (+467,586)
 9月   +385,146 (+809,644)
10月 +2,880,993 (+611,895)
11月   +323,062 (+494,426)
12月   +439,567 (+235,485)
申告 +512万円(うち配当 +33万円)

2014 確定損益(含み損益込前月比)
 1月    +508,788 (+427,432)
 2月    +560,810 (+778,034)
 3月    +507,715 (-253,540)
 4月     +68,688 (-1,069,645)
 5月    +347,468 (+1,255,721)
 6月  +1,068,696 (+901,076)
 7月    +305,470 (+380,862)
 8月     +69,794 (-641,412)
 9月  -1,215,544 (+390,466)
10月    +304,769 (+591,055)
11月    +231,939 (+196,234)
12月  +1,422,970 (+887,793)
申告 +451万円(うち配当 +26万円)

2015 確定損益(含み損益込前月比)
 1月    +266,262 (+832,570)
 2月  +1,097,569 (+907,316)
 3月    +530,465 (+467,067)

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。