protobufの調査をしたかったのだが、緊急事態発生だ。
mdb_dbi_open()でデータベース名を指定する場合、MDB_CREATEを付けていれば、なければ新規作成してくれるし、あれば既存のものをオープンする。
単純な話だ。
しかーし!
昨日、不思議な現象が起きるようになり、DBを作り直しても必ず再現するのだが、未だに解決方法が分かっていない。
mdb_put()を何回も行い、mdb_dumpコマンドで確認して、データが1種類しか無いことは確認できた。
しかし、それをmdb_drop()しようとしたら、MDB_NOTFOUNDが発生してしまった。
よくよく見ると、mdb_drop()ではなく、その前のmdb_dbi_open()で発生しているのだ。
でも、チェックするとデータは存在しているのである。
よくわからないので、dropするときのmdb_dbi_open()で、MDB_CREATEを指定して、dropしないようにしてみた。
その結果をmdb_dumpコマンドで確認すると、同じデータベース名が複数出てきたのだ。
違いがあるのは、mdb_dbi_open()するまでの過程だ。
うまくいっているときは、mdb_txn_begin()でトランザクションを取って、mdb_dbi_open()でデータベースをオープンして、mdb_put()なりmdb_get()なりしている。
現象が起きるときは、トランザクションを取るところは同じなのだが、mdb_dbi_open()で名前を指定していない。
そして、取得したdbiでmdb_cursor_open()し、これをぐるぐる回して、全部のデータベース名を見に行っているのだ。
期待するデータベース名が見つかったら、その名前でmdb_dbi_open()したり、そこからアクセスして得た名称でmdb_dbi_open()して、あーだこーだしたあと、dropさせている。
「あーだこーだ」と省略したが、いろいろやっているのだ。
だから、正統派としては、現象に影響しないところをじわじわ切り取っていって、キツネ狩りのように追い込んでいくのがよいのだろう。
が、気力が無いときは、えいや、で片付けてしまいたいではないか。
昨日から今日に掛けてがそういう気分で、そして、未だに解決していない。。。
ちなみに、名前を指定せずにmdb_dbi_open()するのは、mdb_dumpコマンドを参考にしている。
https://github.com/LMDB/lmdb/blob/mdb.master/libraries/liblmdb/mdb_dump.c#L253
memchr()で\0を探し、見つかったらやり直している。
たぶん、DB名をstrlen()で保存しているから、DB名だったら\0がその中に無いように作っているのだろう。
envの中に複数のdbiがあり、dbiの中にkeyがある。
だから、まずはdbiをcursorで回して、次に各dbiの中でkeyをcursorで回す、というところか。
全部を検索したいのであれば、そういう方法しか無いのだろうと思う。
じゃあ、これのどこがまずいのだ?
まずいのであれば、MDB_NOTFOUND、ではないはずだ。
そして、同じDB名でデータ生成できないはずである。
それができているということは、なにか想定外というか、lmdbが禁じていることを行っていると考えた方がよいか。
それがわかれば苦労はしないのだが、想像がつかない。
スレッドとかプロセスとかがありがちなのだけど、「あーだこーだ」の最初の方ではopenに成功しているのよねぇ。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。