Skip to content

Commit

Permalink
implemented backup functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
ghaering committed Oct 26, 2010
1 parent 2be0aea commit 7434848
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 1 deletion.
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -37,7 +37,7 @@

sources = ["src/module.c", "src/connection.c", "src/cursor.c", "src/cache.c",
"src/microprotocols.c", "src/prepare_protocol.c", "src/statement.c",
"src/util.c", "src/row.c"]
"src/util.c", "src/row.c", "src/backup.c"]

include_dirs = []
library_dirs = []
Expand Down
134 changes: 134 additions & 0 deletions src/backup.c
@@ -0,0 +1,134 @@
/* backup.c - the backup type
*
* Copyright (C) 2010 Gerhard Häring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

#include "module.h"
#include "backup.h"
#include "sqlitecompat.h"

void pysqlite_backup_dealloc(pysqlite_Backup* self)
{
int rc;

if (self->backup) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_backup_finish(self->backup);
Py_END_ALLOW_THREADS

Py_DECREF(self->source_con);
Py_DECREF(self->dest_con);

self->backup = NULL;
}

Py_TYPE(self)->tp_free((PyObject*)self);
}

PyObject* pysqlite_backup_step(pysqlite_Backup* self, PyObject* args, PyObject* kwargs)
{
int npages;

if (!PyArg_ParseTuple(args, "i", &npages)) {
return NULL;
}

int rc = sqlite3_backup_step(self->backup, npages);

if (rc == SQLITE_DONE) {
Py_RETURN_TRUE;
} else if (rc == SQLITE_OK) {
Py_RETURN_FALSE;
} else {
PyErr_SetString(pysqlite_OperationalError, sqlite3_errmsg(self->source_con->db));
return NULL;
}
}

static PyObject* pysqlite_backup_get_remaining(pysqlite_Backup* self, void* unused)
{
return Py_BuildValue("i", sqlite3_backup_remaining(self->backup));
}

static PyObject* pysqlite_backup_get_pagecount(pysqlite_Backup* self, void* unused)
{
return Py_BuildValue("i", sqlite3_backup_remaining(self->backup));
}

static PyGetSetDef pysqlite_backup_getset[] = {
{"remaining", (getter)pysqlite_backup_get_remaining, (setter)0},
{"pagecount", (getter)pysqlite_backup_get_pagecount, (setter)0},
{NULL}
};

static PyMethodDef pysqlite_backup_methods[] = {
{"step", (PyCFunction)pysqlite_backup_step, METH_VARARGS,
PyDoc_STR("Copy pages to backup database.")},
{NULL, NULL}
};

PyTypeObject pysqlite_BackupType = {
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME ".Backup", /* tp_name */
sizeof(pysqlite_Backup), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pysqlite_backup_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
pysqlite_backup_methods, /* tp_methods */
0, /* tp_members */
pysqlite_backup_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0 /* tp_free */
};

extern int pysqlite_backup_setup_types(void)
{
pysqlite_BackupType.tp_new = PyType_GenericNew;
return PyType_Ready(&pysqlite_BackupType);
}
43 changes: 43 additions & 0 deletions src/backup.h
@@ -0,0 +1,43 @@
/* backup.h - definitions for the backup type
*
* Copyright (C) 2010 Gerhard Häring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

#ifndef PYSQLITE_BACKUP_H
#define PYSQLITE_BACKUP_H
#include "Python.h"

#include "sqlite3.h"
#include "connection.h"

typedef struct
{
PyObject_HEAD
sqlite3_backup* backup;
pysqlite_Connection* source_con;
pysqlite_Connection* dest_con;
} pysqlite_Backup;

extern PyTypeObject pysqlite_BackupType;

int pysqlite_backup_setup_types(void);

#endif
36 changes: 36 additions & 0 deletions src/connection.c
Expand Up @@ -21,6 +21,7 @@
* 3. This notice may not be removed or altered from any source distribution.
*/

#include "backup.h"
#include "cache.h"
#include "module.h"
#include "connection.h"
Expand Down Expand Up @@ -351,6 +352,39 @@ PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args,
return cursor;
}

PyObject* pysqlite_connection_backup(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
{
static char *kwlist[] = {"dest_db", "source_name", "dest_db_name", NULL, NULL};
char* source_name;
char* dest_name;
pysqlite_Connection* dest_con;
pysqlite_Backup* backup;

if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!ss", kwlist,
&pysqlite_ConnectionType, &dest_con, &source_name, &dest_name)) {
return NULL;
}

if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
}

backup = PyObject_New(pysqlite_Backup, &pysqlite_BackupType);
if (!backup) {
return NULL;
}

Py_INCREF(self);
backup->source_con = self;

Py_INCREF(dest_con);
backup->dest_con = dest_con;

backup->backup = sqlite3_backup_init(dest_con->db, dest_name, self->db, source_name);

return (PyObject*)backup;
}

PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args)
{
PyObject* ret;
Expand Down Expand Up @@ -1554,6 +1588,8 @@ static PyGetSetDef connection_getset[] = {
};

static PyMethodDef connection_methods[] = {
{"backup", (PyCFunction)pysqlite_connection_backup, METH_VARARGS|METH_KEYWORDS,
PyDoc_STR("Backup database.")},
{"cursor", (PyCFunction)pysqlite_connection_cursor, METH_VARARGS|METH_KEYWORDS,
PyDoc_STR("Return a cursor for the connection.")},
{"close", (PyCFunction)pysqlite_connection_close, METH_NOARGS,
Expand Down
2 changes: 2 additions & 0 deletions src/module.c
Expand Up @@ -24,6 +24,7 @@
#include "connection.h"
#include "statement.h"
#include "cursor.h"
#include "backup.h"
#include "cache.h"
#include "prepare_protocol.h"
#include "microprotocols.h"
Expand Down Expand Up @@ -314,6 +315,7 @@ PyMODINIT_FUNC init_sqlite(void)
(pysqlite_connection_setup_types() < 0) ||
(pysqlite_cache_setup_types() < 0) ||
(pysqlite_statement_setup_types() < 0) ||
(pysqlite_backup_setup_types() < 0) ||
(pysqlite_prepare_protocol_setup_types() < 0)
) {
return;
Expand Down

0 comments on commit 7434848

Please sign in to comment.