2010-03-12 6 views
5

Je développe une application dans Visual C++ qui utilise une base de données SQLite3 pour stocker des données. Habituellement, il se trouve dans le bac la plupart du temps.Verrouillage de fichiers SQLite et DropBox

Je voudrais également activer l'application de mon application dans un dossier DropBox pour la partager sur plusieurs ordinateurs. Cela a très bien fonctionné jusqu'à ce que DropBox se soit récemment mis à jour. Et maintenant, il dit qu'il "ne peut pas synchroniser le fichier en cours d'utilisation". Le fichier SQLite est ouvert dans mon application, mais le verrou est partagé. Il existe des instructions préparées, mais toutes sont réinitialisées immédiatement après l'utilisation de step.

Est-il possible d'activer la synchronisation d'un fichier de base de données SQLite ouvert? Merci!

Voici l'emballage simple que je viens d'utiliser pour les tests (pas de gestion des erreurs), dans le cas où cette aide:

class Statement 
{ 
private: 
    Statement(sqlite3* db, const std::wstring& sql) : db(db) 
    { 
    sqlite3_prepare16_v2(db, sql.c_str(), sql.length() * sizeof(wchar_t), &stmt, NULL); 
    } 

public: 
    ~Statement() { sqlite3_finalize(stmt); } 

public: 
    void reset() { sqlite3_reset(stmt); } 
    int step() { return sqlite3_step(stmt); } 
    int getInt(int i) const { return sqlite3_column_int(stmt, i); } 

    std::wstring getText(int i) const 
    { 
    const wchar_t* v = (const wchar_t*)sqlite3_column_text16(stmt, i); 
    int sz = sqlite3_column_bytes16(stmt, i)/sizeof(wchar_t); 
    return std::wstring(v, v + sz); 
    } 

private: 
    friend class Database; 

    sqlite3* db; 
    sqlite3_stmt* stmt; 
}; 


class Database 
{ 
public: 
    Database(const std::wstring& filename = L"")) : db(NULL) 
    { 
    sqlite3_open16(filename.c_str(), &db); 
    } 

    ~Database() { sqlite3_close(db); } 

    void exec(const std::wstring& sql) 
    { 
    auto_ptr<Statement> st(prepare(sql)); 
    st->step(); 
    } 

    auto_ptr<Statement> prepare(const std::wstring& sql) const 
    { 
    return auto_ptr<Statement>(new Statement(db, sql)); 
    } 

private: 
    sqlite3* db; 
}; 

UPD: a essayé de commenter tous les appels à LockFile et LockFileEx à sqlite3.c - même résultat.

UPD2: Essayé d'appeler sqlite3_close au repos (comme preuve de concept) - toujours le même résultat! Filemon dit que le fichier n'est toujours pas fermé, seulement déverrouillé.

UPD3: Le mode Autocommit est activé. Les nombres de BEGINs et COMMITs correspondent (la classe Transaction et RAII s'en occupent). SQliteManager est capable de se connecter à la base de données pendant que mon application est en cours d'exécution et y apporter des modifications.

+1

Vérifiez-vous le résultat de sqlite3_close()? Peut-être que cela ne fonctionne pas parce que vous n'avez pas finalisé toutes vos déclarations préparées. –

+0

C'était ça! Cela ne fonctionnait pas à cause d'une sauvegarde en arrière-plan en cours d'exécution. Erreur muette .. Merci! Mettez-le comme une réponse et je vais l'accepter. –

Répondre

4

Vérification du résultat à partir de sqlite3_close(). Peut-être que cela ne fonctionne pas parce que vous n'avez pas finalisé toutes vos déclarations préparées.

2

Quel système de fichiers utilisez-vous? Etes-vous sûr que la validation automatique est activée et/ou que vous validez vos relevés? Je me souviens d'avoir eu un problème de ne pas m'engager et la serrure resterait allumée.

+0

NTFS. Bonne idée de commettre, merci, je vais vérifier si cela pourrait être le cas. –

+0

Le mode Autocommit est activé. Les nombres de BEGINs et COMMITs correspondent (la classe Transaction et RAII s'en occupent). On dirait que ce n'est pas la raison. SQliteManager est capable de se connecter à la base de données pendant que mon application est en cours d'exécution et y apporter des modifications. –

2

Alex Pechnikov dispose d'un programme de réplication de base de données SQLite multi-maître sqlite3-rdiff. Il est probablement exagéré pour ce que vous essayez d'accomplir, mais il peut être plus facile que la réplication de fichiers. SQLite a également un Online Backup API; Voici un exemple sur cette page: Exemple 2: Sauvegarde en ligne d'une base de données en cours d'exécution.

+0

Je n'arrive pas à trouver un moyen de l'utiliser automatiquement. sqlite3-rdiff requiert Tcl, et utiliser l'API de sauvegarde signifie faire une copie de la base de données entière après chaque modification. –

+0

DropBox ne crée-t-il pas une copie (ou un rdiff) de la BD après chaque modification? Si c'est le cas, une copie locale n'est pas très lourde. Si ce n'est pas le cas, faites seulement la copie locale aussi rapidement que DropBox en a besoin. –