2010-03-12 11 views
5

Sto sviluppando un'applicazione in Visual C++ che utilizza un database SQLite3 per l'archiviazione dei dati. Solitamente si trova nel cassetto per la maggior parte del tempo.Blocco file SQLite e DropBox

Vorrei anche abilitare l'inserimento della mia app in una cartella DropBox per condividerla su più PC. Ha funzionato molto bene fino a quando DropBox si è aggiornato di recente. E ora dice che "non può sincronizzare il file in uso". Il file SQLite è aperto nella mia app, ma il blocco è condiviso. Esistono alcune istruzioni preparate, ma tutte vengono ripristinate immediatamente dopo l'utilizzo di step.

C'è un modo per abilitare la sincronizzazione di un file di database SQLite aperto? Grazie!

Ecco il semplice involucro che uso solo per i test (senza gestione degli errori), nel caso in cui questo aiuta:

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: Provato commentando tutte le chiamate a LockFile e LockFileEx in sqlite3.c - stesso risultato.

UPD2: Tentativo di chiamare sqlite3_close inattivo (come prova del concetto) - sempre lo stesso risultato! Filemon dice che il file non è ancora chiuso, solo sbloccato.

UPD3: La modalità di autocommit è attiva. I numeri di BEGIN e COMMIT corrispondono (classe Transaction e RAII si occupano di ciò). SQliteManager è in grado di connettersi al DB mentre la mia app è in esecuzione e apportare modifiche ad esso.

+1

Stai verificando il risultato da sqlite3_close()? Forse non funziona perché non hai finalizzato tutte le tue dichiarazioni preparate. –

+0

Era questo! Non funzionava a causa di un backup in background in esecuzione. Errore stupido .. Grazie! Mettilo come risposta e lo accetterò. –

risposta

4

Controllo del risultato da sqlite3_close(). Forse non funziona perché non hai finalizzato tutte le tue dichiarazioni preparate.

2

Quale file system stai utilizzando?

Sei sicuro che l'autocommit è attivo e/o che stai scrivendo le tue dichiarazioni? Ricordo di avere un problema con il non aver commesso e il blocco sarebbe rimasto acceso.

+0

NTFS. Buona idea di commettere, grazie, controllerò se questo potrebbe essere il caso. –

+0

La modalità di autocommit è attiva. I numeri di BEGIN e COMMIT corrispondono (classe Transaction e RAII si occupano di ciò). Sembra che questa non sia la ragione. SQliteManager è in grado di connettersi al DB mentre la mia app è in esecuzione e apportare modifiche ad esso. –

2

Alex Pechnikov ha un programma di replica di database SQLite multi-master sqlite3-rdiff. Probabilmente è eccessivo per ciò che stai cercando di realizzare, ma potrebbe essere più semplice della replica dei file.

SQLite ha anche un Online Backup API; c'è un esempio in quella pagina: Esempio 2: Backup online di un database in esecuzione.

+0

Non riesco a pensare a come potrei usarlo automaticamente. sqlite3-rdiff richiede Tcl e usare l'API di backup significa fare una copia dell'intero DB dopo ogni modifica. –

+0

Non DropBox fa una copia (o un rdiff) del DB dopo ogni modifica? Se è così, una copia locale non è molto overhead. In caso contrario, eseguire la copia locale solo come DropBox ne ha bisogno. –