2013-06-10 3 views
1

J'utilise LevelDB dans mon application avec 5 bases de données. Chaque base de données est ouverte avec l'option max_open_files = 64.LevelDB: Erreur d'E/S: XXX.sst: Trop de fichiers ouverts

ulimit -Sn indique que le système d'exploitation a une limite de 1024 fichiers. Définir la limite à 2048 résout le problème. Parce que je distribue cette application à des personnes, il devrait avoir des paramètres par défaut qui fonctionnent hors de la boîte sans obliger les gens à configurer leur système d'exploitation.

leveldb::Status status = db_spends_->Get(
    leveldb::ReadOptions(), spent_slice, &raw_spend); 
if (!status.ok()) 
{ 
    std::cerr << "fetch_spend: " << status.ToString() << std::endl; 
    return false; 
} 

Je reçois beaucoup de ces erreurs et ne peux pas lire du tout.

"fetch_spend: IO error: XXXX.sst: Too many open files" 

Il y a 5 bases de données dans un sous-répertoire appelé database:

$ ls 
addr block block_hash spend tx 
$ du -sh . 
16G . 
$ du -sh * 
2.6G addr 
653M block 
7.2M block_hash 
2.6G spend 
9.4G tx 
$ for i in `ls`; do echo $i; ls $i | wc -l; done 
addr 
1279 
block 
333 
block_hash 
10 
spend 
1433 
tx 
5252 

Je voudrais changer la limite de 2 Mo à l'intérieur LevelDB pour chaque fichier .sst, mais il ne semble pas réglable et je seulement vu ce patch sur Google: https://github.com/basho/leveldb/pull/7

J'utilise Ubuntu 13.04 64bit.

Voici le code que j'utilise pour ouvrir les bases de données. Si j'affiche le open_options.max_open_files avant l'appel au leveldb::DB::Open(), il affiche 64 (comme prévu).

bool open_db(const std::string& prefix, const std::string& db_name, 
    std::unique_ptr<leveldb::DB>& db, leveldb::Options open_options) 
{ 
    using boost::filesystem::path; 
    path db_path = path(prefix)/db_name; 
    leveldb::DB* db_base_ptr = nullptr; 
    leveldb::Status status = 
     leveldb::DB::Open(open_options, db_path.native(), &db_base_ptr); 
    if (!status.ok()) 
    { 
     log_fatal(LOG_BLOCKCHAIN) << "Internal error opening '" 
      << db_name << "' database: " << status.ToString(); 
     return false; 
    } 
    // The cointainer ensures db_base_ptr is now managed. 
    db.reset(db_base_ptr); 
    return true; 
} 

... 

// Create comparator for blocks database. 
depth_comparator_.reset(new depth_comparator); 
// Open LevelDB databases 
const size_t cache_size = 1 << 20; 
// block_cache, filter_policy and comparator must be deleted after use! 
open_options_.block_cache = leveldb::NewLRUCache(cache_size/2); 
open_options_.write_buffer_size = cache_size/4; 
open_options_.filter_policy = leveldb::NewBloomFilterPolicy(10); 
open_options_.compression = leveldb::kNoCompression; 
open_options_.max_open_files = 64; 
open_options_.create_if_missing = true; 
// The blocks database options needs its depth comparator too. 
leveldb::Options blocks_open_options = open_options_; 
blocks_open_options.comparator = depth_comparator_.get(); 
if (!open_db(prefix, "block", db_blocks_, blocks_open_options)) 
    return false; 
if (!open_db(prefix, "block_hash", db_blocks_hash_, open_options_)) 
    return false; 
if (!open_db(prefix, "tx", db_txs_, open_options_)) 
    return false; 
if (!open_db(prefix, "spend", db_spends_, open_options_)) 
    return false; 
if (!open_db(prefix, "addr", db_address_, open_options_)) 
    return false; 

Même si je mets max_open_files = 20 je reçois toujours le même problème.

Répondre

2

Jusqu'à récemment, il pouvait y avoir un comportement pathologique lorsque max_option_files était défini sur < 74, où des centaines de descripteurs de fichiers étaient utilisés à la place de ce que l'option disait. (La dernière version des pinces leveldb donne à la limite un plancher de 74.) Le réglage à ~ 80 a-t-il un effet? Si non, et vous avez toujours le problème, pourriez-vous lancer l'incantation appropriée de lsof quand vous voyez le mauvais comportement? Cela nous dira où vont les descripteurs de fichiers.

+0

Le fait de régler un nombre plus élevé a amélioré le fonctionnement. – genjix