2010-03-12 4 views
5

Ich entwickle eine App in Visual C++, die eine SQLite3 DB zum Speichern von Daten verwendet. Normalerweise sitzt es die meiste Zeit im Tablett.SQLite-Datei sperren und DropBox

Ich möchte auch ermöglichen, meine App in einen DropBox-Ordner zu setzen, um es über mehrere PCs zu teilen. Es funktionierte wirklich gut, bis DropBox sich kürzlich aktualisiert hat. Und jetzt heißt es, dass es "die verwendete Datei nicht synchronisieren kann". Die SQLite-Datei ist in meiner App geöffnet, die Sperre ist jedoch freigegeben. Es gibt einige vorbereitete Anweisungen, aber alle werden unmittelbar nach der Verwendung von step zurückgesetzt.

Gibt es eine Möglichkeit, die Synchronisierung einer geöffneten SQLite-Datenbankdatei zu aktivieren? Vielen Dank!

Hier ist die einfache Wrapper, die ich nur zum Testen verwenden (keine Fehlerbehandlung), falls dies hilft:

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: versucht, alle Anrufe zu LockFile kommentieren und LockFileEx in sqlite3.c - Das gleiche Ergebnis.

UPD2: Versucht, sqlite3_close im Leerlauf (wie Proof of Concept) aufzurufen - immer noch das gleiche Ergebnis! Filemon teilt mit, dass die Datei immer noch nicht geschlossen, sondern nur entsperrt ist.

UPD3: Autocommit-Modus ist aktiviert. Die Anzahl der BEGINs und COMMITs stimmt überein (Klasse Transaktion und RAII kümmern sich darum). SQliteManager kann sich mit der Datenbank verbinden, während meine App läuft, und Änderungen daran vornehmen.

+1

Überprüfen Sie das Ergebnis von sqlite3_close()? Vielleicht funktioniert es nicht, weil Sie nicht alle vorbereiteten Aussagen abgeschlossen haben. –

+0

Das war es! Es funktionierte nicht wegen einer laufenden Hintergrundsicherung. Dummer Fehler .. Danke! Setzen Sie es als Antwort und ich werde es akzeptieren. –

Antwort

4

Überprüfung des Ergebnisses von sqlite3_close(). Vielleicht funktioniert es nicht, weil Sie nicht alle vorbereiteten Aussagen abgeschlossen haben.

2

Welches Dateisystem verwenden Sie?

Sind Sie sicher, dass Autocommit aktiviert ist und/oder dass Sie Ihre Aussagen bestätigen? Ich erinnere mich daran, dass ich ein Problem hatte, dass ich nicht beging, und das Schloss würde weitermachen.

+0

NTFS. Gute Idee zum Begehen, danke, ich werde prüfen, ob das der Fall ist. –

+0

Autocommit-Modus ist aktiviert. Die Anzahl der BEGINs und COMMITs stimmt überein (Klasse Transaktion und RAII kümmern sich darum). Scheint, das ist nicht der Grund. SQliteManager kann sich mit der Datenbank verbinden, während meine App läuft, und Änderungen daran vornehmen. –

2

Alex Pechnikov hat ein Multi-Master-SQLite-Datenbankreplikationsprogramm sqlite3-rdiff. Es ist wahrscheinlich zu viel für das, was Sie erreichen möchten, aber es kann einfacher als Dateireplikation sein.

SQLite hat auch eine Online Backup API; Es gibt ein Beispiel auf dieser Seite: Beispiel 2: Online-Backup einer laufenden Datenbank.

+0

Ich kann mir keinen Weg vorstellen, wie ich das automatisch nutzen könnte. sqlite3-rdiff benötigt Tcl, und die Verwendung der Backup-API bedeutet, dass nach jeder Änderung eine Kopie der gesamten Datenbank erstellt wird. –

+0

Erstellt DropBox nicht nach jeder Änderung eine Kopie (oder einen rdiff) der Datenbank? Wenn ja, ist eine lokale Kopie nicht viel Aufwand. Wenn nicht, dann nur die lokale Kopie so oft wie DropBox es benötigt. –