2018/03/05

[c/c++][lmdb]同じ名前のDBが複数出来てしまう謎 (1)

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 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。